summaryrefslogtreecommitdiffhomepage
path: root/src/loader/mbr.c
blob: 599952c1d99b53c45e6640f0aba59e93e0c0bb49 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// MIT License, Copyright (c) 2021 Marvin Borner

#include <lib.h>
#include <log.h>
#include <mbr.h>
#include <pnc.h>

static struct mbr_entry entries[16] = { 0 };

static s32 mbr_read(void *buf, u32 lba, u32 sector_count, struct dev *part)
{
	u8 dev_id = (part->data & 0xff00) >> 8;
	struct dev *dev = dev_get(dev_id);
	assert(dev && dev->type == DEV_DISK && dev->read);

	u8 mbr_id = part->data & 0xff;
	assert(mbr_id < COUNT(entries));
	struct mbr_entry *entry = &entries[mbr_id];

	return dev->read(buf, entry->start + lba, sector_count, dev);
}

static u8 mbr_add_entry(struct mbr_entry *entry)
{
	static u8 i = 0;
	assert(i + 1 < (u8)COUNT(entries));
	entries[i] = *entry;
	return i++;
}

u8 mbr_detect(struct dev *dev)
{
	assert(dev->type == DEV_DISK);

	struct mbr mbr = { 0 };
	dev->read(&mbr, 0, 1, dev); // Read first sector (MBR)

	if (mbr.magic != 0xaa55)
		return 0;

	for (u8 i = 0; i < 4; i++) {
		struct mbr_entry *entry = &mbr.entries[i];
		if (!entry->type || !entry->size)
			continue;

		char name[5] = { 0 };
		strlcpy(name, dev->name, sizeof(name));
		name[3] = '0' + i;

		log("[MBR] Found part %s\n", name);

		// Saving space and everything
		u16 data = mbr_add_entry(entry) | (dev->id << 8);

		dev_register(DEV_DISK, name, data, mbr_read, NULL);
	}

	return 1;
}