diff --git a/stage23/drivers/disk.h b/stage23/drivers/disk.h index 4df24a71..7df6b71a 100644 --- a/stage23/drivers/disk.h +++ b/stage23/drivers/disk.h @@ -10,11 +10,11 @@ #include -bool disk_volume_from_efi_handle(struct volume *ret, EFI_HANDLE *efi_handle); +struct volume *disk_volume_from_efi_handle(EFI_HANDLE *efi_handle); #endif -size_t disk_create_index(struct volume **ret); +void disk_create_index(void); bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t count); #endif diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c index b67b7bf1..7e347d7d 100644 --- a/stage23/drivers/disk.s2.c +++ b/stage23/drivers/disk.s2.c @@ -80,9 +80,8 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t return true; } -size_t disk_create_index(struct volume **ret) { - struct volume *volume_index; - size_t volume_count = 0, volume_index_i = 0; +void disk_create_index(void) { + size_t volume_count = 0; for (uint8_t drive = 0x80; drive; drive++) { struct rm_regs r = {0}; @@ -104,8 +103,6 @@ size_t disk_create_index(struct volume **ret) { print(" ... %X total %u-byte sectors\n", drive_params.lba_count, drive_params.bytes_per_sect); - volume_count++; - struct volume block = {0}; block.drive = drive; @@ -120,6 +117,8 @@ size_t disk_create_index(struct volume **ret) { continue; } + volume_count++; + for (int part = 0; ; part++) { struct volume p = {0}; int ret = part_get(&p, &block, part); @@ -151,7 +150,7 @@ size_t disk_create_index(struct volume **ret) { if (r.eflags & EFLAGS_CF) continue; - struct volume *block = &volume_index[volume_index_i++]; + struct volume *block = ext_mem_alloc(sizeof(struct volume)); block->drive = drive; block->partition = -1; @@ -165,13 +164,15 @@ size_t disk_create_index(struct volume **ret) { continue; } + volume_index[volume_index_i++] = block; + if (gpt_get_guid(&block->guid, block)) { block->guid_valid = true; } for (int part = 0; ; part++) { - struct volume p = {0}; - int ret = part_get(&p, block, part); + struct volume *p = ext_mem_alloc(sizeof(struct volume)); + int ret = part_get(p, block, part); if (ret == END_OF_TABLE || ret == INVALID_TABLE) break; @@ -181,17 +182,14 @@ size_t disk_create_index(struct volume **ret) { volume_index[volume_index_i++] = p; } } - - *ret = volume_index; - return volume_count; } #endif #if defined (uefi) -bool disk_volume_from_efi_handle(struct volume *ret, EFI_HANDLE *efi_handle) { - bool ok = false; +struct volume *disk_volume_from_efi_handle(EFI_HANDLE *efi_handle) { + struct volume *ret = NULL; EFI_GUID disk_io_guid = DISK_IO_PROTOCOL; EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL; @@ -217,20 +215,19 @@ bool disk_volume_from_efi_handle(struct volume *ret, EFI_HANDLE *efi_handle) { EFI_DISK_IO *cur_disk_io = NULL; EFI_BLOCK_IO *cur_block_io = NULL; - uefi_call_wrapper(gBS->HandleProtocol, 3, volume_index[i].drive, + uefi_call_wrapper(gBS->HandleProtocol, 3, volume_index[i]->efi_handle, &disk_io_guid, &cur_disk_io); - uefi_call_wrapper(gBS->HandleProtocol, 3, volume_index[i].drive, + uefi_call_wrapper(gBS->HandleProtocol, 3, volume_index[i]->efi_handle, &block_io_guid, &cur_block_io); uefi_call_wrapper(cur_disk_io->ReadDisk, 5, cur_disk_io, cur_block_io->Media->MediaId, 0 + - volume_index[i].first_sect * volume_index[i].sector_size, + volume_index[i]->first_sect * volume_index[i]->sector_size, sizeof(uint64_t), &compare); if (compare == signature) { - *ret = volume_index[i]; - ok = true; + ret = volume_index[i]; break; } } @@ -238,7 +235,7 @@ bool disk_volume_from_efi_handle(struct volume *ret, EFI_HANDLE *efi_handle) { uefi_call_wrapper(disk_io->WriteDisk, 5, disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &orig); - return ok; + return ret; } bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t count) { @@ -247,7 +244,7 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL; EFI_BLOCK_IO *block_io = NULL; - status = uefi_call_wrapper(gBS->HandleProtocol, 3, volume->drive, + status = uefi_call_wrapper(gBS->HandleProtocol, 3, volume->efi_handle, &block_io_guid, &block_io); status = uefi_call_wrapper(block_io->ReadBlocks, 5, block_io, @@ -261,11 +258,9 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t return true; } -size_t disk_create_index(struct volume **ret) { +void disk_create_index(void) { EFI_STATUS status; - struct volume *volume_index = NULL; - size_t volume_index_i = 0; size_t volume_count = 0; EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL; @@ -296,14 +291,14 @@ size_t disk_create_index(struct volume **ret) { volume_count++; - block.drive = handles[i]; + block.efi_handle = handles[i]; block.sector_size = block_io->Media->BlockSize; block.first_sect = 0; block.sect_count = block_io->Media->LastBlock + 1; for (int part = 0; ; part++) { - struct volume p = {0}; - int ret = part_get(&p, &block, part); + struct volume trash = {0}; + int ret = part_get(&trash, &block, part); if (ret == END_OF_TABLE || ret == INVALID_TABLE) break; @@ -316,6 +311,8 @@ size_t disk_create_index(struct volume **ret) { volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count); + size_t drives_counter = 0x80; + for (size_t i = 0; i < handles_size / sizeof(EFI_HANDLE); i++) { EFI_BLOCK_IO *drive = NULL; @@ -328,17 +325,20 @@ size_t disk_create_index(struct volume **ret) { if (drive->Media->LogicalPartition) continue; - struct volume *block = &volume_index[volume_index_i++]; + struct volume *block = ext_mem_alloc(sizeof(struct volume)); - block->drive = handles[i]; + block->drive = drives_counter++; + block->efi_handle = handles[i]; block->partition = -1; block->sector_size = drive->Media->BlockSize; block->first_sect = 0; block->sect_count = drive->Media->LastBlock + 1; + volume_index[volume_index_i++] = block; + for (int part = 0; ; part++) { - struct volume p = {0}; - int ret = part_get(&p, block, part); + struct volume *p = ext_mem_alloc(sizeof(struct volume)); + int ret = part_get(p, block, part); if (ret == END_OF_TABLE || ret == INVALID_TABLE) break; @@ -348,9 +348,6 @@ size_t disk_create_index(struct volume **ret) { volume_index[volume_index_i++] = p; } } - - *ret = volume_index; - return volume_count; } #endif diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c index 6fba5037..12136efb 100644 --- a/stage23/entry.s2.c +++ b/stage23/entry.s2.c @@ -19,11 +19,12 @@ #include #include #include +#include extern uint64_t stage3_build_id; -drive_t boot_drive; -int boot_partition = -1; +int boot_drive; +int boot_partition = -1; bool booted_from_pxe = false; bool booted_from_cd = false; @@ -79,29 +80,18 @@ void entry(uint8_t _boot_drive, int boot_from) { init_e820(); init_memmap(); - volume_create_index(); + disk_create_index(); - switch (boot_from) { - case BOOT_FROM_HDD: - case BOOT_FROM_CD: { - struct volume boot_volume = {0}; - volume_get_by_coord(&boot_volume, boot_drive, -1); - struct volume part = boot_volume; - for (int i = 0; ; i++) { - if (stage3_init(&part)) { - print("Stage 3 found and loaded.\n"); - break; - } - int ret = part_get(&part, &boot_volume, i); - switch (ret) { - case INVALID_TABLE: - case END_OF_TABLE: - panic("Stage 3 not found."); - } - } + struct volume *boot_volume = volume_get_by_coord(boot_drive, -1); + + volume_iterate_parts(boot_volume, + if (stage3_init(_PART)) { break; } - } + ); + + if (!stage3_loaded) + panic("Failed to load stage 3.\n"); __attribute__((noreturn)) void (*stage3)(int boot_from) = (void *)stage3_addr; diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index 5fe6ec70..eab5371f 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -31,7 +31,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable print("Limine " LIMINE_VERSION "\n\n", print); - volume_create_index(); + disk_create_index(); EFI_GUID loaded_img_prot_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_LOADED_IMAGE_PROTOCOL *loaded_image = NULL; @@ -39,23 +39,54 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable uefi_call_wrapper(gBS->HandleProtocol, 3, ImageHandle, &loaded_img_prot_guid, &loaded_image); - struct volume boot_volume = {0}; - if (!disk_volume_from_efi_handle(&boot_volume, loaded_image->DeviceHandle)) { + struct volume *boot_volume = disk_volume_from_efi_handle(loaded_image->DeviceHandle); + if (boot_volume == NULL) { panic("Can't determine boot disk"); } - if (!volume_iterate_parts(boot_volume, - if (!init_config_disk(&_PART_)) { - print("Config file found and loaded.\n"); - boot_partition = _PARTNUM_; - break; + if (boot_volume->backing_dev != NULL) { + boot_volume = boot_volume->backing_dev; + + int part_cnt = 0; + for (size_t i = 0; ; i++) { + if (part_cnt > boot_volume->max_partition) + break; + + struct volume *volume = volume_get_by_coord(boot_volume->drive, i); + if (volume == NULL) + continue; + + part_cnt++; + + if (!init_config_disk(volume)) { + print("Config file found and loaded.\n"); + boot_partition = i; + boot_drive = boot_volume->drive; + goto config_loaded; + } } - )) { + + panic("Config file not found."); + } else { + struct volume *volume = volume_get_by_coord(boot_volume->drive, -1); + if (volume == NULL) + panic("Config file not found."); + + if (!init_config_disk(volume)) { + print("Config file found and loaded.\n"); + boot_partition = -1; + boot_drive = boot_volume->drive; + goto config_loaded; + } + panic("Config file not found."); } - for (;;); - //stage3_common(); +config_loaded: + print("Boot drive: %x\n", boot_drive); + print("Boot partition: %d\n", boot_partition); + + stage3_common(); } #endif @@ -66,33 +97,20 @@ uint64_t stage3_build_id = BUILD_ID; __attribute__((noreturn)) __attribute__((section(".stage3_entry"))) void stage3_entry(int boot_from) { + (void)boot_from; + mtrr_save(); - switch (boot_from) { - case BOOT_FROM_HDD: - case BOOT_FROM_CD: { - struct volume boot_volume = {0}; - volume_get_by_coord(&boot_volume, boot_drive, -1); + struct volume *boot_volume = volume_get_by_coord(boot_drive, -1); - if (!volume_iterate_parts(boot_volume, - if (!init_config_disk(&_PART_)) { - print("Config file found and loaded.\n"); - boot_partition = _PARTNUM_; - break; - } - )) { - panic("Config file not found."); - } - break; - case BOOT_FROM_PXE: - pxe_init(); - if (init_config_pxe()) { - panic("Failed to load config file"); - } - print("Config loaded via PXE\n"); + volume_iterate_parts(boot_volume, + if (!init_config_disk(_PART)) { + print("Config file found and loaded.\n"); + boot_partition = _PARTNO; + boot_drive = _PART->drive; break; } - } + ); stage3_common(); } diff --git a/stage23/fs/echfs.h b/stage23/fs/echfs.h index 92f221c9..38a684eb 100644 --- a/stage23/fs/echfs.h +++ b/stage23/fs/echfs.h @@ -21,7 +21,7 @@ struct echfs_dir_entry { } __attribute__((packed)); struct echfs_file_handle { - struct volume part; + struct volume *part; uint64_t block_size; uint64_t block_count; uint64_t dir_length; diff --git a/stage23/fs/echfs.s2.c b/stage23/fs/echfs.s2.c index 4e1428b6..5c2cfeef 100644 --- a/stage23/fs/echfs.s2.c +++ b/stage23/fs/echfs.s2.c @@ -23,7 +23,7 @@ struct echfs_identity_table { #define DIR_TYPE 1 static bool 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 volume_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) { @@ -69,10 +69,10 @@ bool echfs_get_guid(struct guid *guid, struct volume *part) { int echfs_open(struct echfs_file_handle *ret, struct volume *part, const char *path) { const char *fullpath = path; - ret->part = *part; + ret->part = part; struct echfs_identity_table id_table; - volume_read(&ret->part, &id_table, 0, sizeof(struct echfs_identity_table)); + volume_read(ret->part, &id_table, 0, sizeof(struct echfs_identity_table)); if (strncmp(id_table.signature, "_ECH_FS_", 8)) { print("echfs: signature invalid\n"); @@ -105,7 +105,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)); + volume_read(ret->part, &ret->dir_entry, i + ret->dir_offset, sizeof(struct echfs_dir_entry)); if (!ret->dir_entry.parent_id) { break; @@ -135,7 +135,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, + volume_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/stage23/fs/ext2.h b/stage23/fs/ext2.h index 540c55cc..e9541a09 100644 --- a/stage23/fs/ext2.h +++ b/stage23/fs/ext2.h @@ -113,7 +113,7 @@ struct ext2_inode { } __attribute__((packed)); struct ext2_file_handle { - struct volume part; + struct volume *part; struct ext2_superblock sb; int size; struct ext2_inode root_inode; diff --git a/stage23/fs/ext2.s2.c b/stage23/fs/ext2.s2.c index a809aaf4..7f429a74 100644 --- a/stage23/fs/ext2.s2.c +++ b/stage23/fs/ext2.s2.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)); + volume_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)); + volume_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)); + volume_read(fd->part, ret, ino_offset, sizeof(struct ext2_inode)); return true; } @@ -184,7 +184,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd, } uint32_t indirect_block; volume_read( - &fd->part, &indirect_block, + fd->part, &indirect_block, inode->i_blocks[13] * fd->block_size + index * sizeof(uint32_t), sizeof(uint32_t) ); @@ -192,7 +192,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd, if (i + j >= inode->i_blocks_count) return alloc_map; volume_read( - &fd->part, &alloc_map[i + j], + fd->part, &alloc_map[i + j], indirect_block * fd->block_size + j * sizeof(uint32_t), sizeof(uint32_t) ); @@ -201,7 +201,7 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd, } else { // Single indirect block volume_read( - &fd->part, &alloc_map[i], + fd->part, &alloc_map[i], inode->i_blocks[12] * fd->block_size + block * sizeof(uint32_t), sizeof(uint32_t) ); @@ -289,9 +289,9 @@ next: } int ext2_open(struct ext2_file_handle *ret, struct volume *part, const char *path) { - ret->part = *part; + ret->part = part; - volume_read(&ret->part, &ret->sb, 1024, sizeof(struct ext2_superblock)); + volume_read(ret->part, &ret->sb, 1024, sizeof(struct ext2_superblock)); struct ext2_superblock *sb = &ret->sb; @@ -380,7 +380,7 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count, struct ext4_extent *ext; int i; - leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_blocks, block, fd->block_size, &fd->part); + leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_blocks, block, fd->block_size, fd->part); if (!leaf) panic("invalid extent"); @@ -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); + volume_read(fd->part, buf + progress, (block_index * fd->block_size) + offset, chunk); progress += chunk; } diff --git a/stage23/fs/fat32.h b/stage23/fs/fat32.h index abd56adb..55f401ec 100644 --- a/stage23/fs/fat32.h +++ b/stage23/fs/fat32.h @@ -5,7 +5,7 @@ #include struct fat32_context { - struct volume part; + struct volume *part; uint8_t sectors_per_cluster; uint16_t reserved_sectors; uint8_t number_of_fats; diff --git a/stage23/fs/fat32.s2.c b/stage23/fs/fat32.s2.c index 0433486a..06ffe1d2 100644 --- a/stage23/fs/fat32.s2.c +++ b/stage23/fs/fat32.s2.c @@ -68,10 +68,10 @@ struct fat32_lfn_entry { } __attribute__((packed)); static int fat32_init_context(struct fat32_context* context, struct volume *part) { - context->part = *part; + context->part = part; struct fat32_bpb bpb; - volume_read(&context->part, &bpb, 0, sizeof(struct fat32_bpb)); + volume_read(context->part, &bpb, 0, sizeof(struct fat32_bpb)); if (bpb.signature != FAT32_VALID_SIGNATURE_1 && bpb.signature != FAT32_VALID_SIGNATURE_2) { return 1; @@ -98,7 +98,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)]; - volume_read(&context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters)); + volume_read(context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters)); *out = clusters[offset] & 0x0FFFFFFF; return 0; @@ -139,7 +139,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; - volume_read(&context->part, buf + progress, base + offset, chunk); + volume_read(context->part, buf + progress, base + offset, chunk); progress += chunk; } diff --git a/stage23/fs/iso9660.h b/stage23/fs/iso9660.h index 02c5552a..2819f325 100644 --- a/stage23/fs/iso9660.h +++ b/stage23/fs/iso9660.h @@ -7,7 +7,7 @@ #define ISO9660_SECTOR_SIZE (2 << 10) struct iso9660_context { - struct volume vol; + struct volume *vol; void* root; uint32_t root_size; }; diff --git a/stage23/fs/iso9660.s2.c b/stage23/fs/iso9660.s2.c index c949d310..6c4086fd 100644 --- a/stage23/fs/iso9660.s2.c +++ b/stage23/fs/iso9660.s2.c @@ -108,14 +108,14 @@ static void iso9660_cache_root(struct volume *vol, static struct iso9660_context *iso9660_get_context(struct volume *vol) { struct iso9660_contexts_node *current = contexts; while (current) { - if (current->context.vol.drive == vol->drive) + if (current->context.vol == vol) return ¤t->context; current = current->next; } // The context is not cached at this point struct iso9660_contexts_node *node = ext_mem_alloc(sizeof(struct iso9660_contexts_node)); - node->context.vol = *vol; + node->context.vol = vol; iso9660_cache_root(vol, &node->context.root, &node->context.root_size); node->next = contexts; @@ -211,6 +211,6 @@ int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol, const char } int iso9660_read(struct iso9660_file_handle *file, void *buf, uint64_t loc, uint64_t count) { - volume_read(&file->context->vol, buf, file->LBA * ISO9660_SECTOR_SIZE + loc, count); + volume_read(file->context->vol, buf, file->LBA * ISO9660_SECTOR_SIZE + loc, count); return 0; } diff --git a/stage23/lib/blib.h b/stage23/lib/blib.h index cedff14c..9501947a 100644 --- a/stage23/lib/blib.h +++ b/stage23/lib/blib.h @@ -16,8 +16,8 @@ extern EFI_BOOT_SERVICES *gBS; extern EFI_RUNTIME_SERVICES *gRT; #endif -extern drive_t boot_drive; -extern int boot_partition; +extern int boot_drive; +extern int boot_partition; extern bool booted_from_pxe; extern bool booted_from_cd; diff --git a/stage23/lib/part.h b/stage23/lib/part.h index 2abaa6bd..38c26be8 100644 --- a/stage23/lib/part.h +++ b/stage23/lib/part.h @@ -13,57 +13,62 @@ #define INVALID_TABLE (-2) #define END_OF_TABLE (-3) -#if defined (bios) -typedef int drive_t; -#elif defined (uefi) -typedef EFI_HANDLE drive_t; +struct volume { +#if defined (uefi) + EFI_HANDLE efi_handle; #endif -struct volume { - drive_t drive; + int drive; int partition; int sector_size; + struct volume *backing_dev; + + int max_partition; + int cache_status; uint8_t *cache; uint64_t cached_block; + uint64_t first_sect; uint64_t sect_count; + bool guid_valid; struct guid guid; bool part_guid_valid; struct guid part_guid; }; -extern struct volume *volume_index; +extern struct volume **volume_index; extern size_t volume_index_i; -void volume_create_index(void); - bool gpt_get_guid(struct guid *guid, struct volume *volume); 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, drive_t drive, int partition); + +struct volume *volume_get_by_guid(struct guid *guid); +struct volume *volume_get_by_coord(int drive, int partition); bool volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count); #define volume_iterate_parts(_VOLUME_, _BODY_) ({ \ - bool _OK_ = true; \ - struct volume _PART_ = _VOLUME_; \ - for (int i = 0; ; i++) { \ - int _PARTNUM_ = i - 1; \ - _BODY_ ; \ - switch (part_get(&_PART_, &_VOLUME_, i)) { \ - case INVALID_TABLE: \ - case END_OF_TABLE: \ - _OK_ = false; \ - break; \ - default: \ - continue; \ - } \ - break; \ - } \ - _OK_; \ + struct volume *_VOLUME = _VOLUME_; \ + while (_VOLUME->backing_dev != NULL) { \ + _VOLUME = _VOLUME->backing_dev; \ + } \ + \ + int _PART_CNT = -1; \ + for (size_t _PARTNO = -1; ; _PARTNO++) { \ + if (_PART_CNT > _VOLUME->max_partition) \ + break; \ + \ + struct volume *_PART = volume_get_by_coord(_VOLUME->drive, _PARTNO); \ + if (_PART == NULL) \ + continue; \ + \ + _PART_CNT++; \ + \ + _BODY_ \ + } \ }) #endif diff --git a/stage23/lib/part.s2.c b/stage23/lib/part.s2.c index 9450fc9c..7d918f0a 100644 --- a/stage23/lib/part.s2.c +++ b/stage23/lib/part.s2.c @@ -147,11 +147,15 @@ 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; +#if defined (uefi) + ret->efi_handle = volume->efi_handle; +#endif ret->drive = volume->drive; ret->partition = partition; ret->sector_size = sector_size; ret->first_sect = entry.starting_lba; ret->sect_count = (entry.ending_lba - entry.starting_lba) + 1; + ret->backing_dev = volume; struct guid guid; if (!fs_get_guid(&guid, ret)) { @@ -200,11 +204,15 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part if (entry.type == 0) return NO_PARTITION; +#if defined (uefi) + ret->efi_handle = extended_part->efi_handle; +#endif ret->drive = extended_part->drive; ret->partition = partition + 4; ret->sector_size = extended_part->sector_size; ret->first_sect = extended_part->first_sect + ebr_sector + entry.first_sect; ret->sect_count = entry.sect_count; + ret->backing_dev = extended_part->backing_dev; struct guid guid; if (!fs_get_guid(&guid, ret)) { @@ -239,11 +247,15 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition struct volume extended_part = {0}; +#if defined (uefi) + extended_part.efi_handle = volume->efi_handle; +#endif extended_part.drive = volume->drive; extended_part.partition = i; extended_part.sector_size = volume->sector_size; extended_part.first_sect = entry.first_sect; extended_part.sect_count = entry.sect_count; + extended_part.backing_dev = volume; return mbr_get_logical_part(ret, &extended_part, partition - 4); } @@ -258,11 +270,15 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition if (entry.type == 0) return NO_PARTITION; +#if defined (uefi) + ret->efi_handle = volume->efi_handle; +#endif ret->drive = volume->drive; ret->partition = partition; ret->sector_size = volume->sector_size; ret->first_sect = entry.first_sect; ret->sect_count = entry.sect_count; + ret->backing_dev = volume; struct guid guid; if (!fs_get_guid(&guid, ret)) { @@ -291,41 +307,31 @@ int part_get(struct volume *part, struct volume *volume, int partition) { return INVALID_TABLE; } -struct volume *volume_index = NULL; +struct volume **volume_index = NULL; size_t volume_index_i = 0; -void volume_create_index(void) { - volume_index_i = disk_create_index(&volume_index); -} - -bool volume_get_by_guid(struct volume *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; +struct volume *volume_get_by_guid(struct guid *guid) { + for (size_t i = 0; i < volume_index_i; i++) { + if (volume_index[i]->guid_valid + && memcmp(&volume_index[i]->guid, guid, 16) == 0) { + return volume_index[i]; } - if (volume_index[i].part_guid_valid - && memcmp(&volume_index[i].part_guid, guid, 16) == 0) { - goto found; + if (volume_index[i]->part_guid_valid + && memcmp(&volume_index[i]->part_guid, guid, 16) == 0) { + return volume_index[i]; } } - return false; -found: - *part = volume_index[i]; - return true; + + return NULL; } -bool volume_get_by_coord(struct volume *part, drive_t 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) { - goto found; +struct volume *volume_get_by_coord(int drive, int partition) { + for (size_t i = 0; i < volume_index_i; i++) { + if (volume_index[i]->drive == drive + && volume_index[i]->partition == partition) { + return volume_index[i]; } } - return false; -found: - *part = volume_index[i]; - return true; + + return NULL; } diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c index 705de6dd..78c0cf96 100644 --- a/stage23/lib/uri.c +++ b/stage23/lib/uri.c @@ -95,14 +95,14 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { uint8_t drive, partition; - struct volume volume = {0}; if (!parse_bios_partition(loc, &drive, &partition)) return false; - if (!volume_get_by_coord(&volume, drive, partition)) + struct volume *volume = volume_get_by_coord(drive, partition); + if (volume == NULL) return false; - if (fopen(fd, &volume, path)) + if (fopen(fd, volume, path)) return false; return true; @@ -114,16 +114,17 @@ 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 = {0}; - if (!volume_get_by_guid(&part, &guid)) { + struct volume *volume = volume_get_by_guid(&guid); + if (volume == NULL) { if (!string_to_guid_mixed(&guid, guid_str)) return false; - if (!volume_get_by_guid(&part, &guid)) + volume = volume_get_by_guid(&guid); + if (volume == NULL) return false; } - if (fopen(fd, &part, path)) + if (fopen(fd, volume, path)) return false; return true; @@ -174,11 +175,11 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path) panic("Boot partition information is unavailable."); } - struct volume part = {0}; - if (!volume_get_by_coord(&part, boot_drive, partition)) + struct volume *volume = volume_get_by_coord(boot_drive, partition); + if (volume == NULL) return false; - if (fopen(fd, &part, path)) + if (fopen(fd, volume, path)) return false; return true; diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c index e6e2f172..f407e35d 100644 --- a/stage23/protos/chainload.c +++ b/stage23/protos/chainload.c @@ -77,10 +77,9 @@ void chainload(char *config) { term_deinit(); - struct volume p = {0}; - volume_get_by_coord(&p, drive, part); + struct volume *p = volume_get_by_coord(drive, part); - volume_read(&p, (void *)0x7c00, 0, 512); + volume_read(p, (void *)0x7c00, 0, 512); mtrr_restore();