Skip to content

Commit 8178d38

Browse files
committed
Writing MBR/GPT layouts
1 parent a893e27 commit 8178d38

File tree

3 files changed

+170
-5
lines changed

3 files changed

+170
-5
lines changed

generate_nand.c

+115-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#include <string.h>
44
#include <sys/stat.h>
55
#include <sys/types.h>
6+
#include <stddef.h>
67
#include "vfl.h"
7-
#include <stddef.h>
8+
#include "mbr.h"
9+
#include "gpt.h"
810

911
#define BANKS 8
1012
#define BLOCKS_PER_BANK 4096
@@ -16,6 +18,51 @@
1618
#define FIL_ID 0x43303032
1719
#define FTL_CTX_VBLK_IND 0 // virtual block index of the FTL Context
1820

21+
#define BOOT_PARTITION_FIRST_PAGE 3
22+
23+
static uint32_t crc32_table[256];
24+
static int crc32_table_computed = 0;
25+
26+
/*
27+
CRC32 logic
28+
*/
29+
static void make_crc32_table(void)
30+
{
31+
uint32_t c;
32+
int n, k;
33+
34+
for (n = 0; n < 256; n++) {
35+
c = (uint32_t) n;
36+
for (k = 0; k < 8; k++) {
37+
if (c & 1)
38+
c = 0xedb88320L ^ (c >> 1);
39+
else
40+
c = c >> 1;
41+
}
42+
crc32_table[n] = c;
43+
}
44+
crc32_table_computed = 1;
45+
}
46+
47+
uint32_t update_crc32(uint32_t crc, const uint8_t *buf,
48+
int len)
49+
{
50+
uint32_t c = crc;
51+
int n;
52+
53+
if (!crc32_table_computed)
54+
make_crc32_table();
55+
for (n = 0; n < len; n++) {
56+
c = crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
57+
}
58+
return c;
59+
}
60+
61+
uint32_t crc32(const uint8_t *buf, int len)
62+
{
63+
return update_crc32(0xffffffffL, buf, len) ^ 0xffffffffL;
64+
}
65+
1966
void get_physical_address(uint32_t vpn, uint32_t *bank, uint32_t *physical_block_index, uint32_t *page_in_block) {
2067
*bank = vpn % BANKS;
2168
*physical_block_index = vpn / PAGES_PER_SUBLOCK;
@@ -127,7 +174,7 @@ void write_ftl_context() {
127174
write_page((uint8_t *)ftl_meta, (uint8_t *)vfl_ctx_spare, bank, pbi * PAGES_PER_BLOCK + pib);
128175
}
129176

130-
void write_hfs_partition() {
177+
uint32_t write_hfs_partition(uint32_t page_offset) {
131178
// write the HFS+ partition to the first page and update the associated spare
132179
uint32_t bank, pbi, pib;
133180
FILE *hfs_file = fopen("hfs.part", "rb");
@@ -141,11 +188,74 @@ void write_hfs_partition() {
141188
fread(page, BYTES_PER_PAGE, sizeof(uint8_t), hfs_file);
142189
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
143190
spare->eccMarker = 0xff;
144-
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + i, &bank, &pbi, &pib);
145-
printf("Writing HFS partition offset %d to virtual page %d (writing to bank %d, page %d)\n", i * BYTES_PER_PAGE, (FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + i, bank, pbi * PAGES_PER_BLOCK + pib);
191+
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + i + page_offset, &bank, &pbi, &pib);
192+
printf("Writing HFS partition offset %d to virtual page %d (writing to bank %d, page %d)\n", i * BYTES_PER_PAGE, (FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + i + page_offset, bank, pbi * PAGES_PER_BLOCK + pib);
146193
write_page(page, (uint8_t *)spare, bank, pbi * PAGES_PER_BLOCK + pib);
147194
}
148195
fclose(hfs_file);
196+
197+
return partition_size / BYTES_PER_PAGE;
198+
}
199+
200+
void write_mbr() {
201+
uint32_t bank, pbi, pib;
202+
203+
// write the MBR bytes (LBA 0)
204+
uint8_t *mbr_page = malloc(BYTES_PER_PAGE);
205+
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK, &bank, &pbi, &pib);
206+
struct mbr_partition *mbr = (struct mbr_partition *)(mbr_page + MBR_ADDRESS);
207+
mbr->sysid = 0xEE;
208+
mbr->startlba = 0x3; // offset of the partition
209+
mbr->size = 0x2ce7;
210+
mbr_page[510] = 0x55;
211+
mbr_page[511] = 0xAA;
212+
213+
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
214+
spare->eccMarker = 0xff;
215+
216+
write_page(mbr_page, (uint8_t *)spare, bank, pbi * PAGES_PER_BLOCK + pib);
217+
}
218+
219+
void write_filesystem() {
220+
int pages_for_partition = write_hfs_partition(BOOT_PARTITION_FIRST_PAGE);
221+
222+
write_mbr();
223+
224+
// initialize the EFI header (LBA 1)
225+
uint32_t bank, pbi, pib;
226+
uint8_t *gpt_header_page = malloc(BYTES_PER_PAGE);
227+
gpt_hdr *gpt_header = (gpt_hdr *)gpt_header_page;
228+
229+
VFLSpare *spare = (VFLSpare *)calloc(BYTES_PER_SPARE, sizeof(char));
230+
spare->eccMarker = 0xff;
231+
232+
// create the partition entries (LBA 2)
233+
uint8_t *gpt_entry_boot_partition_page = malloc(BYTES_PER_PAGE);
234+
gpt_ent *gpt_entry_boot_partition = (gpt_ent *)gpt_entry_boot_partition_page;
235+
gpt_entry_boot_partition->ent_type[0] = 0x48465300;
236+
gpt_entry_boot_partition->ent_type[1] = 0x11AA0000;
237+
gpt_entry_boot_partition->ent_type[2] = 0x300011AA;
238+
gpt_entry_boot_partition->ent_type[3] = 0xACEC4365;
239+
gpt_entry_boot_partition->ent_lba_start = BOOT_PARTITION_FIRST_PAGE;
240+
gpt_entry_boot_partition->ent_lba_end = BOOT_PARTITION_FIRST_PAGE + pages_for_partition;
241+
242+
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + 2, &bank, &pbi, &pib);
243+
write_page(gpt_entry_boot_partition_page, (uint8_t *)spare, bank, pbi * PAGES_PER_BLOCK + pib);
244+
245+
// finalize the GPT header
246+
memcpy(gpt_header, GPT_HDR_SIG, 8);
247+
gpt_header->hdr_revision = GPT_HDR_REVISION;
248+
gpt_header->hdr_size = 0x5C; // 92 bytes
249+
gpt_header->hdr_lba_table = 2;
250+
gpt_header->hdr_entries = 1;
251+
gpt_header->hdr_entsz = 0x80;
252+
gpt_header->hdr_crc_table = crc32(gpt_entry_boot_partition_page, sizeof(gpt_ent));
253+
gpt_header->hdr_crc_self = crc32((uint8_t *)gpt_header, 0x5C);
254+
255+
get_physical_address((FTL_CXT_SECTION_START + 1) * PAGES_PER_SUBLOCK + 1, &bank, &pbi, &pib);
256+
write_page(gpt_header_page, (uint8_t *)spare, bank, pbi * PAGES_PER_BLOCK + pib);
257+
258+
printf("%d\n", sizeof(gpt_ent));
149259
}
150260

