Add support for GPT partitions

This commit is contained in:
Mark
2020-01-04 20:11:40 +02:00
parent 7df7f9cbe4
commit 35b93e247f
+79 -1
View File
@@ -29,6 +29,7 @@ ssize_t blk_write(struct blkdev *blk, const void *buf, size_t off, size_t lim) {
}
}
const char GUID_EMPTY[16] = {0};
// TODO: guess this would better be in blk_part.c or something like that
struct mbr {
@@ -46,6 +47,32 @@ struct mbr {
uint16_t sign;
} __attribute__((packed));
struct gpt_header {
char signature[8];
uint32_t revision;
uint32_t header_size;
uint32_t header_crc32;
uint32_t __res0;
uint64_t my_lba;
uint64_t alt_lba;
uint64_t first_lba;
uint64_t last_lba;
char disk_guid[16];
uint64_t partition_entry_lba;
uint32_t partition_count;
uint32_t partition_entry_size;
uint32_t partition_array_crc32;
} __attribute__((packed));
struct gpt_part_entry {
char type_guid[16];
char part_guid[16];
uint64_t start_lba;
uint64_t end_lba;
uint64_t attr;
char part_name[72];
};
struct blk_part {
struct blkdev *device;
uint64_t lba_start;
@@ -119,6 +146,56 @@ static int blk_enumerate_mbr(struct blkdev *dev, uint8_t *head) {
return 0;
}
static int blk_enumerate_gpt(struct blkdev *dev, uint8_t *head) {
// LBA1 - GPT header
struct gpt_header *hdr = (struct gpt_header *) &head[512];
// Read a single block for partition table entries
char buf[512];
_assert(blk_read(dev, buf, hdr->partition_entry_lba * 512, 512) >= 0);
size_t offset = 0;
size_t part_n = 0;
for (size_t i = 0; i < hdr->partition_count; ++i) {
struct gpt_part_entry *ent = (struct gpt_part_entry *) &buf[offset];
if (strncmp(ent->type_guid, GUID_EMPTY, 16)) {
// Maybe some known filesystem here, ignore partition type guid
struct blk_part *part = (struct blk_part *) kmalloc(sizeof(struct blk_part));
part->device = dev;
part->lba_start = ent->start_lba;
part->lba_size = ent->end_lba - ent->start_lba;
void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
struct dev_entry *ent = (struct dev_entry *) buf;
struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
_assert(ent);
blk->dev_data = part;
blk->read = blk_part_read;
blk->ent_parent = dev->ent;
ent->dev = blk;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_PART;
// XXX: This is ugly
strcpy(ent->dev_name, dev->ent->dev_name);
char digit[2] = { '1' + part_n++, 0 };
strcat(ent->dev_name, digit);
dev_entry_add(ent);
}
offset += hdr->partition_entry_size;
if (offset >= 512) {
break;
}
}
return 0;
}
struct blkdev *blk_by_name(const char *name) {
struct dev_entry *it = dev_iter();
@@ -133,13 +210,14 @@ struct blkdev *blk_by_name(const char *name) {
int blk_enumerate_partitions(struct blkdev *dev) {
kdebug("Enumerating partitions of %s\n", dev->ent->dev_name);
// TODO: handle stuff where block size is not 512
uint8_t buf[1024];
_assert(blk_read(dev, buf, 0, 1024) >= 0);
if (!strncmp((const char *) (buf + 512), "EFI PART", 8)) {
// Found GPT
panic("Found GPT: not supported\n");
return blk_enumerate_gpt(dev, buf);
} else if (buf[510] == 0x55 && buf[511] == 0xAA) {
// Found MBR
return blk_enumerate_mbr(dev, buf);