diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile --- a/stand/efi/loader/Makefile +++ b/stand/efi/loader/Makefile @@ -43,6 +43,8 @@ CFLAGS.bootinfo.c += -I${SRCTOP}/contrib/pnglite CFLAGS.framebuffer.c += -I$(SRCTOP)/sys/teken CFLAGS.framebuffer.c += -I${SRCTOP}/contrib/pnglite +CFLAGS.efi_main.c += -I$(SRCTOP)/sys/teken +CFLAGS.efi_main.c += -I${SRCTOP}/contrib/pnglite CFLAGS.main.c += -I$(SRCTOP)/sys/teken CFLAGS.main.c += -I${SRCTOP}/contrib/pnglite CFLAGS.gfx_fb.c += -I$(SRCTOP)/sys/teken diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c --- a/stand/efi/loader/copy.c +++ b/stand/efi/loader/copy.c @@ -192,7 +192,7 @@ bool stage_offset_set = false; ssize_t stage_offset; -static void +void efi_copy_free(void) { BS->FreePages(staging_base, (staging_end - staging_base) / diff --git a/stand/efi/loader/efi_main.c b/stand/efi/loader/efi_main.c --- a/stand/efi/loader/efi_main.c +++ b/stand/efi/loader/efi_main.c @@ -28,18 +28,34 @@ #include #include #include +#include +#include #include static EFI_PHYSICAL_ADDRESS heap; static UINTN heapsize; +extern char panicbuf[PANIC_BUFFER_SIZE]; +CHAR16 *exit_msg; +UINTN exit_msg_size = (PANIC_BUFFER_SIZE + 1) * 2; + void efi_exit(EFI_STATUS exit_code) { - if (boot_services_active) { + if (exit_msg != NULL) { + cpy8to16(panicbuf, exit_msg, exit_msg_size); + } + + /* + * Free what we can. Note, efi_exit() may + * be called as result of panic(), not everything may + * work as expected. + */ + efi_copy_free(); + efi_framebuffer_cleanup(); BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize)); - BS->Exit(IH, exit_code, 0, NULL); + BS->Exit(IH, exit_code, exit_msg_size, exit_msg); } else { RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); } @@ -100,9 +116,17 @@ ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"Failed to allocate memory for heap.\r\n"); BS->Exit(IH, status, 0, NULL); } - setheap((void *)(uintptr_t)heap, (void *)(uintptr_t)(heap + heapsize)); + /* + * Allocate memory for panic message. + */ + status = BS->AllocatePool(EfiLoaderData, exit_msg_size, (void **)&exit_msg); + if (status != EFI_SUCCESS) { + exit_msg = NULL; + exit_msg_size = 0; + } + /* Start tslog now that we have a heap.*/ tslog_init(); @@ -191,5 +215,4 @@ status = main(argc, argv); efi_exit(status); - return (status); } diff --git a/stand/efi/loader/framebuffer.h b/stand/efi/loader/framebuffer.h --- a/stand/efi/loader/framebuffer.h +++ b/stand/efi/loader/framebuffer.h @@ -32,6 +32,7 @@ #define _EFIFB_H_ bool efi_has_gop(void); +void efi_framebuffer_cleanup(void); int efi_find_framebuffer(teken_gfx_t *gfx_state); #endif /* _EFIFB_H_ */ diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c --- a/stand/efi/loader/framebuffer.c +++ b/stand/efi/loader/framebuffer.c @@ -560,7 +560,25 @@ return (status == EFI_BUFFER_TOO_SMALL); } +/* + * Clean up and de-allocate the frame buffer related resources + * allocated with efi_find_framebuffer(). + */ +void +efi_framebuffer_cleanup(void) +{ + if (gfx_state.tg_shadow_fb != NULL) { + BS->FreePages((uintptr_t)gfx_state.tg_shadow_fb, + gfx_state.tg_shadow_sz); + } +} +/* + * Find and fill frame buffer details, and allocate memory + * for shadow frame buffer, so we can keep the knowledge + * about our screen state and do not have to read from + * actual frame buffer. + */ int efi_find_framebuffer(teken_gfx_t *gfx_state) { diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -50,6 +50,7 @@ int efi_autoload(void); int efi_copy_init(void); +void efi_copy_free(void); ssize_t efi_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t efi_copyout(const vm_offset_t src, void *dest, const size_t len); diff --git a/stand/libsa/panic.c b/stand/libsa/panic.c --- a/stand/libsa/panic.c +++ b/stand/libsa/panic.c @@ -36,6 +36,7 @@ #include #include +char panicbuf[PANIC_BUFFER_SIZE]; /* * Boot loaders and other standalone programs that wish to have a * different panic policy can provide their own panic_action rotuine. @@ -43,6 +44,7 @@ __weak_symbol void panic_action(void) { + printf("%s\n", panicbuf); printf("--> Press a key on the console to reboot <--\n"); getchar(); printf("Rebooting...\n"); @@ -56,8 +58,7 @@ printf("panic: "); va_start(ap, fmt); - vprintf(fmt, ap); + vsnprintf(panicbuf, sizeof(panicbuf), fmt, ap); va_end(ap); - printf("\n"); panic_action(); } diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -433,6 +433,8 @@ * Machine dependent functions and data, must be provided or stubbed by * the consumer */ +#define PANIC_BUFFER_SIZE 160 + extern void exit(int) __dead2; extern int getchar(void); extern int ischar(void);