Skip to content

Commit ec11f38

Browse files
committed
Cleanup
1 parent b2cc08b commit ec11f38

File tree

2 files changed

+205
-112
lines changed

2 files changed

+205
-112
lines changed

generate_nand.c

+167-90
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
#include "mbr.h"
99
#include "gpt.h"
1010

11-
#define BANKS 8
12-
#define BLOCKS_PER_BANK 4096
13-
#define PAGES_PER_BANK 524288
14-
#define BYTES_PER_PAGE 2048
15-
#define PAGES_PER_SUBLOCK 1024
16-
#define PAGES_PER_BLOCK 128
11+
#define BYTES_PER_PAGE 4096
1712
#define BYTES_PER_SPARE 64
18-
#define FIL_ID 0x43303032
13+
#define PAGES_PER_BLOCK 128
14+
#define VFL_CTX_PHYSICAL_PAGE PAGES_PER_BLOCK * 1
15+
#define PAGES_PER_SUBLOCK 1024
16+
#define CS_TOTAL 4
17+
18+
#define NAND_SIG_PAGE 524160
19+
#define BBT_PAGE 524161
20+
1921
#define FTL_CTX_VBLK_IND 0 // virtual block index of the FTL Context
2022

2123
#define NUM_PARTITIONS 1
@@ -64,22 +66,65 @@ uint32_t crc32(const uint8_t *buf, int len)
6466
return update_crc32(0xffffffffL, buf, len) ^ 0xffffffffL;
6567
}
6668

