:: commit 8c76a0f40666e84d87ab61620fee4d7832668e16

mintsuki <mintsuki@protonmail.com> — 2021-02-08 17:47

parents: 0c12e2f4da

Revert "volume: Replace concept of partition handle with that of volumes, fix bug in indexing volumes along the way"

This reverts commit af31ba949b59e4df92885a2afcd82de3c8d834b1.
diff --git a/limine-pxe.bin b/limine-pxe.bin
index ff69c4d2..f231d397 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index d5da2bf5..663827f8 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2.map b/stage2.map
index 1f7b8a17..c530b7d1 100644
Binary files a/stage2.map and b/stage2.map differ
diff --git a/stage2/fs/echfs.c b/stage2/fs/echfs.c
index 50df73d7..e7f3c2b0 100644
--- a/stage2/fs/echfs.c
+++ b/stage2/fs/echfs.c
@@ -23,7 +23,7 @@ struct echfs_identity_table {
 #define DIR_TYPE     1
 
 static int read_block(struct echfs_file_handle *file, void *buf, uint64_t block, uint64_t offset, uint64_t count) {
-    return volume_read(&file->part, buf, (file->alloc_map[block] * file->block_size) + offset, count);
+    return part_read(&file->part, buf, (file->alloc_map[block] * file->block_size) + offset, count);
 }
 
 int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
@@ -42,9 +42,9 @@ int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t
     return 0;
 }
 
