setos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit c41010422015c90adb51f7a39e4e33a152c89a4f
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu, 14 Mar 2024 14:27:44 +0900

first commit

Diffstat:
A.gitignore | 3+++
AMakefile | 29+++++++++++++++++++++++++++++
AQEMU_EFI.fd | 0
Ahello.c | 30++++++++++++++++++++++++++++++
Atest/Makefile | 12++++++++++++
Atest/utils_test.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Auefi.h | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autils.c | 23+++++++++++++++++++++++
Autils.h | 7+++++++
9 files changed, 309 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +image +disk.img +include diff --git a/Makefile b/Makefile @@ -0,0 +1,28 @@ +CC = x86_64-w64-mingw32-gcc +CFLAGS = -shared -nostdlib -mno-red-zone -fno-stack-protector -O0 -Wall -e EfiMain +OBJCOPY = objcopy +SRC = hello.c utils.c +HDR = uefi.h + +all: hello.efi + +hello.dll: $(SRC) $(HDR) + $(CC) $(CFLAGS) -o $@ $(SRC) + +hello.efi: hello.dll + $(OBJCOPY) --target=efi-app-x86_64 $< $@ + +run: hello.efi + mkdir -p image + doas mount disk.img image + doas mkdir -p image/EFI/BOOT + doas cp hello.efi image/EFI/BOOT/BOOTX64.EFI + doas umount image + qemu-system-x86_64 -bios /usr/share/edk2/x64/OVMF.fd -drive format=raw,file=disk.img + +test: test/* + (cd test && make) + +clean: + rm -f *.o *.efi *.dll + (cd test && make clean) +\ No newline at end of file diff --git a/QEMU_EFI.fd b/QEMU_EFI.fd Binary files differ. diff --git a/hello.c b/hello.c @@ -0,0 +1,30 @@ +#include "uefi.h" +#include "utils.h" + +#include <stddef.h> + +EFI_STATUS +EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + // Output firmware bender. + SystemTable->ConOut->OutputString(SystemTable->ConOut, SystemTable->FirmwareVendor); + + // Output memory map information. + UINTN mmsize = sizeof(EFI_MEMORY_DESCRIPTOR) * 32; // ? + EFI_MEMORY_DESCRIPTOR mmap[32]; + UINTN mkey; + UINTN dsize; + UINT32 dver; + + SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver); + + // Echo back user input. + EFI_INPUT_KEY Key; + CHAR16 str[2] = {' ', '\0'}; + while(1) { + SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn, &Key); + str[0] = Key.UnicodeChar; + SystemTable->ConOut->OutputString(SystemTable->ConOut, str); + } + return 0; +} diff --git a/test/Makefile b/test/Makefile @@ -0,0 +1,11 @@ +CC = tcc +SRC = utils_test.c ../utils.c + +all: test + ./test + +test: $(SRC) + $(CC) -O0 -g -o test $(SRC) + +clean: + rm -f test +\ No newline at end of file diff --git a/test/utils_test.c b/test/utils_test.c @@ -0,0 +1,95 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../uefi.h" +#include "../utils.h" + +int +str16cmp(CHAR16 *s, CHAR16 *t) +{ + for (; *s != 0 && *t != 0; s++, t++) { + if (*s == *t) { + continue; + } else if (*s < *t) { + return -1; + } else { + return 1; + } + } + if (*s != 0) { + return 1; + } else if (*t != 0) { + return -1; + } else { + return 0; + } +} + +// Strtostr16 converts string s to UTF16 string. +// Caller should free the returned pointer. +CHAR16 * +strtostr16(char *s) +{ + int n; + CHAR16 *ss, *st; + + n = strlen(s); + ss = st = (CHAR16 *) malloc((n+1) * sizeof(CHAR16)); + if (!ss) + return NULL; + for (; *s; ) { + *ss++ = (CHAR16) *s++; + } + return st; +} + +char * +str16tostr(CHAR16 *s) +{ + int n = 0; + CHAR16 *t; + for (t = s; *t; t++) { + n++; + } + char *ss, *tt; + ss = tt = (char *)malloc((n + 1) * sizeof(char)); + if (!ss) { + return NULL; + } + for (tt = ss, t = s; *t;) { + *tt++ = (char) (*t++ & 0xff); + } + *tt = '\0'; + return ss; +} + +int +testSprinth() +{ + int nerr = 0; + struct test { + UINT64 input; + CHAR16 *want; + } tests[] = { + {0xdeadbeef, strtostr16("0x00000000deadbeef")}, + {0xcafecafe, strtostr16("0x00000000cafecafe")}, + {0, NULL}, + }; + struct test *t; + CHAR16 got[19]; + for (t = tests; t->want; t++) { + if (str16cmp(t->want, sprinth(t->input, got)) != 0) { + fprintf(stderr, "sprinth(0x%x, got) = %s, want: %s\n", + t->input, str16tostr(got), str16tostr(t->want)); + nerr++; + } + } + return nerr; +} + +int +main(void) +{ + testSprinth(); +} +\ No newline at end of file diff --git a/uefi.h b/uefi.h @@ -0,0 +1,109 @@ +#define IN +#define OUT +#define OPTIONAL +#define CONST +#define EFIAPI + +typedef unsigned short CHAR16; +typedef unsigned long long UINTN; +typedef unsigned short UINT16; +typedef unsigned UINT32; +typedef unsigned long long UINT64; +typedef unsigned long long EFI_STATUS; +typedef void *EFI_HANDLE; +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL; +typedef +EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY)( + IN struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { + void *dummy; + EFI_INPUT_READ_KEY ReadKeyStroke; +} EFI_SIMPLE_TEXT_INPUT_PROTOCOL; + +struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; +typedef +EFI_STATUS (EFIAPI *EFI_TEXT_STRING)( + IN struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { + void *dummy; + EFI_TEXT_STRING OutputString; +} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; + +typedef struct { // TODO implement. + UINT32 Type; + EFI_PHYSICAL_ADDRESS PhysicalStart; + EFI_VIRTUAL_ADDRESS VirtualStart; + UINT64 NumberOfPages; + UINT64 Attribute; +} EFI_MEMORY_DESCRIPTOR; + +typedef +EFI_STATUS (EFIAPI *EFI_GET_MEMORY_MAP)( + IN OUT UINTN *MemoryMapSize, + OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +typedef +EFI_STATUS (EFIAPI *EFI_EXIT_BOOT_SERVICES)( + ); + +typedef struct { +} EFI_RUNTIME_SERVICES; + +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + +typedef struct { + EFI_TABLE_HEADER Hdr; + // task priority services + void *task_priority_services[2]; + // memory services + void *memory_services0[2]; + EFI_GET_MEMORY_MAP GetMemoryMap; + void *memory_services1[2]; + // event timer services + void *event_timer_services[6]; + // protocol handler services + void *protocol_handler_services[9]; + // image services + void *image_services0[4]; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + void *dummy[17]; +} EFI_BOOT_SERVICES; + +typedef struct { + EFI_TABLE_HEADER Hdr; + CHAR16 *FirmwareVendor; + char dummy1[4]; + EFI_HANDLE ConsoleInHandle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + EFI_HANDLE StandardErrorHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + char dummy2[16]; +} EFI_SYSTEM_TABLE; diff --git a/utils.c b/utils.c @@ -0,0 +1,22 @@ +#include "uefi.h" +#include "utils.h" + +#include <stdio.h> + +CHAR16 * +sprinth(UINT64 n, CHAR16 s[19]) +{ + int i; + int d; + s[0] = L'0'; + s[1] = L'x'; + for (i = 0; i < 16; i++) { + d = (n >> (64 - (i + 1) * 4)) & 0xf; + if (d <= 9) + s[i + 2] = L'0' + d; + else + s[i + 2] = L'a' + d - 10; + } + s[19] = L'\0'; + return s; +} +\ No newline at end of file diff --git a/utils.h b/utils.h @@ -0,0 +1,6 @@ +// #include "uefi.h" + +// Printh converts the integer into a string of hex representation. +// It returns the second argument. +// The second argument should have length of 19 ("0x" + "0123456789abcdef" + "\0"). +CHAR16 *sprinth(UINT64, CHAR16[19]); +\ No newline at end of file