67-
void get_physical_address(uint32_t vpn, uint32_t *bank, uint32_t *pn) {
68-
*bank = vpn % BANKS;
69-
uint32_t pbi = vpn / PAGES_PER_SUBLOCK;
70-
uint32_t pib = (vpn / BANKS) % PAGES_PER_BLOCK;
71-
*pn = pbi * PAGES_PER_BLOCK + pib;
69+
uint8_t *get_valid_ftl_spare() {
70+
uint32_t *spare = (uint32_t *)calloc(BYTES_PER_SPARE, sizeof(char));
71+
spare[2] = 0x00FF00FF;
72+
return (uint8_t *)spare;
73+
}
74+
75+
void _Helper_ConvertP2C_OneBitReorder(uint32_t dwBank, uint32_t dwPpn, uint32_t* pdwCE, uint32_t* pdwCpn, uint32_t dwReorderMask)
76+
{
77+
const uint32_t dwBelowReorderMask = dwReorderMask - 1; // Assumption: dwReorderMask is a power of 2!
78+
const uint32_t dwAboveReorderMask = ~dwBelowReorderMask;
79+
80+
// insert reorder bit back in correct position of "chip" page number by extracting from MSB of "physical" bank number
81+
*pdwCpn = ((dwPpn & dwBelowReorderMask) |
82+
(((dwBank / CS_TOTAL) & 0x1) ? dwReorderMask : 0) |
83+
((dwPpn & dwAboveReorderMask) << 1));
84+
85+
// strip reorder bit from MSB of "physical" bank number to produce "chip" CE
86+
*pdwCE = dwBank % CS_TOTAL;
87+
}
88+
89+
void _pfnConvertP2C_TwoPlaneLSB(uint32_t dwBank, uint32_t dwPpn, uint32_t* pdwCE, uint32_t* pdwCpn)
90+
{
91+
_Helper_ConvertP2C_OneBitReorder(dwBank, dwPpn, pdwCE, pdwCpn, PAGES_PER_BLOCK);
92+
}
93+
94+
void _ConvertT2P_Default(uint16_t wBank, uint16_t wTbn, uint16_t *pwPbn)
95+
{
96+
uint32_t dwCpn, dwCS;
97+
_pfnConvertP2C_TwoPlaneLSB((uint32_t)wBank, (uint32_t)(wTbn * PAGES_PER_BLOCK), &dwCS, &dwCpn);
98+
*pwPbn = (uint16_t)(dwCpn / PAGES_PER_BLOCK);
7299
}
73100

74-
void write_page(uint8_t *page, uint8_t *spare, int bank, int page_index) {
101+
void _Vpn2Ppn(uint32_t dwVpn, uint16_t *pwCS, uint32_t *pdwPpn) {
102+
uint16_t wPbn, wPOffset;
103+
uint16_t wBank = dwVpn % WMR_NUM_OF_BANKS;
104+
uint16_t wVbn = dwVpn / PAGES_PER_SUBLOCK;
105+
_ConvertT2P_Default((wBank & 0xffff), wVbn, &wPbn);
106+
*pwCS = wBank % CS_TOTAL;
107+
wPOffset = (uint16_t)((dwVpn % PAGES_PER_SUBLOCK) / WMR_NUM_OF_BANKS);
108+
*pdwPpn = wPbn * PAGES_PER_BLOCK + wPOffset;
109+
}
110+
111+
void _Lpn2Ppn(uint32_t dwLpn, uint16_t *pwCS, uint32_t *pdwPpn) {
112+
uint32_t dwLbn = dwLpn / PAGES_PER_SUBLOCK;
113+
uint16_t wLPOffset = (uint16_t)(dwLpn - dwLbn * PAGES_PER_SUBLOCK);
114+
uint32_t dwVbn = dwLbn + 1;
115+
uint32_t dwVpn = dwVbn * PAGES_PER_SUBLOCK + wLPOffset;
116+
_Vpn2Ppn(dwVpn, pwCS, pdwPpn);
117+
}
118+
119+
void write_page(uint8_t *page, uint8_t *spare, int cs, int page_index) {
75120
char filename[100];
76-
sprintf(filename, "nand/bank%d", bank);
121+
sprintf(filename, "nand/cs%d", cs);
77122
struct stat st = {0};
78123
if (stat(filename, &st) == -1) {
79124
mkdir(filename, 0700);
80125
}
81126

82-
sprintf(filename, "nand/bank%d/%d.page", bank, page_index);
127+
sprintf(filename, "nand/cs%d/%d.page", cs, page_index);
83128
FILE *f = fopen(filename, "wb");
84129

85130
if(!page) {
@@ -95,56 +140,86 @@ void write_page(uint8_t *page, uint8_t *spare, int bank, int page_index) {
95140
fclose(f);
96141
}
97142

98-
void write_fil_id() {
99-
// set the FIL ID on the very first byte of the first bank
100-
uint8_t *page0_b0 = (uint8_t *)calloc(BYTES_PER_PAGE, sizeof(char));
101-
uint8_t *spare_page0_b0 = (uint8_t *)calloc(BYTES_PER_SPARE, sizeof(char));
102-
((uint32_t *)page0_b0)[0] = FIL_ID;
103-
write_page(page0_b0, spare_page0_b0, 0, 0);
104-
}
105-
106143
void write_bbts() {
107-
// create the bad block table on the first physical page of the last physical block
108-
for(int bank = 0; bank < BANKS; bank++) {
144+
// create the bad block table on each CS
145+
for(int cs = 0; cs < CS_TOTAL; cs++) {
109146
uint8_t *page = calloc(BYTES_PER_PAGE, sizeof(char));
110147
memcpy(page, "DEVICEINFOBBT\0\0\0", 16);
111-
write_page(page, NULL, bank, PAGES_PER_BANK - PAGES_PER_BLOCK);
148+
149+
// set all bits in this page to 1, to indicate that all blocks are of good health.
150+
for(int i = 16; i < BYTES_PER_PAGE; i++) {
151+
page[i] = 0xFF;
152+
}
153+
154+
write_page(page, NULL, cs, BBT_PAGE);
112155
}
113156
}
114157

158+
void write_nand_sig_page() {
159+
// write the NAND signature page
160+
uint8_t *page = calloc(0x100, sizeof(uint8_t));
161+
char *magic = "NANDDRIVERSIGN";
162+
memcpy(page, magic, strlen(magic));
163+
page[0x34] = 0x4; // length of the info
164+
165+
// signature (0x43313131)
166+
page[0x38] = 0x31;
167+
page[0x39] = 0x31;
168+
page[0x3A] = 0x31;
169+
page[0x3B] = 0x43;
170+
write_page(page, NULL, 0, NAND_SIG_PAGE);
171+
}
172+
115173
void write_vfl_context() {
116-
for(int bank = 0; bank < BANKS; bank++) {
174+
for (int wCSIdx = 0; wCSIdx < CS_TOTAL; wCSIdx++) {
117175
// initialize VFL context block on physical block 35, page 0
118176
VFLMeta *vfl_meta = (VFLMeta *)calloc(sizeof(VFLMeta), sizeof(char));
119-
vfl_meta->stVFLCxt.awInfoBlk[0] = 35;
120-
121-
// write the bad mark table
122-
for(int i = 0; i < VFL_BAD_MARK_INFO_TABLE_SIZE; i++) {
123-
vfl_meta->stVFLCxt.aBadMark[i] = 0xff;
177+
vfl_meta->dwVersion = VFL_META_VERSION;
178+
179+
VFLCxt *pVFLCxt = &vfl_meta->stVFLCxt;
180+
181+
// we set the number of VFL/FTL user blocks to 2048 which doesn't give any room for the BBT table. This is fine as we do not have bad blocks.
182+
pVFLCxt->wNumOfVFLSuBlk = 2048;
183+
pVFLCxt->wNumOfFTLSuBlk = 2048;
184+
185+
pVFLCxt->abVSFormtType = VFL_VENDOR_SPECIFIC_TYPE;
186+
pVFLCxt->dwGlobalCxtAge = wCSIdx;
187+
pVFLCxt->wCxtLocation = 1; // the VFL context is located in the first physical block
188+
for (int wIdx = 0; wIdx < FTL_CXT_SECTION_SIZE; wIdx++)
189+
{
190+
pVFLCxt->awFTLCxtVbn[wIdx] = (uint16_t)(wIdx);
191+
}
192+
pVFLCxt->wNumOfInitBadBlk = 0;
193+
194+
for (int wIdx = 0, wPbn = VFL_FIRST_BLK_TO_SEARCH_CXT; wIdx < VFL_INFO_SECTION_SIZE && wPbn < VFL_LAST_BLK_TO_SEARCH_CXT; wPbn++)
195+
{
196+
pVFLCxt->awInfoBlk[wIdx++] = wPbn;
197+
}
198+
199+
// update the bad block map
200+
for(int i = 0; i < WMR_MAX_RESERVED_SIZE; i++) {
201+
pVFLCxt->awBadMapTable[i] = VFL_BAD_MAP_TABLE_AVAILABLE_MARK;
124202
}
125203

126204
VFLSpare *vfl_ctx_spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
127205
vfl_ctx_spare->dwCxtAge = 1;
128206
vfl_ctx_spare->bSpareType = VFL_CTX_SPARE_TYPE;
129207

130-
// indicate the location of the FTL CTX block
131-
vfl_meta->stVFLCxt.aFTLCxtVbn[0] = FTL_CTX_VBLK_IND;
132-
vfl_meta->stVFLCxt.aFTLCxtVbn[1] = FTL_CTX_VBLK_IND;
133-
vfl_meta->stVFLCxt.aFTLCxtVbn[2] = FTL_CTX_VBLK_IND;
134-
135-
write_page((uint8_t *)vfl_meta, (uint8_t *)vfl_ctx_spare, bank, 35 * PAGES_PER_BLOCK);
208+
// store some copies of the VFL
209+
for (uint8_t wPageIdx = 0; wPageIdx < VFL_NUM_OF_VFL_CXT_COPIES; wPageIdx++) {
210+
write_page((uint8_t *)vfl_meta, (uint8_t *)vfl_ctx_spare, wCSIdx, VFL_CTX_PHYSICAL_PAGE + wPageIdx);
211+
}
136212
}
137213
}
138214

139215
void write_ftl_context() {
140-
uint32_t bank, pn;
216+
uint16_t cs;
217+
uint32_t ppn;
141218

142219
// set the FTL spare type of the first page of the FTL CXT block to indicate that there is a CTX index
143220
VFLSpare *vfl_ctx_spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
144221
vfl_ctx_spare->bSpareType = FTL_SPARE_TYPE_CXT_INDEX;
145-
vfl_ctx_spare->eccMarker = 0xff;
146-
get_physical_address( (FTL_CXT_SECTION_START + FTL_CTX_VBLK_IND) * PAGES_PER_SUBLOCK, &bank, &pn);
147-
write_page(NULL, (uint8_t *)vfl_ctx_spare, 0, pn);
222+
write_page(NULL, (uint8_t *)vfl_ctx_spare, 0, 0);
148223

149224
// create the FTL Meta page on the last page of the FTL Cxt block and embed the right versions
150225
FTLMeta *ftl_meta = (FTLMeta *)calloc(sizeof(FTLMeta), sizeof(char));
@@ -164,90 +239,86 @@ void write_ftl_context() {
164239

165240
// prepare the logical block -> virtual block mapping tables
166241
for(int i = 0; i < MAX_NUM_OF_MAP_TABLES; i++) {
167-
ftl_meta->stFTLCxt.adwMapTablePtrs[i] = i + 1; // the mapping will start from the 2nd page in the FTL context block
242+
ftl_meta->stFTLCxt.adwMapTablePtrs[i] = i + 5; // the mapping will start from the 2nd page in the FTL context block
168243

169244
uint16_t *mapping_page = calloc(BYTES_PER_PAGE / sizeof(uint16_t), sizeof(uint16_t));
170-
for(int ind_in_map = 0; ind_in_map < 1024; ind_in_map++) {
171-
mapping_page[ind_in_map] = (i * 1024) + ind_in_map + 1;
245+
uint32_t items_per_map = BYTES_PER_PAGE / sizeof(uint16_t);
246+
for(int ind_in_map = 0; ind_in_map < items_per_map; ind_in_map++) {
247+
mapping_page[ind_in_map] = (i * items_per_map) + ind_in_map + 1;
172248
}
173-
get_physical_address( FTL_CXT_SECTION_START * PAGES_PER_SUBLOCK + i + 1, &bank, &pn);
174-
write_page((uint8_t *)mapping_page, NULL, bank, pn);
249+
_Vpn2Ppn(i + 5, &cs, &ppn);
250+
printf("Writing logical -> virtual block map page %d to physical page %d @ cs %d\n", i, ppn, cs);
251+
write_page((uint8_t *)mapping_page, NULL, cs, ppn);
175252
}
176253

177254
vfl_ctx_spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
178255
vfl_ctx_spare->bSpareType = FTL_SPARE_TYPE_CXT_INDEX;
179-
get_physical_address( (FTL_CXT_SECTION_START + FTL_CTX_VBLK_IND + 1) * PAGES_PER_SUBLOCK - 1, &bank, &pn);
180-
printf("Writing FTL Meta to virtual page %d\n", (FTL_CXT_SECTION_START + FTL_CTX_VBLK_IND + 1) * PAGES_PER_SUBLOCK - 1);
181-
write_page((uint8_t *)ftl_meta, (uint8_t *)vfl_ctx_spare, bank, pn);
256+
257+
// we place the FTL Meta on the last page of the first virtual block.
258+
_Vpn2Ppn(PAGES_PER_SUBLOCK - 1, &cs, &ppn);
259+
260+
printf("Writing FTL Meta to physical page %d @ cs %d\n", ppn, cs);
261+
write_page((uint8_t *)ftl_meta, (uint8_t *)vfl_ctx_spare, cs, ppn);
182262
}
183263

184264
uint32_t write_hfs_partition(char *filename, uint32_t page_offset) {
185265
// write the HFS+ partition to the first page and update the associated spare
186-
uint32_t bank, pn, vpn;
266+
uint16_t cs; uint32_t ppn;
267+
187268
FILE *hfs_file = fopen(filename, "rb");
188269
fseek(hfs_file, 0L, SEEK_END);
189270
int partition_size = ftell(hfs_file);
190271
fclose(hfs_file);
191272

192273
hfs_file = fopen(filename, "rb");
193-
vpn = (FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + page_offset;
194-
for(int i = 0; i < partition_size / BYTES_PER_PAGE; i++) {
274+
int lpn = page_offset;
275+
uint8_t *spare = get_valid_ftl_spare();
276+
uint32_t required_pages_for_partition = partition_size / BYTES_PER_PAGE;
277+
printf("Writing HFS partition using %d pages...\n", required_pages_for_partition);
278+
for(int i = 0; i < required_pages_for_partition; i++) {
195279
uint8_t *page = malloc(BYTES_PER_PAGE);
196280
fread(page, BYTES_PER_PAGE, sizeof(uint8_t), hfs_file);
197-
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
198-
spare->eccMarker = 0xff;
199-
get_physical_address(vpn, &bank, &pn);
200-
if(i == 0) {
201-
printf("Writing HFS partition to virtual page %d (writing to bank %d, page %d)\n", vpn, bank, pn);
202-
}
203-
write_page(page, (uint8_t *)spare, bank, pn);
204-
vpn++;
281+
_Lpn2Ppn(lpn, &cs, &ppn);
282+
printf("Writing HFS partition to physical page %d @ cs %d\n", ppn, cs);
283+
write_page(page, spare, cs, ppn);
284+
lpn++;
285+
286+
//if(i == 2000) break;
205287
}
206288
fclose(hfs_file);
207289

208-
return partition_size / BYTES_PER_PAGE;
290+
return required_pages_for_partition;
209291
}
210292

211293
void write_mbr(int boot_partition_size) {
212-
uint32_t bank, pn;
294+
uint16_t cs; uint32_t ppn;
213295

214296
// write the MBR bytes (LBA 0)
215297
uint8_t *mbr_page = malloc(BYTES_PER_PAGE);
216-
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK, &bank, &pn);
217298
struct mbr_partition *boot_partition = (struct mbr_partition *)(mbr_page + MBR_ADDRESS);
218299
boot_partition->sysid = 0xEE;
219300
boot_partition->startlba = BOOT_PARTITION_FIRST_PAGE;
220301
boot_partition->size = boot_partition_size;
221302

222-
// struct mbr_partition *filesystem_partition = (struct mbr_partition *)(mbr_page + MBR_ADDRESS + sizeof(struct mbr_partition));
223-
// filesystem_partition->sysid = 0xEE;
224-
// filesystem_partition->startlba = filesystem_partition_offset;
225-
// filesystem_partition->size = filesystem_partition_size;
226-
227303
mbr_page[510] = 0x55;
228304
mbr_page[511] = 0xAA;
229305

230-
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
231-
spare->eccMarker = 0xff;
232-
233-
printf("Writing MBR to page %d, bank %d\n", pn, bank);
234-
write_page(mbr_page, (uint8_t *)spare, bank, pn);
306+
_Lpn2Ppn(0, &cs, &ppn);
307+
printf("Writing MBR to physical page %d @ cs %d\n", ppn, cs);
308+
uint8_t *spare = get_valid_ftl_spare();
309+
write_page(mbr_page, spare, cs, ppn);
235310
}
236311

237312
void write_filesystem() {
238-
int pages_for_boot_partition = write_hfs_partition("filesystem-readonly.img", BOOT_PARTITION_FIRST_PAGE);
313+
uint16_t cs; uint32_t ppn;
314+
315+
int pages_for_boot_partition = write_hfs_partition("filesystem-it2g-readonly.img", BOOT_PARTITION_FIRST_PAGE);
239316
printf("Required pages for boot partition: %d\n", pages_for_boot_partition);
240-
//int pages_for_filesystem_partition = write_hfs_partition("filesystem_full.part", BOOT_PARTITION_FIRST_PAGE + pages_for_boot_partition + 1);
241-
//printf("Required pages for filesystem partition: %d\n", pages_for_filesystem_partition);
242317

243318
// initialize the EFI header (LBA 1)
244-
uint32_t bank, pn;
245319
uint8_t *gpt_header_page = malloc(BYTES_PER_PAGE);
246320
gpt_hdr *gpt_header = (gpt_hdr *)gpt_header_page;
247321

248-
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
249-
spare->eccMarker = 0xff;
250-
251322
// create the boot partition entry (LBA 2)
252323
uint8_t *gpt_entry_boot_partition_page = malloc(BYTES_PER_PAGE);
253324
gpt_ent *gpt_entry_boot_partition = (gpt_ent *)gpt_entry_boot_partition_page;
@@ -259,9 +330,10 @@ void write_filesystem() {
259330
gpt_entry_boot_partition->ent_lba_end = BOOT_PARTITION_FIRST_PAGE + pages_for_boot_partition;
260331
printf("Boot system partition located on page %lld - %lld\n", gpt_entry_boot_partition->ent_lba_start, gpt_entry_boot_partition->ent_lba_end);
261332

262-
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + 2, &bank, &pn);
263-
printf("Writing GUID boot partition entry to page %d, bank %d\n", pn, bank);
264-
write_page(gpt_entry_boot_partition_page, (uint8_t *)spare, bank, pn);
333+
_Lpn2Ppn(2, &cs, &ppn);
334+
printf("Writing GUID boot partition entry to page %d @ cs %d\n", ppn, cs);
335+
uint8_t *spare = get_valid_ftl_spare();
336+
write_page(gpt_entry_boot_partition_page, spare, cs, ppn);
265337

266338
// finalize the GPT header
267339
// TODO add the secondary GPT entry!
@@ -274,26 +346,31 @@ void write_filesystem() {
274346
gpt_header->hdr_crc_table = crc32(gpt_entry_boot_partition_page, sizeof(gpt_ent));
275347
gpt_header->hdr_crc_self = crc32((uint8_t *)gpt_header, 0x5C);
276348

277-
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + 1, &bank, &pn);
278-
printf("Writing GUID header to page %d, bank %d\n", pn, bank);
279-
write_page(gpt_header_page, (uint8_t *)spare, bank, pn);
349+
_Lpn2Ppn(1, &cs, &ppn);
350+
printf("Writing GUID header to page %d @ cs %d\n", ppn, cs);
351+
write_page(gpt_header_page, spare, cs, ppn);
280352

281353
// finally, write the MBR
282354
write_mbr(pages_for_boot_partition);
283355
}
284356

285357
int main(int argc, char *argv[]) {
286-
287358
// create the output dir if it does not exist
288359
struct stat st = {0};
289360

290361
if (stat("nand", &st) == -1) {
291362
mkdir("nand", 0700);
292363
}
293364

294-
write_fil_id();
295-
write_bbts();
296365
write_vfl_context();
297366
write_ftl_context();
367+
write_nand_sig_page();
368+
write_bbts();
298369
write_filesystem();
370+
371+
// testing
372+
uint32_t num = 49188;
373+
uint16_t cs; uint32_t ppn;
374+
_Lpn2Ppn(num, &cs, &ppn);
375+
printf("LPN %d => %d, cs %d\n", num, ppn, cs);
299376
}

0 commit comments

Comments
 (0)