FLASHLDR
From S1MP3 Wiki
FLASHLDR is the component in the BROM, a part of the BLOD, which is responsible for loading the BREC from NAND flash.
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 flash support.
It is copied by BLOD to 0400 and a call 0403 is made to initiate the loading process. The following is a reader's guide to the FLASHLDR. The full code (only partially commented) is here.
When the BLOD transfers control to it, the machine state is as follows:
a = aa (presumably low two bits of watchdog register retain values) bc = 0000 de = 1200 hl = 8500 sp = 1ffe (initially 2000, return address pushed by call) CPU is running at full speed (24MHz).
0400-0402: Variables
0400 flashtype db 0 ; holds the detected flash type 0401 read_retry_count db 0 0402 read_retry_stat db 0 ; notes whether ECC or RS correction was used
Flash types:
- 00 -- 16K+512 small-block
- 01 -- 128K+4K large-block
- 02 -- 32K+1K small-block
- 10 -- 4K+128 "small"-block (see below)
- 20 -- 256K+8K large-block
0403-0469: Select and Initialize Flash
Initializes the flash controller, selects the first flash chip (on CE1), and attempts to do a reset followed by a wait-until-ready polling loop. If resetting the flash is unsuccessful, it attempts to verify the signature (55,AA,0F,F0) of an external ROM and tries booting from that. If neither is successful, the function returns 1.
046A-0676: Detect Flash Type
The flash type ID is read by a call to read_flash_id and a large compare-and-jump block of code (which could be written more compactly and efficiently, e.g. by using a table-lookup scheme) is used to determine the precise type of the flash. Eventually, all of the possible types are categorized into the following:
- Large-block flash, 128K blocksize
- Small-block flash, 16K blocksize
- Large-block flash, 256K blocksize
- Small-block flash, 4K blocksize (this is a weird one --- see below)
- Small-block flash, 32K blocksize
Unknown flash types are also accommodated by trying, in the above order, all the types above, until one succeeds (returns 0).
0677-0980: Load BREC
The code to load the BREC into IPMM for each of the 5 flash types above is located here. There is much duplication of code between the types, which could be made considerably more compact and efficient.
Error detection and correction is performed for each 512-byte read, using first the integrated Reed-Solomon (511,503) codec, then basic ECC (22 bits per 256 bytes) if RS fails. This enables this code, which is located in BROM and thus not easily changed, to accommodate both types of error correction.
After all 16KB of the BREC is loaded, in each of the 5 paths the verify_brec routine is called to verify the signature and checksum, and rereads/failure returns done as appropriate.
0677-071B: 256K large-block
The BREC is loaded into IPMM by 8 page reads, broken down into 4 512-byte sectors each. The page address is incremented by 120 after the final read, to point to the second block.
071C-07C0: 128K large-block
The BREC is loaded into IPMM by 8 page reads, broken down into 4 512-byte sectors each. The page address is incremented by 56 after the final read, to point to the second block.
07C1-0858: 32K small-block
The BREC is loaded into IPMM by 32 512-byte page reads. The page address is incremented by 32 after the final read, to point to the second block.
0859-08E5: 16K small-block
The BREC is loaded into IPMM by 32 512-byte page reads. There is no need to increment the page address afterwards, as the BREC fills one block exactly.
08E6-0980: 4K small-block
This path and the subroutines it calls handles a special case, an odd flash structure; the Renesas K29V1G91T and K29V2G74WT, having a 4K blocksize, would be considered small-block under the current classification scheme, except that it also has a 2K pagesize and uses the large-block command set. Thus, the code for this path has an 8x4x512 load loop like the large-block paths, but does not increment the page address since the BREC takes 4 blocks in this flash.
0981-09B7: BREC verification
Implementation of signature-checking and checksum algorithm as described in BREC checksum.
09B8-0E63: Page Read/Error Correction
This region consists of code to read pages from the various flash types, as well as perform error checking/correction.
09B8-0AA9: large-block read
Reads 512 bytes by issuing two commands, FB and FA (mapping to 00 and 30, presumably), then performs verification/correction using either RS or ECC depending on what was selected.
0AAA-0AF8: large-block ECC read
Reads 4 ECC bytes in order l,h,e,d (when calling 0AF1) or 2 ECC bytes in order l,h (when calling 0AAA) by sending raw flash commands 00 and 30 and reading from external memory area.
0AF9-0BBB: 32K small-block read
Reads 512 bytes by issuing command ED (probably mapping to 00/01), then performs verification/correction using either RS or ECC depending on what was selected.
0BBC-0C0D: 32K small-block ECC read
Reads 4 ECC bytes in order l,h,e,d (when calling 0C06) or 2 ECC bytes in order l,h (when calling 0BBC) by sending raw flash command 50 and reading from external memory area.
0C0E-0CD0: 16K small-block read
Identical to 32K small-block read.
0CD1-0D22: 16K small-block ECC read
Identical to 32K small-block ECC read.
0D23-0E14: 4K small-block read
Identical to large-block read.
0E15-0E63: 4K small-block ECC read
Identical to large-block ECC read.
0E64-0E9A: CE select
0E64-0E66: Saved Registers
Registers 01, 02, and 28 are saved here when CE is selected, and restored when CE is unselected.
save_reg_01 db 0 save_reg_02 db 0 save_reg_28 db 0
0E67-0E88: Select CE
This routine saves the registers specified above and enables the CE specified by b.
0E89-0E9A: Unselect CE
Restore the registers saved by select_CE, effectively setting CE to whatever it was before select_CE was called.
0E9B-0ED9: Flash Status
0E9B-0ECF: Get Flash Status
Returns, for the currently selected flash, 0, 1, 2, or 3 for ready, timeout, write-protected, or error, respectively.
0ED0-0ED9: Reset and Get Status
Issues reset command to flash controller before calling the above procedure.
0EDA-108B: Error Correction
The code in this section is responsible for detecting and correcting errors using either Reed-Solomon or standard ECC.
0EDA-0EE2: ECC temporary variables
Stores ECC bytes, data buffer address, and ECC XOR result bytes.
0EE3-0FA0: Correct data ECC
Corrects a block of 256 bytes using 11-bit ECC.
- l = ECC[6:3]
- h = ECC[10:7]
- e = ECC[2:0]
- a = buffer memory bank
- b = buffer high offset
- c = buffer low offset
0FA1-1032: Correct spare ECC
Corrects a block of 8 bytes (in the spare area) using 6-bit ECC.
- l = ECC[5:2]
- h = ECC[1:0]
- c = buffer low (non-banked offset)
- b = buffer high (non-banked offset)
1033-107A: Correct data RS
Uses integrated Reed-Solomon codec to perform error correction on up to 4 bytes.
- a = buffer memory bank
- b = buffer high offset
- c = buffer low offset
107B-108B: Compute Hamming Distance
For computing the number of error bits in ECC calculation.
- b = number of bit pairs to compare
- c = accumulation of number of bits
- l = accumulation of the parity bits
108C-10BC: Read Flash ID
Issues standard 90 (if calling 108C) or non-standard 91 (if calling 109A) command to the flash, and returns 4 bytes of ID in order b, c, d, e. Note that only the first two (manufacturer ID and device ID) are guaranteed to be valid; the code at 046A-0676 uses this information appropriately based on the manufacturer ID.
10BD-11FF: Padding
323 0 bytes for padding, bringing the total size of FLASHLDR to 3.5KB. Judging by the amount of code duplication, with better coding this size could be reduced to <1KB. The current FLASHLDR could definitely be improved greatly, although its location in ROM prevents it.