* Copyright 2004-2008, Axel DΓΆrfler, axeld@pinc-software.de.
* Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
* Distributed under the terms of the MIT License.
*/
#include "efi_platform.h"
#include <efi/protocol/serial-io.h>
#include "serial.h"
#include <boot/platform.h>
#include <arch/cpu.h>
#include <arch/generic/debug_uart.h>
#include <arch/generic/debug_uart_8250.h>
#include <boot/stage2.h>
#include <boot/stdio.h>
#include <string.h>
static efi_guid sSerialIOProtocolGUID = EFI_SERIAL_IO_PROTOCOL_GUID;
static const uint32 kSerialBaudRate = 115200;
static efi_serial_io_protocol *sEFISerialIO = NULL;
static bool sSerialEnabled = false;
static bool sEFIAvailable = true;
DebugUART* gUART = NULL;
bool gUARTSkipInit = false;
static void
serial_putc(char ch)
{
if (!sSerialEnabled)
return;
if (sEFISerialIO != NULL) {
size_t bufSize = 1;
sEFISerialIO->Write(sEFISerialIO, &bufSize, &ch);
return;
}
#ifdef DEBUG
if (sEFIAvailable) {
char16_t ucsBuffer[2];
ucsBuffer[0] = ch;
ucsBuffer[1] = 0;
kSystemTable->ConOut->OutputString(kSystemTable->ConOut, ucsBuffer);
return;
}
#endif
if (gUART != NULL) {
gUART->PutChar(ch);
return;
}
}
extern "C" void
serial_puts(const char* string, size_t size)
{
if (!sSerialEnabled)
return;
while (size-- != 0) {
char ch = string[0];
if (ch == '\n') {
serial_putc('\r');
serial_putc('\n');
} else if (ch != '\r')
serial_putc(ch);
string++;
}
}
extern "C" void
serial_disable(void)
{
sSerialEnabled = false;
}
extern "C" void
serial_enable(void)
{
#if 0
sSerialEnabled = true;
if ((gUART != NULL) && !gUARTSkipInit)
gUART->InitPort(kSerialBaudRate);
#endif
}
extern "C" void
serial_init(void)
{
if (sEFIAvailable) {
efi_status status = kSystemTable->BootServices->LocateProtocol(
&sSerialIOProtocolGUID, NULL, (void**)&sEFISerialIO);
if (status != EFI_SUCCESS)
sEFISerialIO = NULL;
if (sEFISerialIO != NULL) {
status = sEFISerialIO->SetAttributes(sEFISerialIO, kSerialBaudRate, 0, 0, NoParity, 8,
OneStopBit);
if (status != EFI_SUCCESS)
sEFISerialIO = NULL;
return;
}
}
#if defined(__i386__) || defined(__x86_64__)
if (gUART == NULL) {
gUART = arch_get_uart_8250(0x3f8, 1843200);
memset(gKernelArgs.platform_args.serial_base_ports, 0,
sizeof(uint16) * MAX_SERIAL_PORTS);
gKernelArgs.platform_args.serial_base_ports[0] = 0x3f8;
}
#endif
if (gUART != NULL)
gUART->InitEarly();
}
extern "C" void
serial_kernel_handoff(void)
{
stdout = NULL;
stderr = NULL;
sEFISerialIO = NULL;
sEFIAvailable = false;
}