234 lines
12 KiB
Text
234 lines
12 KiB
Text
FriiDump Techincal info
|
|
===============================================================================
|
|
|
|
This document is a reworking and unification of information found all over the
|
|
net, regarding the structure of Nintendo Gamecube/Wii Optical Discs and how to
|
|
read them on an ordinary DVD-ROM drive. All the due credits can be found in the
|
|
AUTHORS file.
|
|
|
|
|
|
===============================================================================
|
|
Nintendo Gamecube/Wii Optical Disc (GOD/WOD) structure
|
|
===============================================================================
|
|
|
|
In order to understand how a Gamecube or WII Optical Disk is made, let us
|
|
first take a look at a standard DVD-ROM. The complete standard is explained in
|
|
the ECMA-267 Standard.
|
|
|
|
The user data stored on the DVD is divided in blocks, each 2048 bytes long.
|
|
Each 2048-byte block is then encapsulated in a 2064-byte structure, adding some
|
|
other data needed for error-correction and head positioning. A 2064-byte block
|
|
is called a "Data frame", and its logical layout is as follows:
|
|
|
|
4bytes 2bytes 6bytes 2048bytes 4bytes
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
| ID | IED | CPR_MAI | User Data Frame | EDC |
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
- Identification Data (ID): Contains the PSN (Physical Sector Number), info
|
|
about the sector itself, like the layer, reflectivity, zone, etc.
|
|
- ID Error Detection Code (IED)
|
|
- Copyright Management Information (CPR_MAI): Its use is application-specific,
|
|
for instance it can be used to store a sector key in videos that use CSS, or
|
|
a scrambling key in the XBox and XBox360 Security Sectors.
|
|
- User Data: This is the data available for the end user.
|
|
- Error Detection Code (EDC): It is the checksum data for all the fields above,
|
|
its polinomial is x^32 + x^31 + x^4 + 1.
|
|
|
|
For various reasons (not related to copy protection), the User Data Frame is
|
|
XOR'ed with a stream cipher generated by an 15bits LFSR (Linear Feedback Shift
|
|
Register), with bits 10 and 14 used as taps. The seeds are obtained from a
|
|
table of the ECMA-267 standard, the index of the seed is the 4 MSB of the last
|
|
byte of the "ID" field of the Data Frame. The same stream cipher is then used
|
|
by 16 consecutive Data Frames: for this and other reasons (again related to
|
|
error correction), data from the DVD are always read in 16-data frame blocks.
|
|
|
|
4bytes 2bytes 6bytes 2048bytes 4bytes
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
| ID | IED | CPR_MAI | User Data Frame | EDC |
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
^ | 2048bytes cipher stream |
|
|
^ - - - - - - - - - -
|
|
Scrambling
|
|
seed index
|
|
|
|
Now, the first problem when dealing with Gamecube/Wii Optical Discs is that
|
|
they use a different (and yet unknown) set of seeds. This means that when an
|
|
ordinary DVD-ROM drive tries to read a GOD/WOD disc, it will unscramble the
|
|
User Data Frame with the wrong seed, causing the EDC check to fail and a read
|
|
error to be reported to the operating system, which means the inability to read
|
|
the disc.
|
|
|
|
Furthermore, Gamecube/Wii Optical Disks use a slightly different structure for
|
|
the Data Frame, as shown in the following figure:
|
|
|
|
4bytes 2bytes 2048bytes 6bytes 4bytes
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
| ID | IED | User Data Frame | CPR_MAI | EDC |
|
|
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
| 2048bytes cipher stream |
|
|
- - - - - - - - - -
|
|
|
|
Basically, the User Data Frame and the CPR_MAI fields are swapped, while the
|
|
scrambled bytes remain the same.
|
|
|
|
|
|
===============================================================================
|
|
Tricks used to read a GOD/WOD on a standard DVD-ROM drive.
|
|
===============================================================================
|
|
To cope with the above-mentioned problems, some methods have been suggested by
|
|
many people on the net. They vary in performance, but the basic idea is always
|
|
the same:
|
|
|
|
1. Issue a read command for the sector of interest (this is actually a
|
|
16-sector block, not a single sector, as stated above).
|
|
2. Let the read return failure.
|
|
3. At this moment, the DVD-ROM drive must have cached the data read from the
|
|
disc somewhere in its internal memory, to be able to unscramble them and to
|
|
check the EDC. So, we can dump the data from the drive's internal RAM.
|
|
|
|
Unfortunately, this is not as easy as it seems, due to the fact that there is
|
|
no standard "Dump drive memory" command. This is probably implemented in many
|
|
drives for firmware debugging purposes, but, as such, it is a vendor-specific
|
|
command, which are usually undocumented and vary from vendor to vendor (or even
|
|
from drive model to drive model).
|
|
|
|
This is where the work that many hackers around the world have done, in order
|
|
to crack the Microsoft XBox360 console, becomes useful. They needed some way to
|
|
read and write data to the XBox360 drive's internal memory, so they
|
|
disassembled the drive's firmware and patiently tried to understand what each
|
|
of the vendor-specific commands did. This way, they discovered that a certain
|
|
command could be used to read an arbitrary portion of the drive's internal RAM.
|
|
They also managed to map the RAM addresses, so that it is known where data
|
|
read from the disc are temporarily stored.
|
|
|
|
Fortunately, the XBox360 drive is not too different from some retail DVD-ROM
|
|
drives, namely some models from LG, which means that the discovered command
|
|
works on them as well. Hence, we now have some sort of access to the disc data.
|
|
|
|
Although, this comes at the price of speed: dumping the drive's internal memory
|
|
is a slow process, as it uses Programmed I/O (PIO) instead of Direct Memory
|
|
Access (DMA) to transfer data from the drive to the computer's memory. For this
|
|
reason, some have proposed the use of the "streaming read" command: it is a
|
|
standard command thought for those applications where the constant flow of data
|
|
is more important than its absolute correctness, such as audio or video
|
|
applications. Thus, this command does not perform the EDC on the data read from
|
|
the disc, but returns it immediately. Anyway, the command will only return the
|
|
User Data Frame, which means that only a portion of the data will be read this
|
|
way, while the rest (i.e.: the first 12 and the last 4 bytes) will have to be
|
|
read using the memory dump method. Nevertheless, this combined method will be
|
|
faster overall, as only some dozens of bytes have to be transfered through PIO,
|
|
instead of the whole sectors.
|
|
|
|
We still have to cope with the unknown seeds. This problem can be easily solved
|
|
through the use of brute force: as there are only 15 bits to try (and commonly
|
|
only 17 seeds per GOD/WOD), this approach only takes about 30 seconds. The
|
|
bruteforce process is very simple: the LFSR is seeded from 0 to 7FFFh and for
|
|
each seed the corresponding stream cipher is generated and XOR'ed with the
|
|
proper section of the Data Frame and the EDC is computed. If the EDC is the same
|
|
as the one in the EDC field then we have the correct seed.
|
|
|
|
|
|
===============================================================================
|
|
The FriiDump approach
|
|
===============================================================================
|
|
FriiDump can use four different disc dump methods. They have been developed
|
|
gradually, empirically and heuristically, by experimenting with the PLScsi tool
|
|
and comparing the retrieved data with a known-good dump. In this section the
|
|
inner working of every dump method will be described. The code implementing the
|
|
different methods can be found in the "disc_read_sector_X" functions of disc.c.
|
|
|
|
Please note that the desibed behaviour is that of my LG GDR8164B drive, which I
|
|
assume to be shared by similar drives. Other, more different drives, might
|
|
behave differently and require totally different methods.
|
|
|
|
Also note that all of the methods read 16-sector blocks.
|
|
|
|
|
|
Method 1
|
|
|
|
This method is very slow. So slow that I have never dumped a whole disc with
|
|
it. Although, it served me to prove that I was going in the right direction and
|
|
that my efforts could eventually come to a working end. It also showed me that
|
|
the first versions of RawDump create bad dumps, sometimes.
|
|
|
|
Basically this method is the same used by those early versions of RawDump,
|
|
which took 50+ hours to dump a whole disc. It works like this:
|
|
|
|
1. Issue a read command for the required sector. This will cause the 16-sector
|
|
block to which the sector belongs to be placed at the beginning of the
|
|
drive's cache memory. Do not even bother to see what the read command
|
|
returns, as it will surely be a data read error.
|
|
2. Dump the 16-sector block.
|
|
|
|
|
|
Method 2
|
|
|
|
Method 2 is similar to method 1, but uses the above-mentioned "streaming read"
|
|
method, which somehow allows us to dump 5 blocks at a time.
|
|
|
|
1. Issue a "streaming read" command for the required sector. This will cause
|
|
the 16-sector block to which the sector belongs to be placed at the
|
|
beginning of the drive's cache memory, together with the 4 following
|
|
16-sector blocks. Do not bother to see what the read command returns.
|
|
2. Dump the 5 16-sector blocks.
|
|
|
|
|
|
Method 3
|
|
|
|
This is similar to the previous method, but instead of dumping the whole
|
|
sectors from memory, it uses the (not EDC checked) data returned by the
|
|
"streaming read" command. and completes it dumping only the missing bits from
|
|
memory.
|
|
|
|
1. Issue a "streaming read" command for the required sector. This will cause
|
|
the 16-sector block to which the sector belongs to be placed at the
|
|
beginning of the drive's cache memory, together with the 4 following
|
|
16-sector blocks.
|
|
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
|
|
- Dump 12 bytes from memory.
|
|
- Use 2048 bytes returned by the read command.
|
|
- Dump 4 more bytes from memory.
|
|
|
|
Note that this method has a small issue, as sometimes the beginning of the
|
|
cache will be dirty and contain invalid data, needing the sector to be read
|
|
again. As this seems to happen quite often, we always read a dummy sector
|
|
before the requested sector.
|
|
|
|
|
|
Method 4
|
|
|
|
Method 4 is just method 3 with a trick to use a single dump command for every
|
|
sector that has to be reconstructed, instead of two. It is the faster dump
|
|
method currently supported and, as such, the default one.
|
|
|
|
1. Issue a "streaming read" command for the required sector. This will cause
|
|
the 16-sector block to which the sector belongs to be placed at the
|
|
beginning of the drive's cache memory, together with the 4 following
|
|
16-sector blocks.
|
|
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
|
|
- If this is the first sector of a block, dump 12 bytes from memory.
|
|
Otherwise, use the last 12 bytes of the preceding dump.
|
|
- Use 2048 bytes returned by the read command.
|
|
- Dump 16 bytes from memory, and use the first 4. This leaves 12 bytes to be
|
|
used for the reconstruction of the next sector.
|
|
|
|
Note that the issue of method 3 applies to this method, too.
|
|
|
|
|
|
===============================================================================
|
|
How to add support for a new drive
|
|
===============================================================================
|
|
If you read all the above stuff, it should be clear that, in order to add
|
|
support for a new DVD-ROM drive, all that is needed is a way to dump the
|
|
drive's internal memory, in particular the portion where the data read from the
|
|
disc is cached. As explained above, this function might not be present in all
|
|
drives, and might not be easy to find or to use. In case you manage to discover
|
|
it, just copy the file "hitachi.c" to a new one, and modify it opportunely.
|
|
|
|
Some modifications will also be needed in "dvd_drive.c", in order to add
|
|
autodetection for the new drive, in the "dvd_assign_functions" function.
|
|
|
|
Apart from this, the cache behaviour of the new drive might not be the same
|
|
as that of the currently supported models, so the program architecture might
|
|
need radical changes. In this case, please report.
|