From 735f1daee956b15d1e2e8a80d54463fd2aba4a61 Mon Sep 17 00:00:00 2001 From: Fredrik Holmqvist Date: Sat, 30 Nov 2013 21:35:06 +0100 Subject: [PATCH] EFI: Implement console code. --- src/system/boot/platform/efi/Jamfile | 3 +- src/system/boot/platform/efi/console.cpp | 218 ++++++++++++++++++++ src/system/boot/platform/efi/console.h | 15 ++ src/system/boot/platform/efi/efi_platform.h | 23 +++ src/system/boot/platform/efi/start.c | 58 ------ src/system/boot/platform/efi/start.cpp | 53 +++++ 6 files changed, 311 insertions(+), 59 deletions(-) create mode 100644 src/system/boot/platform/efi/console.cpp create mode 100644 src/system/boot/platform/efi/console.h create mode 100644 src/system/boot/platform/efi/efi_platform.h delete mode 100644 src/system/boot/platform/efi/start.c create mode 100644 src/system/boot/platform/efi/start.cpp diff --git a/src/system/boot/platform/efi/Jamfile b/src/system/boot/platform/efi/Jamfile index cb925349d4..c125fab3a9 100644 --- a/src/system/boot/platform/efi/Jamfile +++ b/src/system/boot/platform/efi/Jamfile @@ -18,7 +18,8 @@ local efi_glue_src = local platform_src = relocation_func.cpp - start.c + start.cpp + console.cpp ; Includes [ FGristFiles $(efi_glue_src) $(platform_src) ] diff --git a/src/system/boot/platform/efi/console.cpp b/src/system/boot/platform/efi/console.cpp new file mode 100644 index 0000000000..47f1cd449d --- /dev/null +++ b/src/system/boot/platform/efi/console.cpp @@ -0,0 +1,218 @@ +/* + * Copyright 2014-2016 Haiku, Inc. All rights reserved. + * Copyright 2013 Fredrik Holmqvist, fredrik.holmqvist@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "console.h" + +#include + +#include + +#include +#include +#include + +#include "efi_platform.h" + + +class Console : public ConsoleNode { + public: + Console(); + + virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize); + virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize); +}; + + +static uint32 sScreenWidth; +static uint32 sScreenHeight; +static uint32 sScreenMode; +static Console sInput, sOutput; +FILE *stdin, *stdout, *stderr; + + +// #pragma mark - + + +Console::Console() + : ConsoleNode() +{ +} + + +ssize_t +Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) +{ + return B_ERROR; +} + + +ssize_t +Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize) +{ + const char *string = (const char *)buffer; + CHAR16 ucsBuffer[bufferSize + 3]; + uint32 j = 0; + + for (uint32 i = 0; i < bufferSize; i++) { + switch (string[i]) { + case '\n': { + ucsBuffer[j++] = '\r'; + ucsBuffer[j++] = '\n'; + } //fallthrough + case 0 : { + //Not sure if we should keep going or abort for 0. + //Keep going was easy anyway. + ucsBuffer[j] = 0; + kSystemTable->ConOut->OutputString(kSystemTable->ConOut, ucsBuffer); + j = 0; + continue; + } + default: + ucsBuffer[j++] = (CHAR16) string[i]; + } + } + + if (j > 0) { + ucsBuffer[j] = 0; + kSystemTable->ConOut->OutputString(kSystemTable->ConOut, ucsBuffer); + } + return bufferSize; +} + + +// #pragma mark - + + +void +console_clear_screen(void) +{ + kSystemTable->ConOut->ClearScreen(kSystemTable->ConOut); +} + + +int32 +console_width(void) +{ + return sScreenWidth; +} + + +int32 +console_height(void) +{ + return sScreenHeight; +} + + +void +console_set_cursor(int32 x, int32 y) +{ + kSystemTable->ConOut->SetCursorPosition(kSystemTable->ConOut, x, y); +} + + +void +console_show_cursor(void) +{ + kSystemTable->ConOut->EnableCursor(kSystemTable->ConOut, true); +} + + +void +console_hide_cursor(void) +{ + kSystemTable->ConOut->EnableCursor(kSystemTable->ConOut, false); +} + + +void +console_set_color(int32 foreground, int32 background) +{ + kSystemTable->ConOut->SetAttribute(kSystemTable->ConOut, + EFI_TEXT_ATTR((foreground & 0xf), (background & 0xf))); +} + + +int +console_wait_for_key(void) +{ + UINTN index; + EFI_STATUS status; + EFI_INPUT_KEY key; + EFI_EVENT event = kSystemTable->ConIn->WaitForKey; + + do { + kBootServices->WaitForEvent(1, &event, &index); + status = kSystemTable->ConIn->ReadKeyStroke(kSystemTable->ConIn, &key); + } while (status == EFI_NOT_READY); + + if (key.UnicodeChar > 0) + return (int) key.UnicodeChar; + + switch (key.ScanCode) { + case SCAN_UP: + return TEXT_CONSOLE_KEY_UP; + case SCAN_DOWN: + return TEXT_CONSOLE_KEY_DOWN; + case SCAN_LEFT: + return TEXT_CONSOLE_KEY_LEFT; + case SCAN_RIGHT: + return TEXT_CONSOLE_KEY_RIGHT; + case SCAN_PAGE_UP: + return TEXT_CONSOLE_KEY_PAGE_UP; + case SCAN_PAGE_DOWN: + return TEXT_CONSOLE_KEY_PAGE_DOWN; + case SCAN_HOME: + return TEXT_CONSOLE_KEY_HOME; + case SCAN_END: + return TEXT_CONSOLE_KEY_END; + } + return 0; +} + + +static void update_screen_size(void) +{ + UINTN width, height; + UINTN area = 0; + SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut = kSystemTable->ConOut; + + for (int mode = 0; mode < ConOut->Mode->MaxMode; ++mode) { + if (ConOut->QueryMode(ConOut, mode, &width, &height) == EFI_SUCCESS) { + if (width * height > area) { + sScreenWidth = width; + sScreenHeight = height; + sScreenMode = mode; + } + } + } + + ConOut->SetMode(ConOut, sScreenMode); +} + + +status_t +console_init(void) +{ + update_screen_size(); + console_hide_cursor(); + console_clear_screen(); + + // enable stdio functionality + stdin = (FILE *)&sInput; + stdout = stderr = (FILE *)&sOutput; + + return B_OK; +} + + +extern "C" void +platform_switch_to_text_mode(void) +{ + kSystemTable->ConOut->Reset(kSystemTable->ConOut, false); + kSystemTable->ConOut->SetMode(kSystemTable->ConOut, sScreenMode); +} diff --git a/src/system/boot/platform/efi/console.h b/src/system/boot/platform/efi/console.h new file mode 100644 index 0000000000..15942139e0 --- /dev/null +++ b/src/system/boot/platform/efi/console.h @@ -0,0 +1,15 @@ +/* +** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ +#ifndef CONSOLE_H +#define CONSOLE_H + + +#include + + +extern "C" status_t console_init(void); + + +#endif /* CONSOLE_H */ diff --git a/src/system/boot/platform/efi/efi_platform.h b/src/system/boot/platform/efi/efi_platform.h new file mode 100644 index 0000000000..b9670e9869 --- /dev/null +++ b/src/system/boot/platform/efi/efi_platform.h @@ -0,0 +1,23 @@ +/* + * Copyright 2013, Fredrik Homlqvist, fredrik.holmqvist@gmail.com. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef EFI_PLATFORM_H +#define EFI_PLATFORM_H + + +#include "efibind.h" +#include "efidef.h" +#include "efidevp.h" +#include "efiprot.h" +#include "eficon.h" +#include "efierr.h" +#include "efiapi.h" + + +extern const EFI_SYSTEM_TABLE *kSystemTable; +extern const EFI_BOOT_SERVICES *kBootServices; +extern const EFI_RUNTIME_SERVICES *kRuntimeServices; + + +#endif /* EFI_PLATFORM_H */ diff --git a/src/system/boot/platform/efi/start.c b/src/system/boot/platform/efi/start.c deleted file mode 100644 index fe36d5c63f..0000000000 --- a/src/system/boot/platform/efi/start.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011, Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "efibind.h" -#include "efidef.h" -#include "efidevp.h" -#include "eficon.h" -#include "efiprot.h" -#include "efiapi.h" -#include "efierr.h" - -static const CHAR16 *exampleText = L"Example EFI Application. Press any key!"; - -EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable); - -/** - * efi_main - The entry point for the EFI application - * @image: firmware-allocated handle that identifies the image - * @SystemTable: EFI system table - */ -EFI_STATUS -efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable) -{ - UINTN index; - EFI_EVENT event = systemTable->ConIn->WaitForKey; - - SIMPLE_TEXT_OUTPUT_INTERFACE *conOut = systemTable->ConOut; - conOut->OutputString(conOut, (CHAR16*)exampleText); - - systemTable->BootServices->WaitForEvent(1, &event, &index); - - return EFI_SUCCESS; -} diff --git a/src/system/boot/platform/efi/start.cpp b/src/system/boot/platform/efi/start.cpp new file mode 100644 index 0000000000..09ddbf0b84 --- /dev/null +++ b/src/system/boot/platform/efi/start.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2014-2016 Haiku, Inc. All rights reserved. + * Copyright 2013 Fredrik Holmqvist, fredrik.holmqvist@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include "console.h" +#include "efi_platform.h" + + +extern void (*__ctor_list)(void); +extern void (*__ctor_end)(void); + + +const EFI_SYSTEM_TABLE *kSystemTable; +const EFI_BOOT_SERVICES *kBootServices; +const EFI_RUNTIME_SERVICES *kRuntimeServices; + + +static void +call_ctors(void) +{ + void (**f)(void); + + for (f = &__ctor_list; f < &__ctor_end; f++) + (**f)(); +} + + +/** + * efi_main - The entry point for the EFI application + * @image: firmware-allocated handle that identifies the image + * @systemTable: EFI system table + */ +extern "C" EFI_STATUS +efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable) +{ + kSystemTable = systemTable; + kBootServices = systemTable->BootServices; + kRuntimeServices = systemTable->RuntimeServices; + + call_ctors(); + + console_init(); + + printf("Hello from EFI Loader for Haiku!\nPress any key to continue...\n"); + console_wait_for_key(); + + return EFI_SUCCESS; +}