Well, I started this thread to uncover the hidden bootstrap code.
What's the Bootstrap?
It's a piece of executable code designed by the HDD vendor which runs inside the MCU (micro-controller the brain of your HDD's PCB), immediately after power-up the unit. It's a kind of boot-loader for windows. Basically, in a working HDD, it reads the rom flash image, and executes a portion of code described in a table at the very beginning of the flash.bin (rom image).
If you dump your PCB's flash image (ex using WDR tool) and open it in a hex editor (ex HxD) you'll notice a sort of table at the beginning, with a row length of 32 bytes.
The approximate description is here:
Code:
typedef struct 32ByteBlockBiosHeader
{
byte ID; //[Byte 00] Header ID 0x5A it's called "kernel loader"...it loads and unpacks all the others...being executed by the MCU's bootstrap?
byte type; //[Byte 01]?? 1,3 compressed?
short decomp_sizeH; //[Bytes 02:03] higher 16bit of the decompressed size ??
int block_Size; //Directory Size + 1 checksum byte
int block_size; //Directory Size without checksum byte
int block_start; //The offset in this file where dir starts
int block_addr; //Mem addr Where the MCU's Bootstarp or the "kernel loader" (0x5a = first block-not compressed) loads and unpack the data
int entry_point; //The EP for this directosy. Gets called if needs exec. if this is -1 won't be executed;
byte UNK4[4]; //01 0A 00 00
short decomp_sizeL; //lower 16bit of the decompressed size
byte pad;
byte CKS; //checksum is calculated over all buffer but the crc byte
}32ByteBlockBiosHeader;
The ID of the first row it's 0x5A...we name-it "Kernel Loader". Basically, the Bootstrap maps the first entry in that table at the memory address vir_addr, then executes the entry_point.
But what if we have a defective PCB, with an incorrect rom image? (First, I must mention that in this situation, the HDD won't be seen by any software tool which communicates with the device using ATA commands. This means that the firmware must be in a certain degree of integrity.) The Bootloader will enter in another mode in which, it will accept data injection through a xmodem communication interface. AKA Windows terminal ...with some wires between COM and PCB
I have dumped my Bootstrap image using a tool made my myself (which uses VSC) Otherwise you could use a
JTAG debugger to do the dump...If you manage to solder those wires
Usually, on ARM MCU's the Bootstrap code it's mapped in memory at 0xFFFF0000 offset and it's small ...around 1000bytes on my PCB.
My PCB has stamped 2060-701336-003 REV A it's a 2005 WD 200Gb model. At this moment my PCB identifies as a WDC ROM..because I could bet it has the pre-amp dead. Another tip is that in this situation, you could use the PCB detached from the HDD, connected to PC, if you want to play with it, without putting another stress on the platter and internal stuff.
SO, As I said, the Bootstrap enters in a mode...in which accepts receiving data through a serial interface. To enter in this mode, some physical connections must be made. WD has on all PCB's (I believe) a CON1 connector. It's used perhaps for factory firmware upload/tests, and there I assume they have the links and what they need to put the bootstrap to factory mode.
However,
some Chinese guys have found the link which enables the injection. I will concentrate on how the "terminal" function inside the Bootloader, works.
The functions implements a basic code which handles x-modem protocol. It sends 0x15 byte (NAK), waiting to receive data on serial port. It reads constantly to see if someone sends some data. If yes, then analyzes that data and take proper actions.
The injected data is sent as 128bytes packet with prefix consisting of a simple 3-byte header containing a
<SOH> command character (0x01), a "block number" from 0-255, and the "inverse" block number-255 minus the block number
X-Modem <soh> 01 FE -data[128]-CRC. The "terminal", verifies if the data it's ok, responding with an ACK (0x6) or NAK for errors. For the first block, it maps the first 32 bits of the header described upper (yes, injected data must own a header) to some local variables, and keeps track of the Entry_point, maps the executable block to it's memory address from header, checks CRC etc. then wait for another packet.
If it receives <EOT> end of transmission, respond with ACK and executes the Injected code's Entry_point.
The headers members which count when injecting data, are the block_start, block_addr, entry_point, because the code will be executed and active as long as the RAM is powered..
I have attached my Bootstrap dump as an
.ida project (nice graphs), with the terminal code reversed inside. I mention that The analysis it's made only statically, I haven't used any debugger.