-int echfs_check_signature(struct volume *part) {
+int echfs_check_signature(struct part *part) {
     struct echfs_identity_table id_table;
-    volume_read(part, &id_table, 0, sizeof(struct echfs_identity_table));
+    part_read(part, &id_table, 0, sizeof(struct echfs_identity_table));
 
     if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
         return 0;
@@ -53,9 +53,9 @@ int echfs_check_signature(struct volume *part) {
     return 1;
 }
 
-bool echfs_get_guid(struct guid *guid, struct volume *part) {
+bool echfs_get_guid(struct guid *guid, struct part *part) {
     struct echfs_identity_table id_table;
-    volume_read(part, &id_table, 0, sizeof(struct echfs_identity_table));
+    part_read(part, &id_table, 0, sizeof(struct echfs_identity_table));
 
     if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
         return false;
@@ -66,14 +66,14 @@ bool echfs_get_guid(struct guid *guid, struct volume *part) {
     return true;
 }
 
-int echfs_open(struct echfs_file_handle *ret, struct volume *part, const char *path) {
+int echfs_open(struct echfs_file_handle *ret, struct part *part, const char *path) {
     const char *fullpath = path;
 
     ret->disk = part->drive;
     ret->part = *part;
 
     struct echfs_identity_table id_table;
-    volume_read(&ret->part, &id_table, 0, sizeof(struct echfs_identity_table));
+    part_read(&ret->part, &id_table, 0, sizeof(struct echfs_identity_table));
 
     if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
         print("echfs: signature invalid\n");
@@ -106,7 +106,7 @@ next:;
     }
 
     for (uint64_t i = 0; i < ret->dir_length; i += sizeof(struct echfs_dir_entry)) {
-        volume_read(&ret->part, &ret->dir_entry, i + ret->dir_offset, sizeof(struct echfs_dir_entry));
+        part_read(&ret->part, &ret->dir_entry, i + ret->dir_offset, sizeof(struct echfs_dir_entry));
 
         if (!ret->dir_entry.parent_id) {
             break;
@@ -136,7 +136,7 @@ found:;
     ret->alloc_map[0] = ret->dir_entry.payload;
     for (uint64_t i = 1; i < file_block_count; i++) {
         // Read the next block.
-        volume_read(&ret->part,
+        part_read(&ret->part,
             &ret->alloc_map[i],
             ret->alloc_table_offset + ret->alloc_map[i-1] * sizeof(uint64_t),
             sizeof(uint64_t));
diff --git a/stage2/fs/echfs.h b/stage2/fs/echfs.h
index 517e71fe..4aacad2e 100644
--- a/stage2/fs/echfs.h
+++ b/stage2/fs/echfs.h
@@ -22,7 +22,7 @@ struct echfs_dir_entry {
 
 struct echfs_file_handle {
     int disk;
-    struct volume part;
+    struct part part;
     uint64_t block_size;
     uint64_t block_count;
     uint64_t dir_length;
@@ -33,10 +33,10 @@ struct echfs_file_handle {
     struct echfs_dir_entry dir_entry;
 };
 
-int echfs_check_signature(struct volume *part);
-bool echfs_get_guid(struct guid *guid, struct volume *part);
+int echfs_check_signature(struct part *part);
+bool echfs_get_guid(struct guid *guid, struct part *part);
 
-int echfs_open(struct echfs_file_handle *ret, struct volume *part, const char *filename);
+int echfs_open(struct echfs_file_handle *ret, struct part *part, const char *filename);
 int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
 
 #endif
diff --git a/stage2/fs/ext2.c b/stage2/fs/ext2.c
index 014d6b68..80f9ff81 100644
--- a/stage2/fs/ext2.c
+++ b/stage2/fs/ext2.c
@@ -138,7 +138,7 @@ static bool ext2_get_inode(struct ext2_inode *ret,
         struct ext2_bgd target_descriptor;

         const uint64_t bgd_offset = bgd_start_offset + (sizeof(struct ext2_bgd) * ino_blk_grp);

 

-        volume_read(&fd->part, &target_descriptor, bgd_offset, sizeof(struct ext2_bgd));

+        part_read(&fd->part, &target_descriptor, bgd_offset, sizeof(struct ext2_bgd));

 

         ino_offset = ((target_descriptor.bg_inode_table) * block_size) +

                                     (ino_size * ino_tbl_idx);

@@ -146,13 +146,13 @@ static bool ext2_get_inode(struct ext2_inode *ret,
         struct ext4_bgd target_descriptor;

         const uint64_t bgd_offset = bgd_start_offset + (sizeof(struct ext4_bgd) * ino_blk_grp);

 

-        volume_read(&fd->part, &target_descriptor, bgd_offset, sizeof(struct ext4_bgd));

+        part_read(&fd->part, &target_descriptor, bgd_offset, sizeof(struct ext4_bgd));

 

         ino_offset = ((target_descriptor.bg_inode_table | (bit64 ? ((uint64_t)target_descriptor.inode_id_hi << 32) : 0)) * block_size) +

                                     (ino_size * ino_tbl_idx);

     }

 

-    volume_read(&fd->part, ret, ino_offset, sizeof(struct ext2_inode));

+    part_read(&fd->part, ret, ino_offset, sizeof(struct ext2_inode));

 

     return true;

 }

@@ -183,7 +183,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd,
                     panic("ext2: triply indirect blocks unsupported");

                 }

                 uint32_t indirect_block;

-                volume_read(

+                part_read(

                     &fd->part, &indirect_block,

                     inode->i_blocks[13] * fd->block_size + index * sizeof(uint32_t),

                     sizeof(uint32_t)

@@ -191,7 +191,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd,
                 for (uint32_t j = 0; j < entries_per_block; j++) {

                     if (i + j >= inode->i_blocks_count)

                         return alloc_map;

-                    volume_read(

+                    part_read(

                         &fd->part, &alloc_map[i + j],

                         indirect_block * fd->block_size + j * sizeof(uint32_t),

                         sizeof(uint32_t)

@@ -200,7 +200,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd,
                 i += entries_per_block - 1;

             } else {

                 // Single indirect block

-                volume_read(

+                part_read(

                     &fd->part, &alloc_map[i],

                     inode->i_blocks[12] * fd->block_size + block * sizeof(uint32_t),

                     sizeof(uint32_t)

@@ -288,10 +288,10 @@ next:
     return false;

 }

 

-int ext2_open(struct ext2_file_handle *ret, struct volume *part, const char *path) {

+int ext2_open(struct ext2_file_handle *ret, struct part *part, const char *path) {

     ret->part = *part;

 

-    volume_read(&ret->part, &ret->sb, 1024, sizeof(struct ext2_superblock));

+    part_read(&ret->part, &ret->sb, 1024, sizeof(struct ext2_superblock));

 

     struct ext2_superblock *sb = &ret->sb;

 

@@ -330,7 +330,7 @@ int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t c
     return inode_read(buf, loc, count, &file->inode, file, file->alloc_map);

 }

 

-static struct ext4_extent_header* ext4_find_leaf(struct ext4_extent_header* ext_block, uint32_t read_block, uint64_t block_size, struct volume *part) {

+static struct ext4_extent_header* ext4_find_leaf(struct ext4_extent_header* ext_block, uint32_t read_block, uint64_t block_size, struct part *part) {

     struct ext4_extent_idx* index;

     void* buf = NULL;

 

@@ -357,7 +357,7 @@ static struct ext4_extent_header* ext4_find_leaf(struct ext4_extent_header* ext_
         uint64_t block = ((uint64_t)index[i].leaf_hi << 32) | index[i].leaf;

         if(!buf)

             buf = ext_mem_alloc(block_size);

-        volume_read(part, buf, (block * block_size), block_size);

+        part_read(part, buf, (block * block_size), block_size);

         ext_block = buf;

     }

 }

@@ -407,7 +407,7 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count,
             block_index = alloc_map[block];

         }

 

-        volume_read(&fd->part, buf + progress, (block_index * fd->block_size) + offset, chunk);

+        part_read(&fd->part, buf + progress, (block_index * fd->block_size) + offset, chunk);

 

         progress += chunk;

     }

@@ -417,9 +417,9 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count,
 

 // attempts to initialize the ext2 filesystem

 // and checks if all features are supported

-int ext2_check_signature(struct volume *part) {

+int ext2_check_signature(struct part *part) {

     struct ext2_superblock sb;

-    volume_read(part, &sb, 1024, sizeof(struct ext2_superblock));

+    part_read(part, &sb, 1024, sizeof(struct ext2_superblock));

 

     if (sb.s_magic != EXT2_S_MAGIC)

         return 0;

@@ -437,9 +437,9 @@ int ext2_check_signature(struct volume *part) {
     return 1;

 }

 

-bool ext2_get_guid(struct guid *guid, struct volume *part) {

+bool ext2_get_guid(struct guid *guid, struct part *part) {

     struct ext2_superblock sb;

-    volume_read(part, &sb, 1024, sizeof(struct ext2_superblock));

+    part_read(part, &sb, 1024, sizeof(struct ext2_superblock));

 

     if (sb.s_magic != EXT2_S_MAGIC)

         return false;

diff --git a/stage2/fs/ext2.h b/stage2/fs/ext2.h
index 4d33470c..1d18d92d 100644
--- a/stage2/fs/ext2.h
+++ b/stage2/fs/ext2.h
@@ -113,7 +113,7 @@ struct ext2_inode {
 } __attribute__((packed));

 

 struct ext2_file_handle {

-    struct volume part;

+    struct part part;

     struct ext2_superblock sb;

     int size;

     struct ext2_inode root_inode;

@@ -122,10 +122,10 @@ struct ext2_file_handle {
     uint32_t *alloc_map;

 };

 

-int ext2_check_signature(struct volume *part);

-bool ext2_get_guid(struct guid *guid, struct volume *part);

+int ext2_check_signature(struct part *part);

+bool ext2_get_guid(struct guid *guid, struct part *part);

 

-int ext2_open(struct ext2_file_handle *ret, struct volume *part, const char *path);

+int ext2_open(struct ext2_file_handle *ret, struct part *part, const char *path);

 int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count);

 

 #endif

diff --git a/stage2/fs/fat32.c b/stage2/fs/fat32.c
index 852365b2..287d0d87 100644
--- a/stage2/fs/fat32.c
+++ b/stage2/fs/fat32.c
@@ -67,12 +67,12 @@ struct fat32_lfn_entry {
     char name3[4];
 } __attribute__((packed));
 
-static int fat32_init_context(struct fat32_context* context, struct volume *part) {
+static int fat32_init_context(struct fat32_context* context, struct part *part) {
     context->part  = *part;
     context->drive = part->drive;
 
     struct fat32_bpb bpb;
-    volume_read(&context->part, &bpb, 0, sizeof(struct fat32_bpb));
+    part_read(&context->part, &bpb, 0, sizeof(struct fat32_bpb));
 
     if (bpb.signature != FAT32_VALID_SIGNATURE_1 && bpb.signature != FAT32_VALID_SIGNATURE_2) {
         return 1;
@@ -99,7 +99,7 @@ static int fat32_read_cluster_from_map(struct fat32_context* context, uint32_t c
     const uint32_t offset = cluster % (FAT32_SECTOR_SIZE / 4);
 
     uint32_t clusters[FAT32_SECTOR_SIZE / sizeof(uint32_t)];
-    int r = volume_read(&context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters));
+    int r = part_read(&context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters));
 
     if (r) {
         return r;
@@ -144,7 +144,7 @@ static bool read_cluster_chain(struct fat32_context *context,
             chunk = block_size - offset;
 
         uint64_t base = (context->data_start_lba + (cluster_chain[block] - 2)) * block_size;
-        int r = volume_read(&context->part, buf + progress, base + offset, chunk);
+        int r = part_read(&context->part, buf + progress, base + offset, chunk);
 
         if (r)
             return false;
@@ -253,12 +253,12 @@ static int fat32_open_in(struct fat32_context* context, struct fat32_directory_e
     return -1;
 }
 
-int fat32_check_signature(struct volume *part) {
+int fat32_check_signature(struct part *part) {
     struct fat32_context context;
     return fat32_init_context(&context, part) == 0;
 }
 
-int fat32_open(struct fat32_file_handle* ret, struct volume *part, const char* path) {
+int fat32_open(struct fat32_file_handle* ret, struct part *part, const char* path) {
     struct fat32_context context;
     int r = fat32_init_context(&context, part);
 
diff --git a/stage2/fs/fat32.h b/stage2/fs/fat32.h
index a560289d..a08bd392 100644
--- a/stage2/fs/fat32.h
+++ b/stage2/fs/fat32.h
@@ -6,7 +6,7 @@
 
 struct fat32_context {
     int drive;
-    struct volume part;
+    struct part part;
     uint8_t sectors_per_cluster;
     uint16_t reserved_sectors;
     uint8_t number_of_fats;
@@ -25,9 +25,9 @@ struct fat32_file_handle {
     uint32_t *cluster_chain;
 };
 
-int fat32_check_signature(struct volume *part);
+int fat32_check_signature(struct part *part);
 
-int fat32_open(struct fat32_file_handle *ret, struct volume *part, const char *path);
+int fat32_open(struct fat32_file_handle *ret, struct part *part, const char *path);
 int fat32_read(struct fat32_file_handle *file, void *buf, uint64_t loc, uint64_t count);
 
 #endif
diff --git a/stage2/fs/file.c b/stage2/fs/file.c
index fc0ca148..67069cd2 100644
--- a/stage2/fs/file.c
+++ b/stage2/fs/file.c
@@ -9,7 +9,7 @@
 #include <lib/part.h>
 #include <lib/libc.h>
 
-bool fs_get_guid(struct guid *guid, struct volume *part) {
+bool fs_get_guid(struct guid *guid, struct part *part) {
     if (echfs_check_signature(part)) {
         return echfs_get_guid(guid, part);
     }
@@ -20,7 +20,7 @@ bool fs_get_guid(struct guid *guid, struct volume *part) {
     return false;
 }
 
-int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
+int fopen(struct file_handle *ret, struct part *part, const char *filename) {
     ret->is_memfile = false;
 
     if (echfs_check_signature(part)) {
diff --git a/stage2/fs/file.h b/stage2/fs/file.h
index ac261f47..82a4c1ce 100644
--- a/stage2/fs/file.h
+++ b/stage2/fs/file.h
@@ -6,7 +6,7 @@
 #include <stdbool.h>
 #include <lib/part.h>
 
-bool fs_get_guid(struct guid *guid, struct volume *part);
+bool fs_get_guid(struct guid *guid, struct part *part);
 
 struct file_handle {
     bool       is_memfile;
@@ -15,7 +15,7 @@ struct file_handle {
     uint64_t   size;
 };
 
-int fopen(struct file_handle *ret, struct volume *part, const char *filename);
+int fopen(struct file_handle *ret, struct part *part, const char *filename);
 int fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count);
 void *freadall(struct file_handle *fd, uint32_t type);
 
diff --git a/stage2/lib/config.c b/stage2/lib/config.c
index c9c7fa9b..3ea37c38 100644
--- a/stage2/lib/config.c
+++ b/stage2/lib/config.c
@@ -16,7 +16,7 @@ bool config_ready = false;
 
 static char *config_addr;
 
-int init_config_disk(struct volume *part) {
+int init_config_disk(struct part *part) {
     struct file_handle f;
 
     if (fopen(&f, part, "/limine.cfg")
diff --git a/stage2/lib/config.h b/stage2/lib/config.h
index 711d191b..005ed91c 100644
--- a/stage2/lib/config.h
+++ b/stage2/lib/config.h
@@ -18,7 +18,7 @@ struct menu_entry {
 
 extern struct menu_entry *menu_tree;
 
-int init_config_disk(struct volume *part);
+int init_config_disk(struct part *part);
 int init_config_pxe(void);
 int init_config(size_t config_size);
 bool config_get_entry_name(char *ret, size_t index, size_t limit);
diff --git a/stage2/lib/part.c b/stage2/lib/part.c
index f88faf6c..1796ceb5 100644
--- a/stage2/lib/part.c
+++ b/stage2/lib/part.c
@@ -46,47 +46,27 @@ struct gpt_entry {
     uint16_t partition_name[36];
 } __attribute__((packed));
 
-static bool gpt_get_guid(struct guid *guid, struct volume *volume) {
+static int gpt_get_part(struct part *ret, int drive, int partition) {
     struct gpt_table_header header = {0};
 
-    int sector_size = disk_get_sector_size(volume->drive);
+    int sector_size = disk_get_sector_size(drive);
 
     // read header, located after the first block
-    volume_read(volume, &header, sector_size * 1, sizeof(header));
-
-    // check the header
-    // 'EFI PART'
-    if (strncmp(header.signature, "EFI PART", 8))
-        return false;
-    if (header.revision != 0x00010000)
-        return false;
-
-    *guid = header.disk_guid;
-
-    return true;
-}
-
-static int gpt_get_part(struct volume *ret, struct volume *volume, int partition) {
-    struct gpt_table_header header = {0};
-
-    int sector_size = disk_get_sector_size(volume->drive);
-
-    // read header, located after the first block
-    volume_read(volume, &header, sector_size * 1, sizeof(header));
+    disk_read(drive, &header, sector_size * 1, sizeof(header));
 
     // check the header
     // 'EFI PART'
     if (strncmp(header.signature, "EFI PART", 8))
         return INVALID_TABLE;
     if (header.revision != 0x00010000)
-        return INVALID_TABLE;
+        return END_OF_TABLE;
 
     // parse the entries if reached here
     if ((uint32_t)partition >= header.number_of_partition_entries)
         return END_OF_TABLE;
 
     struct gpt_entry entry = {0};
-    volume_read(volume, &entry,
+    disk_read(drive, &entry,
          (header.partition_entry_lba * sector_size) + (partition * sizeof(entry)),
          sizeof(entry));
 
@@ -94,7 +74,7 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
     if (!memcmp(&entry.unique_partition_guid, &empty_guid, sizeof(struct guid)))
         return NO_PARTITION;
 
-    ret->drive       = volume->drive;
+    ret->drive       = drive;
     ret->partition   = partition;
     ret->sector_size = sector_size;
     ret->first_sect  = entry.starting_lba;
@@ -123,8 +103,8 @@ struct mbr_entry {
 	uint32_t sect_count;
 } __attribute__((packed));
 
-static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part,
-                                int partition) {
+static int mbr_get_logical_part(struct part *ret, struct part *extended_part,
+                                int drive, int partition) {
     struct mbr_entry entry;
 
     size_t ebr_sector = 0;
@@ -133,7 +113,7 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
         size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1ce;
 
         int r;
-        r = volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
+        r = part_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
         if (r)
             return r;
 
@@ -146,16 +126,16 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
     size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1be;
 
     int r;
-    r = volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
+    r = part_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
     if (r)
         return r;
 
     if (entry.type == 0)
         return NO_PARTITION;
 
-    ret->drive       = extended_part->drive;
+    ret->drive       = drive;
     ret->partition   = partition + 4;
-    ret->sector_size = disk_get_sector_size(extended_part->drive);
+    ret->sector_size = disk_get_sector_size(drive);
     ret->first_sect  = extended_part->first_sect + ebr_sector + entry.first_sect;
     ret->sect_count  = entry.sect_count;
 
@@ -172,10 +152,10 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
     return 0;
 }
 
-static int mbr_get_part(struct volume *ret, struct volume *volume, int partition) {
+static int mbr_get_part(struct part *ret, int drive, int partition) {
     // Check if actually valid mbr
     uint16_t hint;
-    volume_read(volume, &hint, 444, sizeof(uint16_t));
+    disk_read(drive, &hint, 444, sizeof(uint16_t));
     if (hint && hint != 0x5a5a)
         return INVALID_TABLE;
 
@@ -185,22 +165,22 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
         for (int i = 0; i < 4; i++) {
             size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * i;
 
-            int r = volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry));
+            int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry));
             if (r)
                 return r;
 
             if (entry.type != 0x0f)
                 continue;
 
-            struct volume extended_part;
+            struct part extended_part;
 
-            extended_part.drive       = volume->drive;
+            extended_part.drive       = drive;
             extended_part.partition   = i;
-            extended_part.sector_size = disk_get_sector_size(volume->drive);
+            extended_part.sector_size = disk_get_sector_size(drive);
             extended_part.first_sect  = entry.first_sect;
             extended_part.sect_count  = entry.sect_count;
 
-            return mbr_get_logical_part(ret, &extended_part, partition - 4);
+            return mbr_get_logical_part(ret, &extended_part, drive, partition - 4);
         }
 
         return END_OF_TABLE;
@@ -208,16 +188,16 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
 
     size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition;
 
-    int r = volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry));
+    int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry));
     if (r)
         return r;
 
     if (entry.type == 0)
         return NO_PARTITION;
 
-    ret->drive       = volume->drive;
+    ret->drive       = drive;
     ret->partition   = partition;
-    ret->sector_size = disk_get_sector_size(volume->drive);
+    ret->sector_size = disk_get_sector_size(drive);
     ret->first_sect  = entry.first_sect;
     ret->sect_count  = entry.sect_count;
 
@@ -234,26 +214,24 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
     return 0;
 }
 
-int part_get(struct volume *part, struct volume *volume, int partition) {
+int part_get(struct part *part, int drive, int partition) {
     int ret;
 
-    ret = gpt_get_part(part, volume, partition);
+    ret = gpt_get_part(part, drive, partition);
     if (ret != INVALID_TABLE)
         return ret;
 
-    ret = mbr_get_part(part, volume, partition);
+    ret = mbr_get_part(part, drive, partition);
     if (ret != INVALID_TABLE)
         return ret;
 
     return INVALID_TABLE;
 }
 
-static struct volume *volume_index = NULL;
-static size_t volume_index_i = 0;
-
-void volume_create_index(void) {
-    size_t volume_count = 0;
+static struct part *part_index = NULL;
+static size_t part_index_i = 0;
 
+void part_create_index(void) {
     for (uint8_t drive = 0x80; drive < 0x8f; drive++) {
         struct rm_regs r = {0};
         struct bios_drive_params drive_params;
@@ -274,105 +252,51 @@ void volume_create_index(void) {
         print(" ... %X total %u-byte sectors\n",
               drive_params.lba_count, drive_params.bytes_per_sect);
 
-        volume_count++;
-
-        struct volume block;
-
-        block.drive = drive;
-        block.sector_size = drive_params.bytes_per_sect;
-        block.first_sect = 0;
-        block.sect_count = drive_params.lba_count;
+        size_t part_count = 0;
 
+load_up:
         for (int part = 0; ; part++) {
-            struct volume p;
-            int ret = part_get(&p, &block, part);
+            struct part p;
+            int ret = part_get(&p, drive, part);
 
-            if (ret == END_OF_TABLE || ret == INVALID_TABLE)
+            if (ret == END_OF_TABLE)
                 break;
             if (ret == NO_PARTITION)
                 continue;
 
-            volume_count++;
-        }
-    }
-
-    volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
-
-    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;
-
-        struct volume *block = &volume_index[volume_index_i++];
-
-        block->drive = drive;
-        block->partition = -1;
-        block->sector_size = drive_params.bytes_per_sect;
-        block->first_sect = 0;
-        block->sect_count = drive_params.lba_count;
-
-        if (gpt_get_guid(&block->guid, block)) {
-            block->guid_valid = true;
+            if (part_index)
+                part_index[part_index_i++] = p;
+            else
+                part_count++;
         }
 
-        for (int part = 0; ; part++) {
-            struct volume p;
-            int ret = part_get(&p, block, part);
-
-            if (ret == END_OF_TABLE || ret == INVALID_TABLE)
-                break;
-            if (ret == NO_PARTITION)
-                continue;
+        if (part_index)
+            return;
 
-            volume_index[volume_index_i++] = p;
-        }
+        part_index = ext_mem_alloc(sizeof(struct part) * part_count);
+        goto load_up;
     }
 }
 
-bool volume_get_by_guid(struct volume *part, struct guid *guid) {
+bool part_get_by_guid(struct part *part, struct guid *guid) {
     size_t i;
-    for (i = 0; i < volume_index_i; i++) {
-        if (volume_index[i].guid_valid
-         && memcmp(&volume_index[i].guid, guid, 16) == 0) {
-            goto found;
-        }
-        if (volume_index[i].part_guid_valid
-         && memcmp(&volume_index[i].part_guid, guid, 16) == 0) {
+    for (i = 0; i < part_index_i; i++) {
+        if (part_index[i].guid_valid
+         && memcmp(&part_index[i].guid, guid, 16) == 0) {
             goto found;
         }
-    }
-    return false;
-found:
-    *part = volume_index[i];
-    return true;
-}
-
-bool volume_get_by_coord(struct volume *part, int drive, int partition) {
-    size_t i;
-    for (i = 0; i < volume_index_i; i++) {
-        if (volume_index[i].drive == drive
-         && volume_index[i].partition == partition) {
+        if (part_index[i].part_guid_valid
+         && memcmp(&part_index[i].part_guid, guid, 16) == 0) {
             goto found;
         }
     }
     return false;
 found:
-    *part = volume_index[i];
+    *part = part_index[i];
     return true;
 }
 
-int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count) {
+int part_read(struct part *part, void *buffer, uint64_t loc, uint64_t count) {
     return disk_read(part->drive, buffer,
                      loc + (part->first_sect * part->sector_size), count);
 }
diff --git a/stage2/lib/part.h b/stage2/lib/part.h
index 38dfbc7f..7be0e712 100644
--- a/stage2/lib/part.h
+++ b/stage2/lib/part.h
@@ -9,7 +9,7 @@
 #define INVALID_TABLE (-2)
 #define END_OF_TABLE  (-3)
 
-struct volume {
+struct part {
     int drive;
     int partition;
     int sector_size;
@@ -21,12 +21,11 @@ struct volume {
     struct guid part_guid;
 };
 
-void volume_create_index(void);
+void part_create_index(void);
 
-int part_get(struct volume *part, struct volume *volume, int partition);
-bool volume_get_by_guid(struct volume *part, struct guid *guid);
-bool volume_get_by_coord(struct volume *part, int drive, int partition);
+int part_get(struct part *part, int drive, int partition);
+bool part_get_by_guid(struct part *part, struct guid *guid);
 
-int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count);
+int part_read(struct part *part, void *buffer, uint64_t loc, uint64_t count);
 
 #endif
diff --git a/stage2/lib/uri.c b/stage2/lib/uri.c
index 152a76c3..02cad9a1 100644
--- a/stage2/lib/uri.c
+++ b/stage2/lib/uri.c
@@ -97,11 +97,11 @@ static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) {
     if (!parse_bios_partition(loc, &drive, &partition))
         return false;
 
-    struct volume volume;
-    if (!volume_get_by_coord(&volume, drive, partition))
+    struct part part;
+    if (part_get(&part, drive, partition))
         return false;
 
-    if (fopen(fd, &volume, path))
+    if (fopen(fd, &part, path))
         return false;
 
     return true;
@@ -112,12 +112,12 @@ static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path
     if (!string_to_guid_be(&guid, guid_str))
         return false;
 
-    struct volume part;
-    if (!volume_get_by_guid(&part, &guid)) {
+    struct part part;
+    if (!part_get_by_guid(&part, &guid)) {
         if (!string_to_guid_mixed(&guid, guid_str))
             return false;
 
-        if (!volume_get_by_guid(&part, &guid))
+        if (!part_get_by_guid(&part, &guid))
             return false;
     }
 
@@ -170,8 +170,8 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path)
         }
     }
 
-    struct volume part;
-    if (!volume_get_by_coord(&part, boot_drive, partition))
+    struct part part;
+    if (part_get(&part, boot_drive, partition))
         return false;
 
     if (fopen(fd, &part, path))
diff --git a/stage2/main.c b/stage2/main.c
index d91657f6..f91824ca 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -39,7 +39,7 @@ void entry(uint8_t _boot_drive, int pxe_boot, void *_tinf_gzip_uncompress) {
     init_e820();
     init_memmap();
 
-    volume_create_index();
+    part_create_index();
 
     if (pxe_boot) {
         pxe_init();
@@ -52,8 +52,8 @@ void entry(uint8_t _boot_drive, int pxe_boot, void *_tinf_gzip_uncompress) {
         // Look for config file.
         print("Searching for config file...\n");
         for (int i = 0; ; i++) {
-            struct volume part;
-            int ret = volume_get_by_coord(&part, boot_drive, i);
+            struct part part;
+            int ret = part_get(&part, boot_drive, i);
             switch (ret) {
                 case INVALID_TABLE:
                     panic("Partition table of boot drive is invalid.");
diff --git a/stage2/protos/chainload.c b/stage2/protos/chainload.c
index 8bcc66eb..8048e100 100644
--- a/stage2/protos/chainload.c
+++ b/stage2/protos/chainload.c
@@ -75,10 +75,14 @@ void chainload(char *config) {
 
     term_deinit();
 
-    struct volume p;
-    volume_get_by_coord(&p, drive, part);
+    if (part != -1) {
+        struct part p;
+        part_get(&p, drive, part);
 
-    volume_read(&p, (void *)0x7c00, 0, 512);
+        part_read(&p, (void *)0x7c00, 0, 512);
+    } else {
+        disk_read(drive, (void *)0x7c00, 0, 512);
+    }
 
     mtrr_restore();
 
tab: 248 wrap: offon