1BL (Bootrom)
Buried deep inside the CPU die, this ~32kb of ROM code is responsible for reading the 2BL from NAND-flash and decrypts it into the embedded SRAM in the CPU. It verifies the hash of the decrypted image with a signed block at the beginning of the 2BL, and will stop execution if this hash mismatches. This code also contains a number of test functions, which can be activated by pulling the 5 "POST IN"-pins, which are available on the backside of the PCB. None of these tests looks particulary interesting (from an exploitation perspective) - they mostly seem to be related to the FSB (the bus between CPU and GPU). This code is fixed, and all systems use identical code here.
2BL ("CB")
This code is usually located at 0x8000 in NAND flash. It's decrypted by 1BL, and runs from internal SRAM.
It does a basic hardware initialization, and contains the "fuse check code", which verifies the "2BL version". The fuses store the expected version. The 2BL stores a "Version" and a "AllowedMask" (=bitfield), and this is usually stored at address 0x3B1 / 0x3B2..0x3B3.
Xenon Zephyr Falcon Jasper
2 0003 1888, 1901, 1902
4 1920 "new zeropair code"
5 0010 1921 4558 5760,5761,5770 6712 TA-fixed
It then verifies the pairing information stored in the 2BL header. Part of this verification is a checksum check of the NAND area which was used to load the SMC code from.
It also contains a virtual machine and some code to run on this machine. The virtual machine code, which is pretty complicated, does the following things:
Initialisation of the PCI-Bridge
Disable the GPU PCIE JTAG test port
initialize the serial port
talk to the SMC to clear the "handshake"-bit
initialize memory
hopefully not: generate RROD if memory init fails
After that, the external (512MB) memory will be initialized and usable. 2BL then decrypts the 4BL into this memory. Memory encryption will already be enabled - no executable code is *ever* written unencrypted.
4BL ("CD")
This code is responsible for checking and unpacking 5BL, as well as applying update patches. First, the fuses are read to determine the console "Update Sequence", a number which basically counts the number of updates installed. Since updates are, in the same way as 2BL, paired to a console, this allows to configure the console in a way that no old update will be used. So each update slot stores the maximum value of burned fuses (well, essentially the exact value). The base kernel also has an associated value, usually zero, but this can be changed in the 2BL pairing data block. This is what the timing-attack increments, in order to revert to the 1888 kernel.
5BL ("HV/Kernel")
The HV and kernel are merged into a single image, which is compressed with a proprietary algorithm (LDIC).
6BL ("CF"), 7BL ("CG")
This is part of a system upgrade. Each console has a so-called "Base Kernel", which is the 1888 kernel which was available on launch back in 2005. Then there are two "update slots" - areas of 64k each (128k on Jasper), which contain a 6BL and 7BL. 6BL is code which applies the update, using a clever delta-compression. 7BL is the actual delta-compressed update, essentially a binary diff.
Oh, updates are >64k. So only the first 64k are actually stored in the update slots, the rest is stored in the filesystem as a special file. Since 6BL doesn't contain a filesystem parser, a blockmap is added in 6BL which points to the sectors which contain the rest of the update.
Segnalibri