1 #include <klibc/string.h>
2 #include <lunaix/blkpart_gpt.h>
3 #include <lunaix/block.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/status.h>
6 #include <lunaix/syslog.h>
10 #define GPT_BLKSIZE 512
11 #define LBA2OFF(lba) ((lba) * GPT_BLKSIZE)
12 #define ENT_PER_BLK (GPT_BLKSIZE / sizeof(struct gpt_entry))
14 #define GPTSIG_LO 0x20494645UL
15 #define GPTSIG_HI 0x54524150UL
17 static u8_t NULL_GUID[16] = { 0 };
22 blkpart_parse(struct device* master, struct gpt_header* header)
24 struct block_dev* bdev = (struct block_dev*)master->underlay;
29 u32_t ent_lba = (u32_t)header->ents_lba;
30 struct gpt_entry* ents_parial = (struct gpt_entry*)valloc(GPT_BLKSIZE);
32 for (size_t i = 0; i < header->ents_len; i++) {
33 if (!(i % ENT_PER_BLK)) {
34 errno = master->ops.read(
35 master, ents_parial, LBA2OFF(ent_lba++), GPT_BLKSIZE);
41 struct gpt_entry* ent = &ents_parial[i % ENT_PER_BLK];
43 // assuming the entries are not scattered around
44 if (!memcmp(ent->pguid, NULL_GUID, 16)) {
48 // Convert UEFI's 512B LB representation into local LBA range.
50 (ent->start_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
51 u64_t elba_local = (ent->end_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
53 kprintf("%s: guid part#%d: %d..%d",
58 // we ignore the partition name, as it rarely used.
59 blk_mount_part(bdev, NULL, i, slba_local, elba_local);
68 blkpart_probegpt(struct device* master)
71 struct gpt_header* gpt_hdr = (struct gpt_header*)valloc(GPT_BLKSIZE);
73 if ((errno = master->ops.read(master, gpt_hdr, LBA2OFF(1), LBA2OFF(1))) <
78 if (*(u32_t*)&gpt_hdr->signature != GPTSIG_LO ||
79 *(u32_t*)&gpt_hdr->signature[4] != GPTSIG_HI) {
83 u32_t crc = gpt_hdr->hdr_cksum;
84 gpt_hdr->hdr_cksum = 0;
85 if (crc32b((void*)gpt_hdr, sizeof(*gpt_hdr)) != crc) {
86 kprintf(KWARN "checksum failed");
87 // FUTURE check the backup header
91 errno = blkpart_parse(master, gpt_hdr);