commit 2e9c53fab2e2c0d0a28b608921af7993449d8aeb
parent 710525bc8aa30bc58163f35a7249ab1fa79b1358
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 16 Mar 2024 15:55:10 +0900
implement elementary printf
Diffstat:
M | Makefile | | | 2 | +- |
M | hello.c | | | 41 | ++++++++++++++++++++++++++++++++++++----- |
M | uefi.h | | | 37 | +++++++++++++++++++++++++++++++++---- |
M | utils.c | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | utils.h | | | 7 | +++++++ |
5 files changed, 129 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,5 +1,5 @@
CC = x86_64-w64-mingw32-gcc
-CFLAGS = -shared -nostdinc -nostdlib -mno-red-zone -fno-stack-protector \
+CFLAGS = -shared -nostdlib -mno-red-zone -fno-stack-protector \
-mno-stack-arg-probe -Wall -e EfiMain
OBJCOPY = objcopy
SRC = hello.c utils.c
diff --git a/hello.c b/hello.c
@@ -1,27 +1,57 @@
#include "uefi.h"
#include "utils.h"
+EFI_SYSTEM_TABLE *SystemTable;
+
EFI_STATUS
-EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *systab)
{
+ // init global variable.
+ SystemTable = systab;
+
EFI_STATUS stat;
CHAR16 s[19];
// Output firmware bender.
+ SystemTable->ConOut->ClearScreen(SystemTable->ConOut);
SystemTable->ConOut->OutputString(SystemTable->ConOut, SystemTable->FirmwareVendor);
+ printf("--%s--%d--\n\r", "char *", 1259320);
// Output memory map information.
- UINTN mmsize = sizeof(EFI_MEMORY_DESCRIPTOR) * 1024;
- EFI_MEMORY_DESCRIPTOR mmap[1024];
+ UINTN mmsize = 8196;
+ char mmbuf[8196];
+ EFI_MEMORY_DESCRIPTOR *mmap;
UINTN mkey;
UINTN dsize;
UINT32 dver;
+ mmap = (EFI_MEMORY_DESCRIPTOR *) mmbuf;
stat = SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver);
if (stat != EFI_SUCCESS) {
return stat;
}
- SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap[0].Type, s));
+
+ for (; mmap < (EFI_MEMORY_DESCRIPTOR *)(mmbuf + mmsize);
+ mmap = (EFI_MEMORY_DESCRIPTOR *) (((char *)mmap) + dsize)) {
+ if (mmap->Type != EfiConventionalMemory) {
+ continue;
+ }
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap->Type, s));
+ s[0] = '\t'; s[1] = '\0';
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, s);
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap->VirtualStart, s));
+ s[0] = '\t'; s[1] = '\0';
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, s);
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap->PhysicalStart, s));
+ s[0] = '\t'; s[1] = '\0';
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, s);
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap->NumberOfPages, s));
+ s[0] = '\t'; s[1] = '\0';
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, s);
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, sprinth(mmap->Attribute, s));
+ s[0] = '\n'; s[1] = '\r'; s[2] = '\0';
+ SystemTable->ConOut->OutputString(SystemTable->ConOut, s);
+ }
// Echo back user input.
EFI_INPUT_KEY Key;
@@ -31,5 +61,6 @@ EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
str[0] = Key.UnicodeChar;
SystemTable->ConOut->OutputString(SystemTable->ConOut, str);
}
- return 0;
+
+ return EFI_SUCCESS;
}
diff --git a/uefi.h b/uefi.h
@@ -36,17 +36,46 @@ typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
EFI_INPUT_READ_KEY ReadKeyStroke;
} EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_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
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+typedef
+EFI_STATUS (EFIAPI *EFI_TEXT_CLEAR_SCREEN)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
);
-typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
+struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
void *dummy;
EFI_TEXT_STRING OutputString;
-} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+ void *dummy1[4];
+ EFI_TEXT_CLEAR_SCREEN ClearScreen;
+};
+
+typedef enum {
+ EfiReservedMemoryType,
+ EfiLoaderCode,
+ EfiLoaderData,
+ EfiBootServicesCode,
+ EfiBootServicesData,
+ EfiRuntimeServicesCode,
+ EfiRuntimeServicesData,
+ EfiConventionalMemory,
+ EfiUnusableMemory,
+ EfiACPIReclaimMemory,
+ EfiACPIMemoryNVS,
+ EfiMemoryMappedIO,
+ EfiMemoryMappedIOPortSpace,
+ EfiPalCode,
+ EfiPersistentMemory,
+ EfiUnacceptedMemoryType,
+ EfiMaxMemoryType,
+} EFI_MEMORY_TYPE;
typedef struct {
UINT32 Type;
diff --git a/utils.c b/utils.c
@@ -1,3 +1,5 @@
+#include <stdarg.h>
+
#include "uefi.h"
#include "utils.h"
@@ -18,3 +20,53 @@ sprinth(UINT64 n, CHAR16 s[19])
s[19] = L'\0';
return s;
}
+
+int
+printf(char *fmt, ...)
+{
+ va_list ap;
+ CHAR16 _buf[1024], *buf = _buf;
+ EFI_STATUS stat;
+
+ char *s;
+ int d, e;
+
+ va_start(ap, fmt);
+ for (;*fmt;) {
+ if (*fmt != '%') {
+ *buf++ = (CHAR16) *fmt++;
+ continue;
+ }
+ fmt++;
+ switch (*fmt++) {
+ case '%':
+ *buf++ = L'%';
+ break;
+ case 's':
+ s = va_arg(ap, char *);
+ for (;*s;) {
+ *buf++ = (CHAR16) *s++;
+ }
+ break;
+ case 'd':
+ d = va_arg(ap, int);
+ if (d < 0) {
+ *buf++ = '-';
+ d = -d;
+ }
+ for (e = 1; e <= d; e *= 10) {
+ }
+ for (e /= 10; e >= 1; e /= 10) {
+ *buf++ = (CHAR16) ('0' + ((d / e) % 10));
+ }
+ break;
+ }
+ }
+ va_end(ap);
+ *buf = L'\0';
+ stat = SystemTable->ConOut->OutputString(SystemTable->ConOut, _buf);
+ if (stat != EFI_SUCCESS) {
+ return -1;
+ }
+ return (int) (buf - _buf);
+}
diff --git a/utils.h b/utils.h
@@ -1,6 +1,13 @@
// #include "uefi.h"
+extern EFI_SYSTEM_TABLE *SystemTable;
+
// 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]);
+
+// Printf prints formatted string to ConOut.
+// Can't format a string longer than 1024 CHAR16s.
+// It returns number of CHAR16s written excluding the final NULL.
+int printf(char *fmt, ...);