1 /**
2  * @file lv_uefi_private.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "../../lvgl.h"
11 
12 #if LV_USE_UEFI
13 
14 #include "lv_uefi_private.h"
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 
20 /**********************
21  *      TYPEDEFS
22  **********************/
23 
24 /**********************
25  *  STATIC PROTOTYPES
26  **********************/
27 
28 /**********************
29  *  GOLBAL VARIABLES
30  **********************/
31 EFI_HANDLE gLvEfiImageHandle = NULL;
32 EFI_SYSTEM_TABLE * gLvEfiST = NULL;
33 EFI_BOOT_SERVICES * gLvEfiBS = NULL;
34 EFI_RUNTIME_SERVICES * gLvEfiRT = NULL;
35 
36 /**********************
37  *  STATIC VARIABLES
38  **********************/
39 
40 /**********************
41  *      MACROS
42  **********************/
43 
44 /**********************
45  *   GLOBAL FUNCTIONS
46  **********************/
47 
48 /**
49  * @brief Test if a protocol is installed at a handle.
50  * @param handle The handle on which the protocol might be installed.
51  * @param protocol The guid of the protocol.
52  * @return TRUE if the protocol is installed, FALSE if not.
53 */
lv_uefi_protocol_test(EFI_HANDLE handle,EFI_GUID * protocol)54 bool lv_uefi_protocol_test(EFI_HANDLE handle, EFI_GUID * protocol)
55 {
56     EFI_STATUS status;
57     void * interface = NULL;
58 
59     if(handle == NULL) return false;
60     if(protocol == NULL) return false;
61 
62     status = gLvEfiBS->OpenProtocol(
63                  handle,
64                  protocol,
65                  &interface,
66                  gLvEfiImageHandle,
67                  NULL,
68                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
69     if(status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
70         LV_LOG_WARN("couldn't test protocol");
71         return FALSE;
72     }
73     else if(status == EFI_UNSUPPORTED) {
74         return FALSE;
75     }
76 
77     return TRUE;
78 }
79 
80 /**
81  * @brief Open a protocol.
82  * @param handle The handle on which the protocol is installed.
83  * @param protocol The guid of the protocol.
84  * @return A pointer to the interface, NULL if the protocol couldn't be opened.
85 */
lv_uefi_protocol_open(EFI_HANDLE handle,EFI_GUID * protocol)86 void * lv_uefi_protocol_open(EFI_HANDLE handle, EFI_GUID * protocol)
87 {
88     EFI_STATUS status;
89     void * interface = NULL;
90 
91     if(handle == NULL) return NULL;
92     if(protocol == NULL) return NULL;
93 
94     status = gLvEfiBS->OpenProtocol(
95                  handle,
96                  protocol,
97                  &interface,
98                  gLvEfiImageHandle,
99                  NULL,
100                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
101     if(status != EFI_SUCCESS) {
102         LV_LOG_ERROR("[lv_uefi] Couldn't open protocol %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X, error code: %llx.",
103                      protocol->Data1,
104                      protocol->Data2,
105                      protocol->Data3,
106                      protocol->Data4[0],
107                      protocol->Data4[1],
108                      protocol->Data4[2],
109                      protocol->Data4[3],
110                      protocol->Data4[4],
111                      protocol->Data4[5],
112                      protocol->Data4[6],
113                      protocol->Data4[7],
114                      status);
115         interface = NULL;
116     }
117 
118     return interface;
119 }
120 
121 /**
122  * @brief Close a protocol.
123  * @param handle The handle on which the protocol is installed.
124  * @param protocol The guid of the protocol.
125 */
lv_uefi_protocol_close(EFI_HANDLE handle,EFI_GUID * protocol)126 void lv_uefi_protocol_close(EFI_HANDLE handle, EFI_GUID * protocol)
127 {
128     EFI_STATUS status;
129 
130     if(handle == NULL) return;
131     if(protocol == NULL) return;
132 
133     status = gLvEfiBS->CloseProtocol(
134                  handle,
135                  protocol,
136                  gLvEfiImageHandle,
137                  NULL);
138     if(status != EFI_SUCCESS) {
139         LV_LOG_WARN("[lv_uefi] Couldn't close protocol %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X, error code: %llx.",
140                     protocol->Data1,
141                     protocol->Data2,
142                     protocol->Data3,
143                     protocol->Data4[0],
144                     protocol->Data4[1],
145                     protocol->Data4[2],
146                     protocol->Data4[3],
147                     protocol->Data4[4],
148                     protocol->Data4[5],
149                     protocol->Data4[6],
150                     protocol->Data4[7],
151                     status);
152     }
153 }
154 
155 /**
156  * @brief Convert an UCS-2 string to an ASCII string.
157  * The string must contain only characters >= 0x20 and <= 0X7E.
158  * @param ucs2 The UCS-2 string.
159  * @param ascii The buffer to store the ASCII string.
160  * @param ascii_len The size of the buffer in ASCII characters.
161  * @return The number of characters written to the buffer or 0 if
162  * there was an error.
163 */
lv_uefi_ucs2_to_ascii(const CHAR16 * ucs2,char * ascii,size_t ascii_len)164 size_t lv_uefi_ucs2_to_ascii(const CHAR16 * ucs2, char * ascii, size_t ascii_len)
165 {
166     size_t invalid_character_count;
167     size_t string_index;
168 
169     if(ucs2 == NULL || ascii == NULL || ascii_len == 0) {
170         return 0;
171     }
172 
173     invalid_character_count = 0;
174 
175     for(string_index = 0; ucs2[string_index] != 0x0000 && string_index < ascii_len - 1; string_index++) {
176         if(ucs2[string_index] < 0x20 || ucs2[string_index] > 0x7E) {
177             invalid_character_count++;
178         }
179         ascii[string_index] = (char) ucs2[string_index];
180     }
181 
182     /* terminate the string even if there was an error */
183     ascii[string_index] = 0x00;
184 
185     return invalid_character_count == 0 ? string_index : 0;
186 }
187 
188 /**
189  * @brief Convert an ASCII string to an UCS-2 string.
190  * The string must contain only characters >= 0x20 and <= 0X7E.
191  * @param ascii The ASCII string.
192  * @param ucs2 The buffer to store the UCS-2 string.
193  * @param ucs2_len The size of the buffer in UCS-2 characters.
194  * @return The number of bytes written to the buffer or 0 if
195  * there was an error.
196 */
lv_uefi_ascii_to_ucs2(const char * ascii,CHAR16 * ucs2,size_t ucs2_len)197 size_t lv_uefi_ascii_to_ucs2(const char * ascii, CHAR16 * ucs2, size_t ucs2_len)
198 {
199     size_t invalid_character_count;
200     size_t string_index;
201 
202     if(ascii == NULL || ucs2 == NULL || ucs2_len == 0) {
203         return 0;
204     }
205 
206     invalid_character_count = 0;
207 
208     for(string_index = 0; ascii[string_index] != 0x0000 && string_index < ucs2_len - 1; string_index++) {
209         if(ascii[string_index] < 0x20 || ascii[string_index] > 0x7E) {
210             invalid_character_count++;
211         }
212         ucs2[string_index] = (CHAR16) ascii[string_index];
213     }
214 
215     /* terminate the string even if there was an error */
216     ucs2[string_index] = 0x0000;
217 
218     return invalid_character_count == 0 ? string_index : 0;
219 }
220 
221 /**********************
222  *   STATIC FUNCTIONS
223  **********************/
224 
225 #endif