blob: 25ffd76b28363326897abc5763ddc58f9451c55c [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <printf.h>
#include <stdlib.h>
#include <string.h>
#include <xefi.h>
#include <efi/protocol/device-path-to-text.h>
#include <efi/protocol/file.h>
#include <efi/protocol/simple-file-system.h>
#include <efi/types.h>
xefi_global xefi_global_state;
void xefi_init(efi_handle img, efi_system_table* sys) {
gSys = sys;
gImg = img;
gBS = sys->BootServices;
gConOut = sys->ConOut;
}
void xefi_wait_any_key(void) {
efi_simple_text_input_protocol* sii = gSys->ConIn;
efi_input_key key;
while (sii->ReadKeyStroke(sii, &key) != EFI_SUCCESS)
;
}
void xefi_fatal(const char* msg, efi_status status) {
printf("\nERROR: %s (%s)\n", msg, xefi_strerror(status));
xefi_wait_any_key();
gBS->Exit(gImg, 1, 0, NULL);
}
char16_t* xefi_devpath_to_str(efi_device_path_protocol* path) {
efi_device_path_to_text_protocol* prot;
efi_status status = gBS->LocateProtocol(&DevicePathToTextProtocol, NULL, (void**)&prot);
if (EFI_ERROR(status)) {
return NULL;
}
return prot->ConvertDevicePathToText(path, false, false);
}
int xefi_cmp_guid(efi_guid* guid1, efi_guid* guid2) {
return memcmp(guid1, guid2, sizeof(efi_guid));
}
char16_t* xefi_handle_to_str(efi_handle h) {
efi_device_path_protocol* path;
efi_status status = gBS->HandleProtocol(h, &DevicePathProtocol, (void*)&path);
if (EFI_ERROR(status)) {
char16_t* err;
status = gBS->AllocatePool(EfiLoaderData, sizeof(L"<NoPath>"), (void**)&err);
if (EFI_ERROR(status)) {
return NULL;
}
gBS->CopyMem(err, L"<NoPath>", sizeof(L"<NoPath>"));
return err;
}
char16_t* str = xefi_devpath_to_str(path);
if (str == NULL) {
char16_t* err;
status = gBS->AllocatePool(EfiLoaderData, sizeof(L"<NoString>"), (void**)&err);
if (EFI_ERROR(status)) {
return NULL;
}
gBS->CopyMem(err, L"<NoString>", sizeof(L"<NoString>"));
return err;
}
return str;
}
efi_status xefi_open_protocol(efi_handle h, efi_guid* guid, void** ifc) {
return gBS->OpenProtocol(h, guid, ifc, gImg, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
}
efi_status xefi_close_protocol(efi_handle h, efi_guid* guid) {
return gBS->CloseProtocol(h, guid, gImg, NULL);
}
const char* xefi_strerror(efi_status status) {
switch (status) {
#define ERR_ENTRY(x) \
case x: { \
return #x; \
}
ERR_ENTRY(EFI_SUCCESS);
ERR_ENTRY(EFI_LOAD_ERROR);
ERR_ENTRY(EFI_INVALID_PARAMETER);
ERR_ENTRY(EFI_UNSUPPORTED);
ERR_ENTRY(EFI_BAD_BUFFER_SIZE);
ERR_ENTRY(EFI_BUFFER_TOO_SMALL);
ERR_ENTRY(EFI_NOT_READY);
ERR_ENTRY(EFI_DEVICE_ERROR);
ERR_ENTRY(EFI_WRITE_PROTECTED);
ERR_ENTRY(EFI_OUT_OF_RESOURCES);
ERR_ENTRY(EFI_VOLUME_CORRUPTED);
ERR_ENTRY(EFI_VOLUME_FULL);
ERR_ENTRY(EFI_NO_MEDIA);
ERR_ENTRY(EFI_MEDIA_CHANGED);
ERR_ENTRY(EFI_NOT_FOUND);
ERR_ENTRY(EFI_ACCESS_DENIED);
ERR_ENTRY(EFI_NO_RESPONSE);
ERR_ENTRY(EFI_NO_MAPPING);
ERR_ENTRY(EFI_TIMEOUT);
ERR_ENTRY(EFI_NOT_STARTED);
ERR_ENTRY(EFI_ALREADY_STARTED);
ERR_ENTRY(EFI_ABORTED);
ERR_ENTRY(EFI_ICMP_ERROR);
ERR_ENTRY(EFI_TFTP_ERROR);
ERR_ENTRY(EFI_PROTOCOL_ERROR);
ERR_ENTRY(EFI_INCOMPATIBLE_VERSION);
ERR_ENTRY(EFI_SECURITY_VIOLATION);
ERR_ENTRY(EFI_CRC_ERROR);
ERR_ENTRY(EFI_END_OF_MEDIA);
ERR_ENTRY(EFI_END_OF_FILE);
ERR_ENTRY(EFI_INVALID_LANGUAGE);
ERR_ENTRY(EFI_COMPROMISED_DATA);
ERR_ENTRY(EFI_IP_ADDRESS_CONFLICT);
ERR_ENTRY(EFI_HTTP_ERROR);
#undef ERR_ENTRY
}
return "<Unknown error>";
}
const char16_t* xefi_wstrerror(efi_status status) {
switch (status) {
#define ERR_ENTRY(x) \
case x: { \
return L"" #x; \
}
ERR_ENTRY(EFI_SUCCESS);
ERR_ENTRY(EFI_LOAD_ERROR);
ERR_ENTRY(EFI_INVALID_PARAMETER);
ERR_ENTRY(EFI_UNSUPPORTED);
ERR_ENTRY(EFI_BAD_BUFFER_SIZE);
ERR_ENTRY(EFI_BUFFER_TOO_SMALL);
ERR_ENTRY(EFI_NOT_READY);
ERR_ENTRY(EFI_DEVICE_ERROR);
ERR_ENTRY(EFI_WRITE_PROTECTED);
ERR_ENTRY(EFI_OUT_OF_RESOURCES);
ERR_ENTRY(EFI_VOLUME_CORRUPTED);
ERR_ENTRY(EFI_VOLUME_FULL);
ERR_ENTRY(EFI_NO_MEDIA);
ERR_ENTRY(EFI_MEDIA_CHANGED);
ERR_ENTRY(EFI_NOT_FOUND);
ERR_ENTRY(EFI_ACCESS_DENIED);
ERR_ENTRY(EFI_NO_RESPONSE);
ERR_ENTRY(EFI_NO_MAPPING);
ERR_ENTRY(EFI_TIMEOUT);
ERR_ENTRY(EFI_NOT_STARTED);
ERR_ENTRY(EFI_ALREADY_STARTED);
ERR_ENTRY(EFI_ABORTED);
ERR_ENTRY(EFI_ICMP_ERROR);
ERR_ENTRY(EFI_TFTP_ERROR);
ERR_ENTRY(EFI_PROTOCOL_ERROR);
ERR_ENTRY(EFI_INCOMPATIBLE_VERSION);
ERR_ENTRY(EFI_SECURITY_VIOLATION);
ERR_ENTRY(EFI_CRC_ERROR);
ERR_ENTRY(EFI_END_OF_MEDIA);
ERR_ENTRY(EFI_END_OF_FILE);
ERR_ENTRY(EFI_INVALID_LANGUAGE);
ERR_ENTRY(EFI_COMPROMISED_DATA);
ERR_ENTRY(EFI_IP_ADDRESS_CONFLICT);
ERR_ENTRY(EFI_HTTP_ERROR);
#undef ERR_ENTRY
}
return L"<Unknown error>";
}
size_t strlen_16(char16_t* str) {
size_t len = 0;
while (*(str + len) != '\0') {
len++;
}
return len;
}