151261
int main(int argc, char *argv[]) {
@@ -161,5 +271,5 @@ int main(int argc, char *argv[]) {
161271
write_bbts();
162272
write_vfl_context();
163273
write_ftl_context();
164-
write_hfs_partition();
274+
write_filesystem();
165275
}

gpt.h

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef GPT_H
2+
#define GPT_H
3+
4+
typedef struct gpt_hdr
5+
{
6+
uint8_t hdr_sig[8];
7+
uint32_t hdr_revision;
8+
uint32_t hdr_size;
9+
uint32_t hdr_crc_self;
10+
uint32_t __reserved;
11+
uint64_t hdr_lba_self;
12+
uint64_t hdr_lba_alt;
13+
uint64_t hdr_lba_start;
14+
uint64_t hdr_lba_end;
15+
uint8_t hdr_uuid[16];
16+
uint64_t hdr_lba_table;
17+
uint32_t hdr_entries; // the number of partition entries
18+
uint32_t hdr_entsz; // size of each partition entry
19+
uint32_t hdr_crc_table;
20+
uint32_t padding;
21+
} gpt_hdr;
22+
23+
typedef struct gpt_ent
24+
{
25+
uint32_t ent_type[4];
26+
uint8_t ent_uuid[16];
27+
uint64_t ent_lba_start;
28+
uint64_t ent_lba_end;
29+
uint64_t ent_attr;
30+
uint16_t ent_name[36];
31+
} gpt_ent;
32+
33+
#define GPT_HDR_SIG "EFI PART"
34+
#define GPT_HDR_REVISION 0x00010000
35+
36+
#endif

mbr.h

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef MBR_H
2+
#define MBR_H
3+
4+
#define MBR_ADDRESS 0x1be
5+
6+
struct mbr_partition {
7+
uint8_t bootid;
8+
uint8_t starthead;
9+
uint8_t startsect;
10+
uint8_t startcyl;
11+
uint8_t sysid;
12+
uint8_t endhead;
13+
uint8_t endsect;
14+
uint8_t endcyl;
15+
uint32_t startlba;
16+
uint32_t size;
17+
} __packed;
18+
19+
#endif

0 commit comments

Comments
 (0)