1 /**
2 * @file lv_fs_uefi.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "../../../lvgl.h"
10
11 #if LV_USE_FS_UEFI && LV_USE_UEFI
12
13 #include "../../drivers/uefi/lv_uefi_private.h"
14
15 #include "../../core/lv_global.h"
16
17 /*********************
18 * DEFINES
19 *********************/
20 #if LV_FS_UEFI_LETTER == '\0'
21 #error "LV_FS_UEFI_LETTER must be set to a valid value"
22 #else
23 #if (LV_FS_UEFI_LETTER < 'A') || (LV_FS_UEFI_LETTER > 'Z')
24 #if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
25 #error "LV_FS_UEFI_LETTER must be an upper case ASCII letter"
26 #else /*Lean rules for backward compatibility*/
27 #warning LV_FS_UEFI_LETTER should be an upper case ASCII letter. \
28 Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
29 #endif
30 #endif
31 #endif
32
33 /**********************
34 * TYPEDEFS
35 **********************/
36
37 typedef struct _lv_uefi_fs_file_context_t {
38 EFI_FILE_PROTOCOL * interface;
39 } lv_uefi_fs_file_context_t;
40
41 /**********************
42 * STATIC PROTOTYPES
43 **********************/
44
45 static void lv_fs_drv_uefi_init(lv_fs_drv_t * drv, char fs_drive_letter, EFI_HANDLE fs_handle);
46 static void lv_fs_drv_uefi_deinit(lv_fs_drv_t * drv);
47
48 static void lv_fs_uefi_lvgl_path_to_uefi_path(CHAR16 * path);
49 static void lv_fs_uefi_uefi_path_to_lvgl_path(CHAR16 * path);
50 static bool lv_fs_uefi_is_dot_path(CONST CHAR16 * path);
51 static bool lv_fs_uefi_is_dir(EFI_FILE_PROTOCOL * dir);
52 static bool lv_fs_uefi_is_file(EFI_FILE_PROTOCOL * file);
53 static EFI_FILE_INFO * lv_fs_uefi_get_info(EFI_FILE_PROTOCOL * file);
54
55 static bool lv_fs_uefi_ready_cb(lv_fs_drv_t * drv);
56
57 static void * lv_fs_uefi_open_cb(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
58 static lv_fs_res_t lv_fs_uefi_close_cb(lv_fs_drv_t * drv, void * file_p);
59 static lv_fs_res_t lv_fs_uefi_read_cb(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
60 static lv_fs_res_t lv_fs_uefi_write_cb(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
61 static lv_fs_res_t lv_fs_uefi_seek_cb(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
62 static lv_fs_res_t lv_fs_uefi_tell_cb(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
63
64 static void * lv_fs_uefi_dir_open_cb(lv_fs_drv_t * drv, const char * path);
65 static lv_fs_res_t lv_fs_uefi_dir_read_cb(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len);
66 static lv_fs_res_t lv_fs_uefi_dir_close_cb(lv_fs_drv_t * drv, void * rddir_p);
67
68 /**********************
69 * STATIC VARIABLES
70 **********************/
71
72 static EFI_GUID _uefi_guid_simple_file_system = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
73 static EFI_GUID _uefi_guid_loaded_image = EFI_LOADED_IMAGE_PROTOCOL_GUID;
74 static EFI_GUID _uefi_guid_file_info = EFI_FILE_INFO_ID;
75
76 /**********************
77 * MACROS
78 **********************/
79
80 /**********************
81 * GLOBAL FUNCTIONS
82 **********************/
83
84 /**
85 * Register a driver for the File system interface
86 */
lv_fs_uefi_init(void)87 void lv_fs_uefi_init(void)
88 {
89 EFI_LOADED_IMAGE_PROTOCOL * interface_loaded_image = NULL;
90 EFI_HANDLE fs_handle = NULL;
91
92 /*---------------------------------------------------
93 * Register the file system interface in LVGL
94 *--------------------------------------------------*/
95
96 interface_loaded_image = lv_uefi_protocol_open(gLvEfiImageHandle, &_uefi_guid_loaded_image);
97 LV_ASSERT_NULL(interface_loaded_image);
98
99 fs_handle = interface_loaded_image->DeviceHandle;
100
101 if(fs_handle == NULL) return;
102
103 lv_uefi_protocol_close(gLvEfiImageHandle, &_uefi_guid_loaded_image);
104
105 /*Add a simple driver to open images*/
106 lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->uefi_fs_drv);
107 lv_fs_drv_uefi_init(fs_drv_p, LV_FS_UEFI_LETTER, fs_handle);
108
109 lv_fs_drv_register(fs_drv_p);
110 }
111
112 /**********************
113 * STATIC FUNCTIONS
114 **********************/
115
lv_fs_uefi_ready_cb(lv_fs_drv_t * drv)116 static bool lv_fs_uefi_ready_cb(lv_fs_drv_t * drv)
117 {
118 EFI_HANDLE fs_handle = (EFI_HANDLE)drv->user_data;
119
120 return fs_handle != NULL;
121 }
122
lv_fs_uefi_open_cb(lv_fs_drv_t * drv,const char * path,lv_fs_mode_t mode)123 static void * lv_fs_uefi_open_cb(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
124 {
125 EFI_STATUS status;
126 EFI_FILE_PROTOCOL * fs_root = NULL;
127 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * fs_interface = NULL;
128 CHAR16 path_ucs2[LV_FS_MAX_PATH_LENGTH + 1];
129 lv_uefi_fs_file_context_t * file_ctx = NULL;
130 UINT64 uefi_mode = 0;
131
132 EFI_HANDLE fs_handle = (EFI_HANDLE)drv->user_data;
133
134 fs_interface = lv_uefi_protocol_open(fs_handle, &_uefi_guid_simple_file_system);
135 if(fs_interface == NULL) {
136 LV_LOG_WARN("[lv_uefi] Unable to open file system protocol.");
137 goto error;
138 }
139
140 status = fs_interface->OpenVolume(fs_interface, &fs_root);
141 if(status != EFI_SUCCESS) {
142 LV_LOG_WARN("[lv_uefi] Unable to open file system root.");
143 goto error;
144 }
145
146 if(lv_uefi_ascii_to_ucs2(path, path_ucs2, LV_FS_MAX_PATH_LENGTH + 1) == 0) {
147 LV_LOG_WARN("[lv_uefi] Unable to convert the ASCII path into an UCS-2 path.");
148 goto error;
149 }
150
151 lv_fs_uefi_lvgl_path_to_uefi_path(path_ucs2);
152
153 file_ctx = lv_calloc(1, sizeof(lv_uefi_fs_file_context_t));
154 LV_ASSERT_MALLOC(file_ctx);
155
156 if(mode == LV_FS_MODE_WR) {
157 uefi_mode = EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE;
158 }
159 else {
160 uefi_mode = EFI_FILE_MODE_READ;
161 }
162
163 status = fs_root->Open(
164 fs_root,
165 &file_ctx->interface,
166 path_ucs2,
167 uefi_mode,
168 0);
169 if(status != EFI_SUCCESS) {
170 LV_LOG_WARN("[lv_uefi] Unable to open file '%s'.", path);
171 goto error;
172 }
173
174 if(!lv_fs_uefi_is_file(file_ctx->interface)) {
175 goto error;
176 }
177
178 goto finish;
179
180 error:
181 if(file_ctx != NULL) {
182 if(file_ctx->interface != NULL) file_ctx->interface->Close(file_ctx->interface);
183 lv_free(file_ctx);
184 file_ctx = NULL;
185 }
186
187 finish:
188 if(fs_interface != NULL) lv_uefi_protocol_close(fs_handle, &_uefi_guid_simple_file_system);
189 if(fs_root != NULL) fs_root->Close(fs_root);
190
191 return file_ctx;
192 }
193
lv_fs_uefi_close_cb(lv_fs_drv_t * drv,void * file_p)194 static lv_fs_res_t lv_fs_uefi_close_cb(lv_fs_drv_t * drv, void * file_p)
195 {
196 EFI_STATUS status;
197 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)file_p;
198
199 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
200
201 status = file_ctx->interface->Close(file_ctx->interface);
202 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
203
204 lv_free(file_ctx);
205
206 return LV_FS_RES_OK;
207 }
208
lv_fs_uefi_read_cb(lv_fs_drv_t * drv,void * file_p,void * buf,uint32_t btr,uint32_t * br)209 static lv_fs_res_t lv_fs_uefi_read_cb(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
210 {
211 EFI_STATUS status;
212 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)file_p;
213 UINTN buf_size = btr;
214
215 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
216
217 status = file_ctx->interface->Read(
218 file_ctx->interface,
219 &buf_size,
220 buf);
221 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
222
223 *br = (uint32_t) buf_size;
224
225 return LV_FS_RES_OK;
226 }
227
lv_fs_uefi_write_cb(lv_fs_drv_t * drv,void * file_p,const void * buf,uint32_t btw,uint32_t * bw)228 static lv_fs_res_t lv_fs_uefi_write_cb(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
229 {
230 EFI_STATUS status;
231 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)file_p;
232 UINTN buf_size = btw;
233
234 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
235
236 status = file_ctx->interface->Write(
237 file_ctx->interface,
238 &buf_size,
239 (VOID *)buf);
240 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
241
242 file_ctx->interface->Flush(file_ctx->interface);
243
244 *bw = (uint32_t) buf_size;
245
246 return LV_FS_RES_OK;
247 }
248
lv_fs_uefi_seek_cb(lv_fs_drv_t * drv,void * file_p,uint32_t pos,lv_fs_whence_t whence)249 static lv_fs_res_t lv_fs_uefi_seek_cb(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
250 {
251 EFI_STATUS status;
252 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)file_p;
253 UINT64 new_pos;
254
255 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
256
257 if(whence == LV_FS_SEEK_END) {
258 status = file_ctx->interface->SetPosition(
259 file_ctx->interface,
260 UINT64_MAX);
261 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
262
263 status = file_ctx->interface->GetPosition(
264 file_ctx->interface,
265 &new_pos);
266 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
267
268 if(new_pos < pos) {
269 new_pos = 0;
270 }
271 else {
272 new_pos -= pos;
273 }
274 }
275 else if(whence == LV_FS_SEEK_SET) {
276 new_pos = pos;
277 }
278 else if(whence == LV_FS_SEEK_CUR) {
279 status = file_ctx->interface->GetPosition(
280 file_ctx->interface,
281 &new_pos);
282 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
283
284 new_pos += pos;
285 }
286 else {
287 return LV_FS_RES_INV_PARAM;
288 }
289
290 status = file_ctx->interface->SetPosition(
291 file_ctx->interface,
292 new_pos);
293 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
294
295 return LV_FS_RES_OK;
296 }
297
lv_fs_uefi_tell_cb(lv_fs_drv_t * drv,void * file_p,uint32_t * pos_p)298 static lv_fs_res_t lv_fs_uefi_tell_cb(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
299 {
300 EFI_STATUS status;
301 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)file_p;
302 UINT64 pos;
303
304 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
305
306 status = file_ctx->interface->GetPosition(
307 file_ctx->interface,
308 &pos);
309 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
310
311 if(pos > UINT32_MAX) return LV_FS_RES_UNKNOWN;
312
313 *pos_p = (uint32_t) pos;
314
315 return LV_FS_RES_OK;
316 }
317
lv_fs_uefi_dir_open_cb(lv_fs_drv_t * drv,const char * path)318 static void * lv_fs_uefi_dir_open_cb(lv_fs_drv_t * drv, const char * path)
319 {
320 EFI_STATUS status;
321 EFI_FILE_PROTOCOL * fs_root = NULL;
322 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * fs_interface = NULL;
323 CHAR16 path_ucs2[LV_FS_MAX_PATH_LENGTH + 1];
324 lv_uefi_fs_file_context_t * file_ctx = NULL;
325 UINT64 mode = 0;
326 UINT64 attributes = 0;
327
328 EFI_HANDLE fs_handle = (EFI_HANDLE)drv->user_data;
329
330 fs_interface = lv_uefi_protocol_open(fs_handle, &_uefi_guid_simple_file_system);
331 if(fs_interface == NULL) {
332 LV_LOG_WARN("[lv_uefi] Unable to open file system protocol.");
333 goto error;
334 }
335
336 status = fs_interface->OpenVolume(fs_interface, &fs_root);
337 if(status != EFI_SUCCESS) {
338 LV_LOG_WARN("[lv_uefi] Unable to open file system root.");
339 goto error;
340 }
341
342 if(path != NULL && path[0] != '\0') {
343 if(lv_uefi_ascii_to_ucs2(path, path_ucs2, LV_FS_MAX_PATH_LENGTH + 1) == 0) {
344 LV_LOG_WARN("[lv_uefi] Unable to convert the ASCII path into an UCS-2 path.");
345 goto error;
346 }
347 }
348 else {
349 path_ucs2[0] = '\\';
350 path_ucs2[1] = '\0';
351 }
352
353 lv_fs_uefi_lvgl_path_to_uefi_path(path_ucs2);
354
355 file_ctx = lv_calloc(1, sizeof(lv_uefi_fs_file_context_t));
356 LV_ASSERT_MALLOC(file_ctx);
357
358 mode = EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE;
359 attributes = EFI_FILE_DIRECTORY;
360
361 status = fs_root->Open(
362 fs_root,
363 &file_ctx->interface,
364 path_ucs2,
365 mode,
366 attributes);
367 if(status != EFI_SUCCESS) {
368 LV_LOG_WARN("[lv_uefi] Unable to open directory '%s'.", path);
369 goto error;
370 }
371
372 if(!lv_fs_uefi_is_dir(file_ctx->interface)) {
373 goto error;
374 }
375
376 goto finish;
377
378 error:
379 if(file_ctx != NULL) {
380 if(file_ctx->interface != NULL) {
381 file_ctx->interface->Close(file_ctx->interface);
382 }
383 lv_free(file_ctx);
384 file_ctx = NULL;
385 }
386
387 finish:
388 if(fs_interface != NULL) lv_uefi_protocol_close(fs_handle, &_uefi_guid_simple_file_system);
389 if(fs_root != NULL) fs_root->Close(fs_root);
390
391 return file_ctx;
392 }
393
lv_fs_uefi_dir_read_cb(lv_fs_drv_t * drv,void * rddir_p,char * fn,uint32_t fn_len)394 static lv_fs_res_t lv_fs_uefi_dir_read_cb(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len)
395 {
396 lv_fs_res_t return_code;
397 EFI_STATUS status;
398 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)rddir_p;
399
400 EFI_FILE_INFO * info = NULL;
401 UINTN size;
402
403 CONST CHAR16 * fn_ucs2;
404
405 if(fn == NULL || fn_len == 0) return LV_FS_RES_INV_PARAM;
406 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
407
408 // skip . and ..
409 do {
410 if(info != NULL) lv_free(info);
411 info = NULL;
412 size = 0;
413 status = file_ctx->interface->Read(
414 file_ctx->interface,
415 &size,
416 info);
417 if(status == EFI_SUCCESS && size == 0) {
418 return_code = LV_FS_RES_OK;
419 *fn = '\0';
420 goto finish;
421 }
422 else if(status != EFI_BUFFER_TOO_SMALL) {
423 return_code = LV_FS_RES_NOT_EX;
424 goto error;
425 }
426
427 info = lv_calloc(1, size);
428 LV_ASSERT_MALLOC(info);
429
430 status = file_ctx->interface->Read(
431 file_ctx->interface,
432 &size,
433 info);
434 if(status != EFI_SUCCESS) {
435 return_code = LV_FS_RES_HW_ERR;
436 goto error;
437 }
438 } while(lv_fs_uefi_is_dot_path(info->FileName));
439
440 lv_fs_uefi_uefi_path_to_lvgl_path(info->FileName);
441
442 // skip leading \ and /
443 for(fn_ucs2 = info->FileName; *fn_ucs2 != L'\0'; fn_ucs2++) {
444 if(*fn_ucs2 != L'\\' && *fn_ucs2 != L'/') {
445 break;
446 }
447 }
448
449 if((info->Attribute & EFI_FILE_DIRECTORY) != 0) {
450 if(fn_len == 0) {
451 return_code = LV_FS_RES_UNKNOWN;
452 goto error;
453 }
454 fn[0] = '/';
455 fn++;
456 fn_len--;
457 }
458
459 if(lv_uefi_ucs2_to_ascii(fn_ucs2, fn, fn_len) == 0) {
460 LV_LOG_WARN("[lv_uefi] Unable to convert the UCS-2 path into an ascii path.");
461 return_code = LV_FS_RES_UNKNOWN;
462 goto error;
463 }
464
465 return_code = LV_FS_RES_OK;
466 goto finish;
467
468 error:
469
470 finish:
471 if(info) lv_free(info);
472
473 return return_code;
474 }
475
lv_fs_uefi_dir_close_cb(lv_fs_drv_t * drv,void * rddir_p)476 static lv_fs_res_t lv_fs_uefi_dir_close_cb(lv_fs_drv_t * drv, void * rddir_p)
477 {
478 EFI_STATUS status;
479 lv_uefi_fs_file_context_t * file_ctx = (lv_uefi_fs_file_context_t *)rddir_p;
480
481 if(file_ctx == NULL || file_ctx->interface == NULL) return LV_FS_RES_INV_PARAM;
482
483 status = file_ctx->interface->Close(file_ctx->interface);
484 if(status != EFI_SUCCESS) return LV_FS_RES_HW_ERR;
485
486 lv_free(file_ctx);
487
488 return LV_FS_RES_OK;
489 }
490
lv_fs_drv_uefi_init(lv_fs_drv_t * drv,char fs_drive_letter,EFI_HANDLE fs_handle)491 static void lv_fs_drv_uefi_init(lv_fs_drv_t * drv, char fs_drive_letter, EFI_HANDLE fs_handle)
492 {
493 LV_ASSERT_NULL(drv);
494 LV_ASSERT_NULL(fs_handle);
495
496 lv_fs_drv_init(drv);
497
498 drv->letter = fs_drive_letter;
499 drv->cache_size = 0;
500
501 drv->ready_cb = lv_fs_uefi_ready_cb;
502 drv->open_cb = lv_fs_uefi_open_cb;
503 drv->close_cb = lv_fs_uefi_close_cb;
504 drv->read_cb = lv_fs_uefi_read_cb;
505 drv->write_cb = lv_fs_uefi_write_cb;
506 drv->seek_cb = lv_fs_uefi_seek_cb;
507 drv->tell_cb = lv_fs_uefi_tell_cb;
508
509 drv->dir_open_cb = lv_fs_uefi_dir_open_cb;
510 drv->dir_read_cb = lv_fs_uefi_dir_read_cb;
511 drv->dir_close_cb = lv_fs_uefi_dir_close_cb;
512
513 drv->user_data = (void *) fs_handle;
514 }
515
lv_fs_drv_uefi_deinit(lv_fs_drv_t * drv)516 static void lv_fs_drv_uefi_deinit(lv_fs_drv_t * drv)
517 {
518 LV_ASSERT_NULL(drv);
519 drv->user_data = NULL;
520 }
521
lv_fs_uefi_lvgl_path_to_uefi_path(CHAR16 * path)522 static void lv_fs_uefi_lvgl_path_to_uefi_path(CHAR16 * path)
523 {
524 if(path == NULL) return;
525
526 for(; *path != '\0'; path++) {
527 if(*path == L'/') *path = L'\\';
528 }
529 }
530
lv_fs_uefi_uefi_path_to_lvgl_path(CHAR16 * path)531 static void lv_fs_uefi_uefi_path_to_lvgl_path(CHAR16 * path)
532 {
533 if(path == NULL) return;
534
535 for(; *path != '\0'; path++) {
536 if(*path == L'\\') *path = L'/';
537 }
538 }
539
lv_fs_uefi_is_dot_path(CONST CHAR16 * path)540 static bool lv_fs_uefi_is_dot_path(CONST CHAR16 * path)
541 {
542 if(path == NULL) return FALSE;
543
544 if(path[0] == L'.' && path[1] == L'\0') return TRUE;
545 if(path[0] == L'.' && path[1] == L'.' && path[2] == L'\0') return TRUE;
546
547 return FALSE;
548 }
549
lv_fs_uefi_is_dir(EFI_FILE_PROTOCOL * dir)550 static bool lv_fs_uefi_is_dir(EFI_FILE_PROTOCOL * dir)
551 {
552 UINT64 attributes;
553
554 if(dir == NULL) return FALSE;
555
556 EFI_FILE_INFO * info = lv_fs_uefi_get_info(dir);
557 if(info == NULL) return FALSE;
558
559 attributes = info->Attribute;
560 lv_free(info);
561
562 return (attributes & EFI_FILE_DIRECTORY) != 0;
563 }
564
lv_fs_uefi_is_file(EFI_FILE_PROTOCOL * file)565 static bool lv_fs_uefi_is_file(EFI_FILE_PROTOCOL * file)
566 {
567 UINT64 attributes;
568
569 if(file == NULL) return FALSE;
570
571 EFI_FILE_INFO * info = lv_fs_uefi_get_info(file);
572 if(info == NULL) return FALSE;
573
574 attributes = info->Attribute;
575 lv_free(info);
576
577 return (attributes & EFI_FILE_DIRECTORY) == 0;
578 }
579
lv_fs_uefi_get_info(EFI_FILE_PROTOCOL * file)580 static EFI_FILE_INFO * lv_fs_uefi_get_info(EFI_FILE_PROTOCOL * file)
581 {
582 EFI_STATUS status;
583 EFI_FILE_INFO * info = NULL;
584 UINTN size = 0;
585
586 status = file->GetInfo(file, &_uefi_guid_file_info, &size, info);
587 if(status != EFI_BUFFER_TOO_SMALL) return NULL;
588
589 info = lv_calloc(1, size);
590 LV_ASSERT_MALLOC(info);
591
592 status = file->GetInfo(file, &_uefi_guid_file_info, &size, info);
593 if(status != EFI_SUCCESS) {
594 lv_free(info);
595 return NULL;
596 }
597
598 return info;
599 }
600
601 #else /* LV_FS_UEFI_LETTER == 0*/
602
603 #if defined(LV_FS_UEFI_LETTER) && LV_FS_UEFI_LETTER != '\0'
604 #warning "LV_FS_UEFI is not enabled but LV_FS_UEFI_LETTER is set"
605 #endif
606
607 #endif
608