[PATCH 1/4] wstr: introduce function conv to convert strings from utf16 to utf8
Export this patch
---
include/wstr.h | 2 ++
src/wstr.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/include/wstr.h b/include/wstr.h
index 13f11c6..aea8dcc 100644
--- a/include/wstr.h
+++ b/include/wstr.h
@@ -1,7 +1,9 @@
#ifndef WSTR_H
#define WSTR_H
+
#include <efi/types.h> // for char16_t
char16_t *wconv(const char *str, char16_t *buf, size_t n);
+ char *conv(const char16_t *str, char *buf, size_t n);
#endif
diff --git a/src/wstr.c b/src/wstr.c
index 6f1227c..3b16205 100644
--- a/src/wstr.c
+++ b/src/wstr.c
@@ -13,3 +13,51 @@ wconv(const char *str, char16_t *buf, size_t n)
buf[i] = 0;
return buf;
}
+
+ /**
+ * Thanks U-boot
+ * https://elixir.bootlin.com/u-boot/v2023.10/source/lib/charset.c#L211
+ */
+ int32_t utf16_get(const char16_t **src)
+ {
+ int32_t code, code2;
+
+ if (!src || !*src)
+ return -1;
+ if (!**src)
+ return 0;
+ code = **src;
+ ++*src;
+ if (code >= 0xDC00 && code <= 0xDFFF)
+ return -1;
+ if (code >= 0xD800 && code <= 0xDBFF) {
+ if (!**src)
+ return -1;
+ code &= 0x3ff;
+ code <<= 10;
+ code += 0x10000;
+ code2 = **src;
+ ++*src;
+ if (code2 <= 0xDC00 || code2 >= 0xDFFF)
+ return -1;
+ code2 &= 0x3ff;
+ code += code2;
+ }
+ return code;
+ }
+
+ char *
+ conv(const char16_t *str, char *buf, size_t n)
+ {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ int32_t c = utf16_get(&str);
+ if (!c) {
+ break;
+ }
+ buf[i] = c;
+ }
+ assert(i + 1 < n);
+ buf[i] = 0;
+ return buf;
+ }
--
2.42.1
[PATCH 2/4] wstr: introduce wstrcmp to compare two char16_t strings
Export this patch
---
include/wstr.h | 1 +
src/wstr.c | 11 +++++++++++
2 files changed, 12 insertions(+)
diff --git a/include/wstr.h b/include/wstr.h
index aea8dcc..229facc 100644
--- a/include/wstr.h
+++ b/include/wstr.h
@@ -5,5 +5,6 @@
char16_t *wconv(const char *str, char16_t *buf, size_t n);
char *conv(const char16_t *str, char *buf, size_t n);
+ int wstrcmp(const char16_t *str1, const char16_t *str2);
#endif
diff --git a/src/wstr.c b/src/wstr.c
index 3b16205..371ea78 100644
--- a/src/wstr.c
+++ b/src/wstr.c
@@ -61,3 +61,14 @@ conv(const char16_t *str, char *buf, size_t n)
buf[i] = 0;
return buf;
}
+
+ int
+ wstrcmp(const char16_t *str1, const char16_t *str2)
+ {
+ while(*str1 && (*str1 == *str2))
+ {
+ str1++;
+ str2++;
+ }
+ return *str1 - *str2;
+ }
--
2.42.1
Thanks!
To git@git.sr.ht:~sircmpwn/hboot
8d4b296..745fe4f master -> master
[PATCH 3/4] fs: introduce readdir function
Export this patch
---
include/fs.h | 1 +
src/fs.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/fs.h b/include/fs.h
index 945ec94..ed8758b 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -10,5 +10,6 @@ efi_file_protocol *open(char16_t *filename, uint64_t mode, uint64_t attrs);
size_t read(efi_file_protocol *f, void *buf, size_t n);
void seek(efi_file_protocol *f, uint64_t pos);
void close(efi_file_protocol *f);
+ const efi_file_info *readdir(efi_file_protocol *file);
#endif
diff --git a/src/fs.c b/src/fs.c
index 34e425a..8201d46 100644
--- a/src/fs.c
+++ b/src/fs.c
@@ -5,6 +5,9 @@
#include <efi/protocol/simple-file-system.h>
#include "fs.h"
+ // Reserve space for file name in wstr
+ #define EFI_FILE_SIZE sizeof(efi_file_info) + 512
+
static efi_file_protocol *root = NULL;
efi_status
@@ -57,3 +60,16 @@ close(efi_file_protocol *f)
efi_status st = f->Close(f);
assert(st == EFI_SUCCESS);
}
+
+ const efi_file_info *
+ readdir(efi_file_protocol *file)
+ {
+ static uint8_t buffer[EFI_FILE_SIZE] = {0};
+
+ size_t n = read(file, buffer, sizeof(buffer));
+ if (n == 0) {
+ return NULL;
+ }
+
+ return (efi_file_info *)buffer;
+ }
--
2.42.1
[PATCH 4/4] modules: introduce load_modules function
Export this patch
---
Makefile | 3 ++ -
include/modules.h | 12 +++++++++
src/main.c | 14 ++++++++++
src/modules.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 97 insertions(+), 1 deletion(-)
create mode 100644 include/modules.h
create mode 100644 src/modules.c
diff --git a/Makefile b/Makefile
index 6c7db18..39a4de2 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ BOOT_OBJ=\
src/guids.o \
src/load.o \
src/main.o \
+ src/modules.o \
src/mmap.o \
src/mmu.o \
src/string.o \
@@ -53,6 +54,6 @@ nographic-gdb: boot.img
-m 1G -no-reboot -no-shutdown \
-drive file=boot.img,format=raw \
-display none \
- -serial stdio -enable-kvm
+ -serial stdio -enable-kvm -d cpu_reset
.PHONY: all clean nographic
diff --git a/include/modules.h b/include/modules.h
new file mode 100644
index 0000000..7d00057
--- /dev/null
+++ b/include/modules.h
@@ -0,0 +1,12 @@
+ #ifndef MODULES_H
+ #define MODULES_H
+
+ #include <efi/types.h>
+ #include <efi/system-table.h>
+ #include <efi/protocol/file.h>
+ #include "bootctx.h"
+
+ efi_status load_modules (efi_boot_services *bsvc, struct bootctx *ctx,
+ efi_file_protocol *modules);
+
+ #endif
diff --git a/src/main.c b/src/main.c
index 3dbfed2..3d22f51 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,6 +8,7 @@
#include "global.h"
#include "hboot.h"
#include "load.h"
+ #include "modules.h"
#include "mmap.h"
#include "mmu.h"
@@ -55,6 +56,19 @@ efi_main(efi_handle image, efi_system_table *systab)
close(kernel);
+ efi_file_protocol *modules = open(L"\\modules", EFI_FILE_MODE_READ, 0);
+ if (modules == NULL) {
+ bprintfln("Error loading boot modules from /modules");
+ return EFI_LOAD_ERROR;
+ }
+
+ st = load_modules(bsvc, ctx, modules);
+ if (st != EFI_SUCCESS) {
+ bprintfln("Error loading boot modules");
+ return st;
+ }
+ close(modules);
+
size_t map_key;
st = collect_mmap(bsvc, ctx, &map_key);
if (st != EFI_SUCCESS) {
diff --git a/src/modules.c b/src/modules.c
new file mode 100644
index 0000000..f3da398
--- /dev/null
+++ b/src/modules.c
@@ -0,0 +1,69 @@
+ #include <assert.h>
+ #include "bprintf.h"
+ #include "fs.h"
+ #include "modules.h"
+ #include "wstr.h"
+
+ #define MAX_MODS 16
+
+ efi_status load_modules(efi_boot_services *bsvc, struct bootctx *ctx,
+ efi_file_protocol *modules)
+ {
+ efi_status st = EFI_SUCCESS;
+
+ struct bootmodule mods[MAX_MODS] = {0};
+
+ size_t nmods;
+ for (nmods = 0; nmods < MAX_MODS; ++nmods) {
+ const efi_file_info *info = readdir(modules);
+ if (info == NULL) {
+ break;
+ }
+
+ if (info->Attribute & EFI_FILE_DIRECTORY ||
+ wstrcmp(info->FileName, L".") == 0 ||
+ wstrcmp(info->FileName, L"..") == 0) {
+ continue;
+ }
+
+ char filename[256] = {0};
+ conv(info->FileName, filename, sizeof(filename));
+ bprintfln("Load boot module /modules/%s", filename);
+
+ struct bootmodule *mod = &mods[nmods++];
+ mod->length = info->FileSize;
+
+ efi_file_protocol *file = NULL;
+ modules->Open(modules, &file, info->FileName,
+ EFI_FILE_MODE_READ, 0);
+ if (file == NULL) {
+ bprintfln("Error loading module");
+ return EFI_LOAD_ERROR;
+ }
+
+ efi_physical_addr *data;
+ st = bsvc->AllocatePool(EfiLoaderData, mod->length,
+ (void **)&data);
+ if (st != EFI_SUCCESS) {
+ bprintfln("Failed to allocate file");
+ return st;
+ }
+ size_t n = read(file, data, mod->length);
+ assert(n == mod->length);
+ mod->base = *data;
+ }
+
+ size_t slicesz = sizeof(struct bootmodule) * nmods;
+ struct slice *slice = &ctx->mods;
+ slice->length = nmods;
+ slice->capacity = nmods;
+ st = bsvc->AllocatePool(EfiLoaderData, slicesz, (void **)&slice->data);
+ if (st != EFI_SUCCESS) {
+ bprintfln("Failed to allocate modules slice");
+ return st;
+ }
+
+ bsvc->CopyMem(slice->data, mods, slicesz);
+
+ return st;
+ }
--
2.42.1