| // 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 <efi/types.h> |
| #include <efi/protocol/device-path-to-text.h> |
| #include <efi/protocol/file.h> |
| #include <efi/protocol/simple-file-system.h> |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <printf.h> |
| #include <xefi.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; |
| } |