fix: add dummy process to keep scheduler busy
[lunaix-os.git] / lunaix-os / kernel / block / blkpart_gpt.c
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
7 #include <lib/crc.h>
8
9 #define GPT_BLKSIZE 512
10 #define LBA2OFF(lba) ((lba)*GPT_BLKSIZE)
11 #define ENT_PER_BLK (GPT_BLKSIZE / sizeof(struct gpt_entry))
12
13 #define GPTSIG_LO 0x20494645UL
14 #define GPTSIG_HI 0x54524150UL
15
16 static u8_t NULL_GUID[16] = { 0 };
17
18 int
19 blkpart_parse(struct device* master, struct gpt_header* header)
20 {
21     struct block_dev* bdev = (struct block_dev*)master->underlay;
22     if (!bdev)
23         return ENODEV;
24
25     int errno;
26     u32_t ent_lba = (u32_t)header->ents_lba;
27     struct gpt_entry* ents_parial = (struct gpt_entry*)valloc(GPT_BLKSIZE);
28
29     for (size_t i = 0; i < header->ents_len; i++) {
30         if (!(i % ENT_PER_BLK)) {
31             errno = master->read(
32               master, ents_parial, LBA2OFF(ent_lba++), GPT_BLKSIZE);
33             if (errno < 0) {
34                 goto done;
35             }
36         }
37
38         struct gpt_entry* ent = &ents_parial[i % ENT_PER_BLK];
39
40         // assuming the entries are not scattered around
41         if (!memcmp(ent->pguid, NULL_GUID, 16)) {
42             break;
43         }
44
45         // Convert UEFI's 512B LB representation into local LBA range.
46         u64_t slba_local = (ent->start_lba * GPT_BLKSIZE) / bdev->blk_size;
47         u64_t elba_local = (ent->end_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
48
49         // we ignore the partition name, as it rarely used.
50         blk_mount_part(bdev, NULL, i, slba_local, elba_local);
51     }
52
53 done:
54     vfree(ents_parial);
55     return errno;
56 }
57
58 int
59 blkpart_probegpt(struct device* master)
60 {
61     int errno;
62     struct gpt_header* gpt_hdr = (struct gpt_header*)valloc(GPT_BLKSIZE);
63
64     if ((errno = master->read(master, gpt_hdr, LBA2OFF(1), LBA2OFF(1))) < 0) {
65         goto done;
66     }
67
68     if (*(u32_t*)&gpt_hdr->signature != GPTSIG_LO ||
69         *(u32_t*)&gpt_hdr->signature[4] != GPTSIG_HI) {
70         return 0;
71     }
72
73     u32_t crc = gpt_hdr->hdr_cksum;
74     gpt_hdr->hdr_cksum = 0;
75     if (crc32b((void*)gpt_hdr, sizeof(*gpt_hdr)) != crc) {
76         // FUTURE check the backup header
77         return EINVAL;
78     }
79
80     errno = blkpart_parse(master, gpt_hdr);
81 done:
82     vfree(gpt_hdr);
83     return errno;
84 }