EFI: Implement console code.

This commit is contained in:
Fredrik Holmqvist
2016-09-02 19:02:32 +12:00
committed by Jessica Hamilton
parent bd0604764e
commit 735f1daee9
6 changed files with 311 additions and 59 deletions
+2 -1
View File
@@ -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) ]
+218
View File
@@ -0,0 +1,218 @@
/*
* Copyright 2014-2016 Haiku, Inc. All rights reserved.
* Copyright 2013 Fredrik Holmqvist, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "console.h"
#include <string.h>
#include <SupportDefs.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <util/kernel_cpp.h>
#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);
}
+15
View File
@@ -0,0 +1,15 @@
/*
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <boot/platform/generic/text_console.h>
extern "C" status_t console_init(void);
#endif /* CONSOLE_H */
@@ -0,0 +1,23 @@
/*
* Copyright 2013, Fredrik Homlqvist, [email protected].
* 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 */
-58
View File
@@ -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;
}
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright 2014-2016 Haiku, Inc. All rights reserved.
* Copyright 2013 Fredrik Holmqvist, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#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;
}