1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <efi/types.h>
6 #include <efi/protocol/device-path-to-text.h>
7 #include <efi/protocol/file.h>
8 #include <efi/protocol/simple-file-system.h>
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <printf.h>
13 #include <xefi.h>
14 
15 xefi_global xefi_global_state;
16 
xefi_init(efi_handle img,efi_system_table * sys)17 void xefi_init(efi_handle img, efi_system_table* sys) {
18     gSys = sys;
19     gImg = img;
20     gBS = sys->BootServices;
21     gConOut = sys->ConOut;
22 }
23 
xefi_wait_any_key(void)24 void xefi_wait_any_key(void) {
25     efi_simple_text_input_protocol* sii = gSys->ConIn;
26     efi_input_key key;
27     while (sii->ReadKeyStroke(sii, &key) != EFI_SUCCESS)
28         ;
29 }
30 
xefi_fatal(const char * msg,efi_status status)31 void xefi_fatal(const char* msg, efi_status status) {
32     printf("\nERROR: %s (%s)\n", msg, xefi_strerror(status));
33     xefi_wait_any_key();
34     gBS->Exit(gImg, 1, 0, NULL);
35 }
36 
xefi_devpath_to_str(efi_device_path_protocol * path)37 char16_t* xefi_devpath_to_str(efi_device_path_protocol* path) {
38     efi_device_path_to_text_protocol* prot;
39     efi_status status = gBS->LocateProtocol(&DevicePathToTextProtocol, NULL, (void**)&prot);
40     if (EFI_ERROR(status)) {
41         return NULL;
42     }
43     return prot->ConvertDevicePathToText(path, false, false);
44 }
45 
xefi_cmp_guid(efi_guid * guid1,efi_guid * guid2)46 int xefi_cmp_guid(efi_guid* guid1, efi_guid* guid2) {
47     return memcmp(guid1, guid2, sizeof(efi_guid));
48 }
49 
xefi_handle_to_str(efi_handle h)50 char16_t* xefi_handle_to_str(efi_handle h) {
51     efi_device_path_protocol* path;
52     efi_status status = gBS->HandleProtocol(h, &DevicePathProtocol, (void*)&path);
53     if (EFI_ERROR(status)) {
54         char16_t* err;
55         status = gBS->AllocatePool(EfiLoaderData, sizeof(L"<NoPath>"), (void**)&err);
56         if (EFI_ERROR(status)) {
57             return NULL;
58         }
59         gBS->CopyMem(err, L"<NoPath>", sizeof(L"<NoPath>"));
60         return err;
61     }
62     char16_t* str = xefi_devpath_to_str(path);
63     if (str == NULL) {
64         char16_t* err;
65         status = gBS->AllocatePool(EfiLoaderData, sizeof(L"<NoString>"), (void**)&err);
66         if (EFI_ERROR(status)) {
67             return NULL;
68         }
69         gBS->CopyMem(err, L"<NoString>", sizeof(L"<NoString>"));
70         return err;
71     }
72     return str;
73 }
74 
xefi_open_protocol(efi_handle h,efi_guid * guid,void ** ifc)75 efi_status xefi_open_protocol(efi_handle h, efi_guid* guid, void** ifc) {
76     return gBS->OpenProtocol(h, guid, ifc, gImg, NULL,
77                              EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
78 }
79 
xefi_close_protocol(efi_handle h,efi_guid * guid)80 efi_status xefi_close_protocol(efi_handle h, efi_guid* guid) {
81     return gBS->CloseProtocol(h, guid, gImg, NULL);
82 }
83 
xefi_strerror(efi_status status)84 const char *xefi_strerror(efi_status status) {
85     switch (status) {
86 #define ERR_ENTRY(x) \
87     case x: {        \
88         return #x;   \
89     }
90         ERR_ENTRY(EFI_SUCCESS);
91         ERR_ENTRY(EFI_LOAD_ERROR);
92         ERR_ENTRY(EFI_INVALID_PARAMETER);
93         ERR_ENTRY(EFI_UNSUPPORTED);
94         ERR_ENTRY(EFI_BAD_BUFFER_SIZE);
95         ERR_ENTRY(EFI_BUFFER_TOO_SMALL);
96         ERR_ENTRY(EFI_NOT_READY);
97         ERR_ENTRY(EFI_DEVICE_ERROR);
98         ERR_ENTRY(EFI_WRITE_PROTECTED);
99         ERR_ENTRY(EFI_OUT_OF_RESOURCES);
100         ERR_ENTRY(EFI_VOLUME_CORRUPTED);
101         ERR_ENTRY(EFI_VOLUME_FULL);
102         ERR_ENTRY(EFI_NO_MEDIA);
103         ERR_ENTRY(EFI_MEDIA_CHANGED);
104         ERR_ENTRY(EFI_NOT_FOUND);
105         ERR_ENTRY(EFI_ACCESS_DENIED);
106         ERR_ENTRY(EFI_NO_RESPONSE);
107         ERR_ENTRY(EFI_NO_MAPPING);
108         ERR_ENTRY(EFI_TIMEOUT);
109         ERR_ENTRY(EFI_NOT_STARTED);
110         ERR_ENTRY(EFI_ALREADY_STARTED);
111         ERR_ENTRY(EFI_ABORTED);
112         ERR_ENTRY(EFI_ICMP_ERROR);
113         ERR_ENTRY(EFI_TFTP_ERROR);
114         ERR_ENTRY(EFI_PROTOCOL_ERROR);
115         ERR_ENTRY(EFI_INCOMPATIBLE_VERSION);
116         ERR_ENTRY(EFI_SECURITY_VIOLATION);
117         ERR_ENTRY(EFI_CRC_ERROR);
118         ERR_ENTRY(EFI_END_OF_MEDIA);
119         ERR_ENTRY(EFI_END_OF_FILE);
120         ERR_ENTRY(EFI_INVALID_LANGUAGE);
121         ERR_ENTRY(EFI_COMPROMISED_DATA);
122         ERR_ENTRY(EFI_IP_ADDRESS_CONFLICT);
123         ERR_ENTRY(EFI_HTTP_ERROR);
124 #undef ERR_ENTRY
125     }
126 
127     return "<Unknown error>";
128 }
129 
xefi_wstrerror(efi_status status)130 const char16_t* xefi_wstrerror(efi_status status) {
131     switch (status) {
132 #define ERR_ENTRY(x)     \
133     case x: {            \
134         return L"" #x;   \
135     }
136         ERR_ENTRY(EFI_SUCCESS);
137         ERR_ENTRY(EFI_LOAD_ERROR);
138         ERR_ENTRY(EFI_INVALID_PARAMETER);
139         ERR_ENTRY(EFI_UNSUPPORTED);
140         ERR_ENTRY(EFI_BAD_BUFFER_SIZE);
141         ERR_ENTRY(EFI_BUFFER_TOO_SMALL);
142         ERR_ENTRY(EFI_NOT_READY);
143         ERR_ENTRY(EFI_DEVICE_ERROR);
144         ERR_ENTRY(EFI_WRITE_PROTECTED);
145         ERR_ENTRY(EFI_OUT_OF_RESOURCES);
146         ERR_ENTRY(EFI_VOLUME_CORRUPTED);
147         ERR_ENTRY(EFI_VOLUME_FULL);
148         ERR_ENTRY(EFI_NO_MEDIA);
149         ERR_ENTRY(EFI_MEDIA_CHANGED);
150         ERR_ENTRY(EFI_NOT_FOUND);
151         ERR_ENTRY(EFI_ACCESS_DENIED);
152         ERR_ENTRY(EFI_NO_RESPONSE);
153         ERR_ENTRY(EFI_NO_MAPPING);
154         ERR_ENTRY(EFI_TIMEOUT);
155         ERR_ENTRY(EFI_NOT_STARTED);
156         ERR_ENTRY(EFI_ALREADY_STARTED);
157         ERR_ENTRY(EFI_ABORTED);
158         ERR_ENTRY(EFI_ICMP_ERROR);
159         ERR_ENTRY(EFI_TFTP_ERROR);
160         ERR_ENTRY(EFI_PROTOCOL_ERROR);
161         ERR_ENTRY(EFI_INCOMPATIBLE_VERSION);
162         ERR_ENTRY(EFI_SECURITY_VIOLATION);
163         ERR_ENTRY(EFI_CRC_ERROR);
164         ERR_ENTRY(EFI_END_OF_MEDIA);
165         ERR_ENTRY(EFI_END_OF_FILE);
166         ERR_ENTRY(EFI_INVALID_LANGUAGE);
167         ERR_ENTRY(EFI_COMPROMISED_DATA);
168         ERR_ENTRY(EFI_IP_ADDRESS_CONFLICT);
169         ERR_ENTRY(EFI_HTTP_ERROR);
170 #undef ERR_ENTRY
171     }
172 
173     return L"<Unknown error>";
174 }
175 
strlen_16(char16_t * str)176 size_t strlen_16(char16_t* str) {
177     size_t len = 0;
178     while (*(str + len) != '\0') {
179         len++;
180     }
181 
182     return len;
183 }
184