Add BIOS drive indexing
diff --git a/limine.bin b/limine.bin
index b9d1a300..5069e1e8 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/Makefile b/stage2/Makefile
index 48b4d9a8..8ac4c472 100644
--- a/stage2/Makefile
+++ b/stage2/Makefile
@@ -2,7 +2,8 @@ CC = i386-elf-gcc
LD = i386-elf-gcc
OBJCOPY = i386-elf-objcopy
-CFLAGS = -flto -Os -pipe -Wall -Wextra -Werror
+WERROR = -Werror
+CFLAGS = -flto -Os -pipe -Wall -Wextra $(WERROR)
INTERNAL_CFLAGS = \
-std=gnu11 \
diff --git a/stage2/drivers/disk.h b/stage2/drivers/disk.h
index daacbf56..843d0fac 100644
--- a/stage2/drivers/disk.h
+++ b/stage2/drivers/disk.h
@@ -5,6 +5,17 @@
#include <stdint.h>
#include <lib/part.h>
+struct bios_drive_params {
+ uint16_t buf_size;
+ uint16_t info_flags;
+ uint32_t cyl;
+ uint32_t heads;
+ uint32_t sects;
+ uint64_t lba_count;
+ uint16_t bytes_per_sect;
+ uint32_t edd;
+} __attribute__((packed));
+
int read(int drive, void *buffer, uint64_t loc, uint64_t count);
int read_partition(int drive, struct part *part, void *buffer, uint64_t loc, uint64_t count);
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index f6b018a1..d2d2e1a6 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -168,7 +168,7 @@ bool string_to_guid(struct guid *guid, const char *s) {
guid_convert_le_cluster((uint8_t *)guid + 4, s + 9, 4);
guid_convert_le_cluster((uint8_t *)guid + 6, s + 14, 4);
guid_convert_be_cluster((uint8_t *)guid + 8, s + 19, 4);
- guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 16);
+ guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12);
return true;
}
diff --git a/stage2/lib/part.c b/stage2/lib/part.c
index 9c3fe988..a3d764e2 100644
--- a/stage2/lib/part.c
+++ b/stage2/lib/part.c
@@ -4,9 +4,13 @@
#include <drivers/disk.h>
#include <lib/libc.h>
#include <lib/blib.h>
+#include <lib/real.h>
+#include <lib/print.h>
+#include <mm/pmm.h>
#define NO_PARTITION (-1)
#define INVALID_TABLE (-2)
+#define END_OF_TABLE (-3)
struct gpt_table_header {
// the head
@@ -53,12 +57,14 @@ static int gpt_get_part(struct part *ret, int drive, int partition) {
// check the header
// 'EFI PART'
- if (strncmp(header.signature, "EFI PART", 8)) return INVALID_TABLE;
- if (header.revision != 0x00010000) return NO_PARTITION;
+ if (strncmp(header.signature, "EFI PART", 8))
+ return INVALID_TABLE;
+ if (header.revision != 0x00010000)
+ return END_OF_TABLE;
// parse the entries if reached here
if ((uint32_t)partition >= header.number_of_partition_entries)
- return NO_PARTITION;
+ return END_OF_TABLE;
struct gpt_entry entry = {0};
read(drive, &entry,
@@ -71,6 +77,7 @@ static int gpt_get_part(struct part *ret, int drive, int partition) {
ret->first_sect = entry.starting_lba;
ret->sect_count = (entry.ending_lba - entry.starting_lba) + 1;
+ ret->guid = entry.unique_partition_guid;
return 0;
}
@@ -91,6 +98,12 @@ static int mbr_get_part(struct part *ret, int drive, int partition) {
if (hint && hint != 0x5a5a)
return INVALID_TABLE;
+ if (partition > 3)
+ return END_OF_TABLE;
+
+ uint32_t disk_signature;
+ read(drive, &disk_signature, 440, sizeof(uint32_t));
+
struct mbr_entry entry;
size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition;
@@ -103,6 +116,13 @@ static int mbr_get_part(struct part *ret, int drive, int partition) {
ret->first_sect = entry.first_sect;
ret->sect_count = entry.sect_count;
+
+ // We use the same method of generating GUIDs for MBR partitions as Linux
+ struct guid empty_guid = {0};
+ ret->guid = empty_guid;
+ ret->guid.a = disk_signature;
+ ret->guid.b = (partition + 1) << 8;
+
return 0;
}
@@ -119,3 +139,58 @@ int get_part(struct part *part, int drive, int partition) {
return -1;
}
+
+static struct part *part_index = NULL;
+static size_t part_index_i = 0;
+
+void part_create_index(void) {
+ part_index = conv_mem_alloc(0);
+
+ for (uint8_t drive = 0x80; drive < 0x8f; drive++) {
+ struct rm_regs r = {0};
+ struct bios_drive_params drive_params;
+
+ r.eax = 0x4800;
+ r.edx = drive;
+ r.ds = rm_seg(&drive_params);
+ r.esi = rm_off(&drive_params);
+
+ drive_params.buf_size = sizeof(struct bios_drive_params);
+
+ rm_int(0x13, &r, &r);
+
+ if (r.eflags & EFLAGS_CF)
+ continue;
+
+ print("Found BIOS drive %x\n", drive);
+ print(" ... %X total %u-byte sectors\n",
+ drive_params.lba_count, drive_params.bytes_per_sect);
+
+ size_t part_count = 0;
+ for (int part = 0; ; part++) {
+ struct part p;
+ int ret = get_part(&p, drive, part);
+
+ if (ret == END_OF_TABLE)
+ break;
+ if (ret == NO_PARTITION)
+ continue;
+
+ part_count++;
+ }
+
+ part_index = conv_mem_alloc(sizeof(struct part) * part_count);
+
+ for (int part = 0; ; part++) {
+ struct part p;
+ int ret = get_part(&p, drive, part);
+
+ if (ret == END_OF_TABLE)
+ break;
+ if (ret == NO_PARTITION)
+ continue;
+
+ part_index[part_index_i++] = p;
+ }
+ }
+}
diff --git a/stage2/lib/part.h b/stage2/lib/part.h
index ad142af5..135c32f5 100644
--- a/stage2/lib/part.h
+++ b/stage2/lib/part.h
@@ -2,12 +2,17 @@
#define __LIB__PART_H__
#include <stdint.h>
+#include <stdbool.h>
+#include <lib/blib.h>
struct part {
- uint64_t first_sect;
- uint64_t sect_count;
+ uint64_t first_sect;
+ uint64_t sect_count;
+ struct guid guid;
};
int get_part(struct part *part, int drive, int partition);
+void part_create_index(void);
+
#endif
diff --git a/stage2/main.c b/stage2/main.c
index 801b055d..ae754e1d 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -32,6 +32,8 @@ void entry(uint8_t _boot_drive) {
print("Boot drive: %x\n", boot_drive);
+ part_create_index();
+
// Look for config file.
print("Searching for config file...\n");
struct part parts[4];
