From 4ec95a6a52b057f5965340c2412ca78937c1a697 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 29 Jan 2025 20:05:50 +0100 Subject: [PATCH] Added SimpleFS read support --- boot/common/fs/uefi_sfs.c | 126 +++++++++++++++++- boot/common/init.c | 15 ++- boot/common/lib/string.c | 3 +- boot/common/vfs/vfs.c | 75 +++-------- boot/include/fs/uefi_sfs.h | 7 +- boot/include/menu/bootmenu.h | 25 ---- boot/include/vfs/vfs.h | 19 +-- .../main_menu.c => platform/uefi/mount.c} | 11 +- 8 files changed, 174 insertions(+), 107 deletions(-) delete mode 100644 boot/include/menu/bootmenu.h rename boot/{common/menu/main_menu.c => platform/uefi/mount.c} (86%) diff --git a/boot/common/fs/uefi_sfs.c b/boot/common/fs/uefi_sfs.c index 1b17978..589d783 100644 --- a/boot/common/fs/uefi_sfs.c +++ b/boot/common/fs/uefi_sfs.c @@ -17,20 +17,138 @@ /* SOFTWARE. */ /*********************************************************************************/ -#ifndef AXBOOT_UEFI +#ifdef AXBOOT_UEFI #include #include +#include +#include +#include +#include #include #include struct sfs_fsdata { + EFI_FILE_PROTOCOL *volume; }; -uint8_t sfs_read(char *filename, char *buffer, struct device *dev, void *fsdata) +struct vfs_drive *sfs_init(char *mountpoint) { - (void)dev; - (void)fsdata; + EFI_LOADED_IMAGE_PROTOCOL *loaded_image = NULL; + EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *iovolume; + EFI_GUID sfs_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + EFI_FILE_PROTOCOL *volume; + EFI_STATUS status = EFI_SUCCESS; + + status = gBootServices->HandleProtocol(gImageHandle, &lip_guid, (void **) &loaded_image); + if (EFI_ERROR(status)) { + debug("sfs_init(): Failed to open volume: %s (%lx)\n", efi_status_to_str(status), status); + return NULL; + } + + status = gBootServices->HandleProtocol(loaded_image->DeviceHandle, &sfs_guid, (void *)&iovolume); + if (EFI_ERROR(status)) { + debug("sfs_init(): Failed to open volume: %s (%lx)\n", efi_status_to_str(status), status); + return NULL; + } + + status = iovolume->OpenVolume(iovolume, &volume); + if (EFI_ERROR(status)) { + debug("sfs_init(): Failed to open volume: %s (%lx)\n", efi_status_to_str(status), status); + return NULL; + } + + debug("sfs_init(): Opened boot volume\n"); + + struct vfs_filesystem *fs = (struct vfs_filesystem *)mem_alloc(sizeof(struct vfs_filesystem)); + if (fs == NULL) { + debug("sfs_init(): Failed to allocate memory for filesystem structure!\n"); + return NULL; + } + + struct sfs_fsdata *fsdata = (struct sfs_fsdata *)mem_alloc(sizeof(struct sfs_fsdata)); + if (fsdata == NULL) { + debug("sfs_init(): Failed to allocate memory for private data!\n"); + mem_free(fs); + return NULL; + } + + fsdata->volume = volume; + + fs->fsdata = fsdata; + fs->read = sfs_read; + fs->write = NULL; // sfs_write() + + struct vfs_drive *drive = (struct vfs_drive *)mem_alloc(sizeof(struct vfs_drive)); + if (drive == NULL) { + debug("sfs_init(): Failed to allocate memory for drive structure!\n"); + mem_free(fsdata); + mem_free(fs); + return NULL; + } + + drive->fs = fs; + drive->read = NULL; + drive->write = NULL; + + return drive; +} + +size_t sfs_read(char *filename, char *buffer, struct vfs_drive *dev, void *fsdata) +{ + struct sfs_fsdata *data = (struct sfs_fsdata *)fsdata; + EFI_FILE_PROTOCOL *volume = data->volume; + EFI_FILE_PROTOCOL *file; + EFI_FILE_INFO *fileinfo; + EFI_GUID fi_guid = EFI_FILE_INFO_GUID; + EFI_UINTN fileinfo_size = sizeof(EFI_FILE_INFO) + 32; + CHAR16 *wfilename; + EFI_STATUS status = EFI_SUCCESS; + size_t len = 0; + + wfilename = (CHAR16 *)mem_alloc(strlen(filename) * sizeof(CHAR16)); + if (!wfilename) { + debug("sfs_read(): Failed to allocate memory for wide strings!\n"); + return 0; + } + + mbstowcs(wfilename, (const char **)&filename, strlen(filename)); + + /* open the file */ + status = volume->Open(volume, &file, wfilename, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); + if (EFI_ERROR(status)) { + debug("sfs_read(): Failed to open file '%s': %s (%lx)\n", filename, efi_status_to_str(status), status); + mem_free(wfilename); + return 0; + } + + mem_free(wfilename); + + /* get file size */ + fileinfo = (EFI_FILE_INFO *)mem_alloc(fileinfo_size); + if (!fileinfo) { + debug("sfs_read(): Failed to allocate memory for file info!"); + while (1); + } + + file->GetInfo(file, &fi_guid, &fileinfo_size, fileinfo); + len = fileinfo->FileSize; + + debug("sfs_read: %u\n", len); + + buffer = (char *)mem_alloc(len * sizeof(char)); + if (!buffer) { + debug("sfs_read(): Failed to allocate memory for output buffer!\n"); + return 0; + } + + file->Read(file, &len, buffer); + + /* close the file */ + file->Close(file); + + return len; } #endif \ No newline at end of file diff --git a/boot/common/init.c b/boot/common/init.c index 72280f5..076a603 100644 --- a/boot/common/init.c +++ b/boot/common/init.c @@ -18,9 +18,22 @@ /*********************************************************************************/ #include +#include +#include void axboot_init() { - vfs_init(); + if (!vfs_init("/")) { + debug("axboot_init(): Failed to mount boot drive! Halting..."); + // TODO: Halt + while (1); + } + + // read kernel -> test read + char *buffer = NULL; + vfs_read("/System/axkrnl", buffer); + + mem_free(buffer); + while (1); } \ No newline at end of file diff --git a/boot/common/lib/string.c b/boot/common/lib/string.c index 533806f..de3ef8b 100644 --- a/boot/common/lib/string.c +++ b/boot/common/lib/string.c @@ -32,7 +32,7 @@ size_t mbstowcs(wchar_t *dest, const char **src, size_t len) return 0; } - while (count) { + while (count--) { if ((*dest = *lsrc) == 0) { lsrc = NULL; break; @@ -44,7 +44,6 @@ size_t mbstowcs(wchar_t *dest, const char **src, size_t len) lsrc++; dest++; - count--; } return len - count; diff --git a/boot/common/vfs/vfs.c b/boot/common/vfs/vfs.c index 38cc383..eabdd23 100644 --- a/boot/common/vfs/vfs.c +++ b/boot/common/vfs/vfs.c @@ -30,74 +30,29 @@ #define MAX_MOUNTS 32 -struct vfs_mount **mountpoints = NULL; -uint8_t last_mount = 0; +struct vfs_drive *boot_drive = NULL; -size_t str_backspace(char *str, char c) +int vfs_init(char *root_mountpoint) { - size_t i = strlen(str) - 1; - - while (--i) { - if (str[i] == c) { - str[i+1] = 0; - return 1; - } - } - return 0; -} - -/* Returns UINT8_MAX incase an error happens */ -uint8_t find_mntpoint_from_filename(char *filename, uint32_t *s_off) -{ - char *orig = (char *)mem_alloc(strlen(filename) + 1); - if (!orig) { - debug("find_mntpoint_from_filename(): Failed to allocate memory for filename!\n"); - return UINT8_MAX; - } - - memset(orig, 0, strlen(filename) + 1); - memcpy(orig, filename, strlen(filename) + 1); - - if (orig[strlen(orig)] == '/') - str_backspace(orig, '/'); - - // TODO: Check if there's a way to stay in this loop forever - while (1) { - for (int i = 0; i < MAX_MOUNTS; i++) { - if (!mountpoints[i]) - break; - - if (strcmp(mountpoints[i]->mnt, orig) == 0) { - /* Adjust the orig to make it relative to the partition */ - *s_off = (strlen(orig) - 1); - mem_free(orig); - return i; - } - } - - if (strcmp(orig, "/") == 0) - break; - str_backspace(orig, '/'); - } - return 0; -} - -void vfs_init(void) -{ - mountpoints = (struct vfs_mount **)mem_alloc(sizeof(struct vfs_mount) * MAX_MOUNTS); - if (!mountpoints) { + boot_drive = mount_boot_volume(root_mountpoint); + if (boot_drive == NULL) { debug("vfs_init(): Failed to allocate memory for VFS!\n"); - // TODO: Panic and halt + // fuck off and boot out early. + return 0; } + + debug("vfs_init(): Mounted boot drive to \"/\"\n"); + return 1; } -int vfs_read(char *filename, char *buf, size_t len) +size_t vfs_read(char *filename, char *buf) { - uint32_t s_off = 0; - int i = find_mntpoint_from_filename(filename, &s_off); - filename += s_off; + if (boot_drive->fs->read == NULL) { + debug("vfs_read(): Filesystem didn't set up a read function!"); + return 0; + } - return mountpoints[i]->drive->fs->read(filename, buf, mountpoints[i]->drive, mountpoints[i]->drive->fs->fs_data); + return boot_drive->fs->read(filename, buf, boot_drive, boot_drive->fs->fsdata); } int vfs_write(char *filename, char *buf, size_t len) diff --git a/boot/include/fs/uefi_sfs.h b/boot/include/fs/uefi_sfs.h index 8d22f7b..791963a 100644 --- a/boot/include/fs/uefi_sfs.h +++ b/boot/include/fs/uefi_sfs.h @@ -20,8 +20,11 @@ #ifndef _FS_UEFI_SFS_H #define _FS_UEFI_SFS_H -#ifndef AXBOOT_UEFI +#include +#include -#endif +struct vfs_drive *sfs_init(char *mountpoint); + +size_t sfs_read(char *filename, char *buffer, struct vfs_drive *dev, void *fsdata); #endif /* _FS_UEFI_SFS_H */ diff --git a/boot/include/menu/bootmenu.h b/boot/include/menu/bootmenu.h deleted file mode 100644 index 6870fdf..0000000 --- a/boot/include/menu/bootmenu.h +++ /dev/null @@ -1,25 +0,0 @@ -/*********************************************************************************/ -/* Module Name: bootmenu.h */ -/* Project: AurixOS */ -/* */ -/* Copyright (c) 2024-2025 Jozef Nagy */ -/* */ -/* This source is subject to the MIT License. */ -/* See License.txt in the root of this repository. */ -/* All other rights reserved. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/*********************************************************************************/ - -#ifndef _MENU_BOOTMENU_H -#define _MENU_BOOTMENU_H - -void main_menu(void); - -#endif /* _MENU_BOOTMENU_H */ diff --git a/boot/include/vfs/vfs.h b/boot/include/vfs/vfs.h index dc6f8c9..4002c89 100644 --- a/boot/include/vfs/vfs.h +++ b/boot/include/vfs/vfs.h @@ -20,19 +20,15 @@ #ifndef _VFS_VFS_H #define _VFS_VFS_H +#include #include #include -struct vfs_drive; - struct vfs_filesystem { - char *fsname; - - uint8_t (*read)(char *, char *, struct vfs_drive *, void *); + size_t (*read)(char *, char *, struct vfs_drive *, void *); uint8_t (*write)(char *, char *, size_t, struct vfs_drive *, void *); - uint8_t (*mount)(struct vfs_drive *, void *); - uint8_t *fs_data; + void *fsdata; }; struct vfs_mount { @@ -40,9 +36,14 @@ struct vfs_mount { struct vfs_drive *drive; }; -void vfs_init(void); +int vfs_init(char *root_mountpoint); -int vfs_read(char *filename, char *buf, size_t len); +/* This function allocates `buf`. Passing a non-NULL value will result in an error. */ +/* NOTE: Remember to free the allocated memory afterwards! */ +size_t vfs_read(char *filename, char *buf); int vfs_write(char *filename, char *buf, size_t len); +/* Every platform will define this on its own */ +struct vfs_drive *mount_boot_volume(char *mountpoint); + #endif /* _VFS_VFS_H */ diff --git a/boot/common/menu/main_menu.c b/boot/platform/uefi/mount.c similarity index 86% rename from boot/common/menu/main_menu.c rename to boot/platform/uefi/mount.c index a91a5ad..4fff527 100644 --- a/boot/common/menu/main_menu.c +++ b/boot/platform/uefi/mount.c @@ -1,5 +1,5 @@ /*********************************************************************************/ -/* Module Name: main_menu.c */ +/* Module Name: mount.c */ /* Project: AurixOS */ /* */ /* Copyright (c) 2024-2025 Jozef Nagy */ @@ -17,9 +17,12 @@ /* SOFTWARE. */ /*********************************************************************************/ -#include +#include +#include +#include +#include -void main_menu(void) +struct vfs_drive *mount_boot_volume(char *mountpoint) { - while (1); + return sfs_init(mountpoint); } \ No newline at end of file