HARDADFU
From S1MP3 Wiki
HARDADFU is the component in the BROM, a part of the BLOD, which is the ADFU protocol handler. Unlike SOFTADFU, HARDADFU mode only recognizes two commands: TRANSFER and EXECUTE. However, these commands are more than powerful enough to perform the operations required, as one can upload and execute any code on the device in this primitive mode, such as a more fully-featured ADFU server, s1giveio, or a diagnostics/device autodetection code to discover the configuration of and recover bricked devices --- the possibilities are endless even with such a primitive "bootstrap" ADFU mode.
Note: The following code and description were taken from the BROM of an ATJ2093H dated 2005-12-40(?). There may be minor differences between it and that of your device, most notably in the area of USB support.
It is copied by BLOD to 0000 and a jp 0000 is made to initiate the ADFU mode. The following is a reader's guide to the HARDADFU. The full code (only partially commented) is here
0000-0BFF: HARDADFU
The actual HARDADFU code proper (3KB) is located in this region.
0000-0003: Jump to ADFU code and Padding
It's not clear why the BLOD doesn't jump to 0200 directly, similar to how it invokes FLASHLDR.
0038-006F: RST38 Interrupt Handler
Since the BLOD initializes the CPU into interrupt mode 1, all interrupts will result in this handler getting executed. Port 26 is examined to determine which subsystem caused the interrupt, and the appropriate handler is invoked. The handler address for USB interrupts is changed by the ADFU setup code to point to the real USB interrupt handler; the version referred to here is a placeholder.
0071-00FF: ADFU stack
143 bytes of stack space for the ADFU code. It's more than enough.
0100-0127: Global Variables
Variables relating to the ADFU code and USB status.
0128-01FF: Padding
Another 216 bytes of it.
0200-0250: Clock Initialization and Wait
Various clock registers are setup and the CPU is switched into low-speed (32KHz) mode. Then a busy-wait loop is executed which waits for the device to be plugged in. Once this event occurs, the CPU is switched to the regular 24MHz HOSC clock and the ADFU routine is called.
0253-0287: ADFU Main Loop
The USB controller is setup and another busy-wait loop is entered, which polls two flags, reset_flag and execute_flag, to see if the interrupt-driven USB routine has set them. They correspond to the action of resetting the device and executing code, respectively. Note that the execute command is called with the equivalent of a jump, i.e. there is no provision for return unless the execute code returns explicitly to the address of the ADFU main loop.
0288-0326: USB Setup
This code resets the two flags mentioned above, installs the USB ISR by writing its address to the main ISR decision routine, calibrates the USB internal resistors and initializes the USB controller in a state where only endpoint 0 is enabled.
0327-0355: USB ISR Main
When a USB interrupt occurs, control is transferred to this code by the main ISR. Four separate interrupts are checked for and the appropriate routine is invoked accordingly:
- Endpoint A interrupt
- Setup packet interrupt
- Root port reset
- Connect/disconnect interrupt
0356-0389: Root Port Reset
Handler for a root port reset event. The interrupt is acknowledged and endpoint 0 is partially reinitialized in response.
038A-039B: Connect/Disconnect Interrupt
A plugging-in event is ignored, but an unplugging event results in the reset flag being set; once the USB ISR returns, the main ADFU loop will then execute the code to reset the device (loop indefinitely until the watchdog performs the reset).
039C-03A5: Setup Packet Interrupt
When a setup packet is received, the somewhat lengthy routine do_setup_pkt is called after the interrupt is acknowledged.
03A6-03D8: Endpoint A Interrupt
Here is where the "command processor" is. The Command Block Wrapper's signature is checked (see USB MS spec), followed by the command field itself. If neither are valid, the routine enters an infinite loop until the watchdog resets. Otherwise, the appropriate command processing code is invoked. Only two commands are supported, 05 and 10.
03D9-03E3: flush_epB_resume
Flushes endpoint B's FIFO and returns from the interrupt. The location of this code is somewhat of a mystery, as it is not used until much further onwards.
03E4-03E5: Infinite Loop
The destination for control flow when the main command processor cannot validate the command.
03E6-0701: Setup Packet Procedure
A somewhat lengthy and repetitive block of code that handles the standard USB device requests (see Chapter 9 of the USB spec). For more details, see the code; the comments are self-explanatory.
0702-071D: Transfer Size Calculation
Calculates the actual number of bytes that are to be send/received during ADFU transfer commands.
071E-076D: Endpoint 0 Send
Used by the setup packet procedure, the code in this region writes the data to the endpoint 0 FIFO, validates the endpoint, and waits until the data is sent.
076E-08AE: Command 05 Processing
Command 05 is the transfer command of HARDADFU mode. Data may be written to or read from any address within the device using this command.
076E-0787: Set Parameters
The transfer command's SCSI command block has the following format:
cmd db 5 ; HARDADFU TRANSFER command dir db ? ; direction of transfer: 00-7F = OUT (to device), 80-FF = IN (from device) addr dw ? ; memory address to use unu0 dw ? ; unused byt1 db ? ; saved in global variables but otherwise unused len dw ? ; length of transfer
The address, length, and byt1 are saved in global variables, and flow branches to the upload/download code depending on the value of bit 7 of dir.
0788-083C: Download
Downloads (transfers from host to device) data through endpoint A (OUT) in blocks of up to 3KB. After the download is complete, a CSW is sent via endpoint B to acknowledge the request.
083D-08AE: Upload
Uploads (transfers from device to host) data through endpoint B (IN) in blocks of up to 3KB. After the upload is complete, a CSW is sent via endpoint B to acknowledge the request.
08AF-0903: Command 10 Processing
Command 10 is the execute command of HARDADFU mode. The SCSI command block has the following format for this command:
cmd db 16 ; HARDADFU EXECUTE command addr dw ? ; address to execute
The address is saved in the global variables, the execute flag is set and the command is acknowledged by sending a CSW through endpoint A. After the USB ISR returns, the set execute_flag causes the main ADFU loop to jump to the specified execution address.
0904-0908: Unused Delay Loop
A delay loop of 8 djnz units which may be left over from an earlier version, but never used in this code.
0909-09C4: USB Descriptors
Descriptors for the USB device, returned through setup packet requests. See the USB spec for more information on the contents of the data in these descriptors.
0909-091A: HS Device
The USB 2.0 device is identified as having VID:PID of 10D6:FF61 and 1 configuration.
091B-093A: HS Config
One interface with two endpoints is defined:
- Endpoint 1 -- OUT, data, nonsync, bulk, max 512 bytes packets
- Endpoint 2 -- IN, data, nonsync, bulk, max 512 bytes packets
093B-0944: HS Device Qualifier
USB 2.0, 1 configuration.
0945-0964: HS Otherspeed
Same as the HS config descriptor with exception of max 64 bytes packet size.
0965-0976: FS Device
Identical to HS Device descriptor
0977-0996: FS Config
Identical to HS Config descriptor with exception of max 64 bytes packet size.
0997-09A0: FS Device Qualifier
Same as HS Device Qualifier
09A1-09C0: FS Otherspeed
Identical to HS Config descriptor
09C1-09C4: String
No actual strings, only 1 entry of LANGID 0x409.
09C5-09EC: Default ISRs
Default ISRS for the interrupts processed by the main interrupt handler at 0038. All of them perform no other action than acknowledging the interrupt.
- 09C5-09C9: Touch panel ADC
- 09CA-09CE: Key Scan
- 09CF-09D3: RTC
- 09D4-09D8: DMA/CTC
- 09D9-09DD: I2S/SPI
- 09DE-09E2: USB (unused, replaced by handler above at 0327)
- 09E3-09E7: UART
- 09E8-09EC: DSP
09ED-0BFF: Padding
Another 531 bytes unused. The ADFU server code is similarly as unefficient as FLASHLDR; it could probably be reduced to 2.5 or even 2KB.
4000-60FF: ZRAM2 and USB memory
This area is used by HARDADFU for USB transfers.
4000-57FF: ZRAM2
6KB buffer for receiving/sending data through endpoints A and B via DMA6 (USBDMA).
5800-60FF: URAM
2KB+256 buffer for received commands and control packets.