mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-23 22:36:48 +03:00
Add GUID resource type
This commit is contained in:
parent
28c1538f94
commit
038c041208
@ -63,3 +63,4 @@ The format for `root` changes depending on the resource used.
|
||||
|
||||
A resource can be one of the following:
|
||||
* `bios` - The `root` takes the form of `drive:partition`; for example: `bios://3:1/...` would use BIOS drive 3, partition 1. Partitions and BIOS drives are both 1-based. Omitting the drive is possible; for example: `bios://:2/...`. Omitting the drive makes Limine use the boot drive.
|
||||
* `guid` - The `root` takes the form of a GUID/UUID, such as `736b5698-5ae1-4dff-be2c-ef8f44a61c52`. It is a filesystem GUID and not a partition GUID.
|
||||
|
6
Makefile
6
Makefile
@ -43,9 +43,11 @@ test.img:
|
||||
|
||||
echfs-test: limine-install test.img
|
||||
$(MAKE) -C test
|
||||
echfs-utils -m -p0 test.img quick-format 512
|
||||
echfs-utils -m -p0 test.img quick-format 512 > part_guid
|
||||
sed "s/@GUID@/`cat part_guid`/g" < test/limine.cfg > limine.cfg.tmp
|
||||
echfs-utils -m -p0 test.img import limine.cfg.tmp limine.cfg
|
||||
rm -f limine.cfg.tmp part_guid
|
||||
echfs-utils -m -p0 test.img import test/test.elf boot/test.elf
|
||||
echfs-utils -m -p0 test.img import test/limine.cfg limine.cfg
|
||||
echfs-utils -m -p0 test.img import test/bg.bmp bg.bmp
|
||||
./limine-install limine.bin test.img
|
||||
qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.img -debugcon stdio
|
||||
|
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
@ -13,6 +13,8 @@ struct echfs_identity_table {
|
||||
uint64_t block_count;
|
||||
uint64_t dir_length;
|
||||
uint64_t block_size;
|
||||
uint32_t reserved;
|
||||
struct guid guid;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ROOT_DIR_ID (~((uint64_t)0))
|
||||
@ -40,14 +42,9 @@ int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
int echfs_check_signature(int disk, int partition) {
|
||||
struct part part;
|
||||
if (get_part(&part, disk, partition)) {
|
||||
panic("Invalid partition");
|
||||
}
|
||||
|
||||
int echfs_check_signature(struct part *part) {
|
||||
struct echfs_identity_table id_table;
|
||||
read_partition(disk, &part, &id_table, 0, sizeof(struct echfs_identity_table));
|
||||
read_partition(part->drive, part, &id_table, 0, sizeof(struct echfs_identity_table));
|
||||
|
||||
if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
|
||||
return 0;
|
||||
@ -56,6 +53,19 @@ int echfs_check_signature(int disk, int partition) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool echfs_get_guid(struct guid *guid, struct part *part) {
|
||||
struct echfs_identity_table id_table;
|
||||
read_partition(part->drive, part, &id_table, 0, sizeof(struct echfs_identity_table));
|
||||
|
||||
if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*guid = id_table.guid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *path) {
|
||||
const char *fullpath = path;
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
#define __FS__ECHFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <lib/part.h>
|
||||
#include <lib/blib.h>
|
||||
|
||||
struct echfs_dir_entry {
|
||||
uint64_t parent_id;
|
||||
@ -31,7 +33,8 @@ struct echfs_file_handle {
|
||||
struct echfs_dir_entry dir_entry;
|
||||
};
|
||||
|
||||
int echfs_check_signature(int disk, int partition);
|
||||
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, int disk, int partition, const char *filename);
|
||||
int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
|
||||
|
@ -411,13 +411,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(int drive, int partition) {
|
||||
struct part part;
|
||||
if (get_part(&part, drive, partition))
|
||||
panic("Invalid partition");
|
||||
|
||||
int ext2_check_signature(struct part *part) {
|
||||
struct ext2_superblock sb;
|
||||
read_partition(drive, &part, &sb, 1024, sizeof(struct ext2_superblock));
|
||||
read_partition(part->drive, part, &sb, 1024, sizeof(struct ext2_superblock));
|
||||
|
||||
if (sb.s_magic != EXT2_S_MAGIC)
|
||||
return 0;
|
||||
@ -434,3 +430,16 @@ int ext2_check_signature(int drive, int partition) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ext2_get_guid(struct guid *guid, struct part *part) {
|
||||
struct ext2_superblock sb;
|
||||
read_partition(part->drive, part, &sb, 1024, sizeof(struct ext2_superblock));
|
||||
|
||||
if (sb.s_magic != EXT2_S_MAGIC)
|
||||
return false;
|
||||
|
||||
((uint64_t *)guid)[0] = sb.s_uuid[0];
|
||||
((uint64_t *)guid)[1] = sb.s_uuid[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <lib/part.h>
|
||||
#include <lib/blib.h>
|
||||
|
||||
struct ext2_linux {
|
||||
uint8_t frag_num;
|
||||
@ -54,7 +56,8 @@ struct ext2_file_handle {
|
||||
uint64_t block_size;
|
||||
};
|
||||
|
||||
int ext2_check_signature(int drive, int partition);
|
||||
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, int drive, int partition, const char *path);
|
||||
int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count);
|
||||
|
@ -66,14 +66,12 @@ struct fat32_lfn_entry {
|
||||
char name3[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
static int fat32_init_context(struct fat32_context* context, int disk, int partition) {
|
||||
context->drive = disk;
|
||||
if (get_part(&context->part, disk, partition)) {
|
||||
panic("Invalid partition");
|
||||
}
|
||||
static int fat32_init_context(struct fat32_context* context, struct part *part) {
|
||||
context->part = *part;
|
||||
context->drive = part->drive;
|
||||
|
||||
struct fat32_bpb bpb;
|
||||
read_partition(disk, &context->part, &bpb, 0, sizeof(struct fat32_bpb));
|
||||
read_partition(part->drive, &context->part, &bpb, 0, sizeof(struct fat32_bpb));
|
||||
|
||||
if (bpb.signature != FAT32_VALID_SIGNATURE_1 && bpb.signature != FAT32_VALID_SIGNATURE_2) {
|
||||
return 1;
|
||||
@ -223,14 +221,19 @@ static int fat32_open_in(struct fat32_context* context, struct fat32_directory_e
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fat32_check_signature(int disk, int partition) {
|
||||
int fat32_check_signature(struct part *part) {
|
||||
struct fat32_context context;
|
||||
return fat32_init_context(&context, disk, partition) == 0;
|
||||
return fat32_init_context(&context, part) == 0;
|
||||
}
|
||||
|
||||
int fat32_open(struct fat32_file_handle* ret, int disk, int partition, const char* path) {
|
||||
struct part part;
|
||||
if (get_part(&part, disk, partition)) {
|
||||
panic("Invalid partition");
|
||||
}
|
||||
|
||||
struct fat32_context context;
|
||||
int r = fat32_init_context(&context, disk, partition);
|
||||
int r = fat32_init_context(&context, &part);
|
||||
|
||||
if (r) {
|
||||
print("fat32: context init failure (%d)\n", r);
|
||||
|
@ -24,7 +24,7 @@ struct fat32_file_handle {
|
||||
uint32_t size_clusters;
|
||||
};
|
||||
|
||||
int fat32_check_signature(int disk, int partition);
|
||||
int fat32_check_signature(struct part *part);
|
||||
|
||||
int fat32_open(struct fat32_file_handle *ret, int disk, int partition, const char *path);
|
||||
int fat32_read(struct fat32_file_handle *file, void *buf, uint64_t loc, uint64_t count);
|
||||
|
@ -6,9 +6,26 @@
|
||||
#include <fs/fat32.h>
|
||||
#include <lib/blib.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <lib/part.h>
|
||||
|
||||
bool fs_get_guid(struct guid *guid, struct part *part) {
|
||||
if (echfs_check_signature(part)) {
|
||||
return echfs_get_guid(guid, part);
|
||||
}
|
||||
if (ext2_check_signature(part)) {
|
||||
return ext2_get_guid(guid, part);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int fopen(struct file_handle *ret, int disk, int partition, const char *filename) {
|
||||
if (echfs_check_signature(disk, partition)) {
|
||||
struct part part;
|
||||
if (get_part(&part, disk, partition)) {
|
||||
panic("Invalid partition");
|
||||
}
|
||||
|
||||
if (echfs_check_signature(&part)) {
|
||||
struct echfs_file_handle *fd = conv_mem_alloc(sizeof(struct echfs_file_handle));
|
||||
|
||||
int r = echfs_open(fd, disk, partition, filename);
|
||||
@ -24,7 +41,7 @@ int fopen(struct file_handle *ret, int disk, int partition, const char *filename
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ext2_check_signature(disk, partition)) {
|
||||
if (ext2_check_signature(&part)) {
|
||||
struct ext2_file_handle *fd = conv_mem_alloc(sizeof(struct ext2_file_handle));
|
||||
|
||||
int r = ext2_open(fd, disk, partition, filename);
|
||||
@ -40,7 +57,7 @@ int fopen(struct file_handle *ret, int disk, int partition, const char *filename
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fat32_check_signature(disk, partition)) {
|
||||
if (fat32_check_signature(&part)) {
|
||||
struct fat32_file_handle *fd = conv_mem_alloc(sizeof(struct fat32_file_handle));
|
||||
|
||||
int r = fat32_open(fd, disk, partition, filename);
|
||||
|
@ -2,6 +2,12 @@
|
||||
#define __FS__FILE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct part;
|
||||
struct guid;
|
||||
|
||||
bool fs_get_guid(struct guid *guid, struct part *part);
|
||||
|
||||
struct file_handle {
|
||||
int disk;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <sys/e820.h>
|
||||
#include <lib/print.h>
|
||||
#include <lib/config.h>
|
||||
#include <lib/part.h>
|
||||
#include <mm/pmm.h>
|
||||
|
||||
uint8_t boot_drive;
|
||||
@ -59,14 +60,32 @@ static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) {
|
||||
struct guid guid;
|
||||
|
||||
if (!string_to_guid(&guid, guid_str))
|
||||
panic("Invalid GUID format");
|
||||
|
||||
int drive, partition;
|
||||
if (!part_get_by_guid(&drive, &partition, &guid))
|
||||
panic("No partition found for GUID: %s", guid_str);
|
||||
|
||||
if (fopen(fd, drive, partition, path))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uri_open(struct file_handle *fd, char *uri) {
|
||||
char *resource, *root, *path;
|
||||
config_resolve_uri(uri, &resource, &root, &path);
|
||||
|
||||
if (!strcmp(resource, "bios")) {
|
||||
return uri_bios_dispatch(fd, root, path);
|
||||
} else if (!strcmp(resource, "guid")) {
|
||||
return uri_guid_dispatch(fd, root, path);
|
||||
} else {
|
||||
panic("Resource `%s` not valid.");
|
||||
panic("Resource `%s` not valid.", resource);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +167,7 @@ static bool is_valid_guid(const char *s) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) {
|
||||
size_t p = 0;
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
@ -157,7 +176,7 @@ static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) {
|
||||
i % 2 ? (dest[p] = val) : (dest[p++] |= val << 4);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
static void guid_convert_be_cluster(uint8_t *dest, const char *s, int len) {
|
||||
size_t p = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
@ -171,9 +190,9 @@ bool string_to_guid(struct guid *guid, const char *s) {
|
||||
if (!is_valid_guid(s))
|
||||
return false;
|
||||
|
||||
guid_convert_le_cluster((uint8_t *)guid + 0, s + 0, 8);
|
||||
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 + 0, s + 0, 8);
|
||||
guid_convert_be_cluster((uint8_t *)guid + 4, s + 9, 4);
|
||||
guid_convert_be_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, 12);
|
||||
|
||||
|
@ -140,6 +140,7 @@ bool config_resolve_uri(char *uri, char **resource, char **root, char **path) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get root
|
||||
for (size_t i = 0; ; i++) {
|
||||
if (uri[i] == 0)
|
||||
return false;
|
||||
@ -152,9 +153,9 @@ bool config_resolve_uri(char *uri, char **resource, char **root, char **path) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get path
|
||||
if (*uri == 0)
|
||||
return false;
|
||||
|
||||
*path = uri;
|
||||
|
||||
return true;
|
||||
|
@ -75,9 +75,18 @@ static int gpt_get_part(struct part *ret, int drive, int partition) {
|
||||
if (!memcmp(&entry.unique_partition_guid, &empty_guid, sizeof(struct guid)))
|
||||
return NO_PARTITION;
|
||||
|
||||
ret->drive = drive;
|
||||
ret->partition = partition;
|
||||
ret->first_sect = entry.starting_lba;
|
||||
ret->sect_count = (entry.ending_lba - entry.starting_lba) + 1;
|
||||
ret->guid = entry.unique_partition_guid;
|
||||
|
||||
struct guid guid;
|
||||
if (!fs_get_guid(&guid, ret)) {
|
||||
ret->guid_valid = false;
|
||||
} else {
|
||||
ret->guid_valid = true;
|
||||
ret->guid = guid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -114,14 +123,18 @@ static int mbr_get_part(struct part *ret, int drive, int partition) {
|
||||
if (entry.type == 0)
|
||||
return NO_PARTITION;
|
||||
|
||||
ret->drive = drive;
|
||||
ret->partition = 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;
|
||||
struct guid guid;
|
||||
if (!fs_get_guid(&guid, ret)) {
|
||||
ret->guid_valid = false;
|
||||
} else {
|
||||
ret->guid_valid = true;
|
||||
ret->guid = guid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -189,3 +202,22 @@ load_up:
|
||||
goto load_up;
|
||||
}
|
||||
}
|
||||
|
||||
bool part_get_by_guid(int *drive, int *part, struct guid *guid) {
|
||||
for (size_t i = 0; i < part_index_i; i++) {
|
||||
if (!part_index[i].guid_valid)
|
||||
continue;
|
||||
print("%X %X\n",
|
||||
((uint64_t*)&part_index[i].guid)[0],
|
||||
((uint64_t*)&part_index[i].guid)[1]);
|
||||
print("%X %X\n",
|
||||
((uint64_t*)guid)[0],
|
||||
((uint64_t*)guid)[1]);
|
||||
if (!memcmp(&part_index[i].guid, guid, 16)) {
|
||||
*drive = part_index[i].drive;
|
||||
*part = part_index[i].partition;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -6,12 +6,16 @@
|
||||
#include <lib/blib.h>
|
||||
|
||||
struct part {
|
||||
int drive;
|
||||
int partition;
|
||||
uint64_t first_sect;
|
||||
uint64_t sect_count;
|
||||
bool guid_valid;
|
||||
struct guid guid;
|
||||
};
|
||||
|
||||
int get_part(struct part *part, int drive, int partition);
|
||||
bool part_get_by_guid(int *drive, int *part, struct guid *guid);
|
||||
|
||||
void part_create_index(void);
|
||||
|
||||
|
@ -20,7 +20,7 @@ BACKGROUND_PATH=bg.bmp
|
||||
:Stivale Test
|
||||
|
||||
PROTOCOL=stivale
|
||||
KERNEL_PATH=bios://:1/boot/test.elf
|
||||
KERNEL_PATH=guid://@GUID@/boot/test.elf
|
||||
KERNEL_CMDLINE=Hi! This is an example!
|
||||
|
||||
:Stivale2 Test
|
||||
|
Loading…
Reference in New Issue
Block a user