1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 * Allocated random UUID, intended to be shared across tools that implement
10 * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
11 * associated EFI variables.
13 const EFI_GUID loader_guid
= { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
16 UINT64
ticks_read(VOID
) {
18 __asm__
volatile ("rdtsc" : "=a" (a
), "=d" (d
));
21 #elif defined(__i386__)
22 UINT64
ticks_read(VOID
) {
24 __asm__
volatile ("rdtsc" : "=A" (val
));
28 UINT64
ticks_read(VOID
) {
34 /* count TSC ticks during a millisecond delay */
35 UINT64
ticks_freq(VOID
) {
36 UINT64 ticks_start
, ticks_end
;
38 ticks_start
= ticks_read();
39 uefi_call_wrapper(BS
->Stall
, 1, 1000);
40 ticks_end
= ticks_read();
42 return (ticks_end
- ticks_start
) * 1000;
45 UINT64
time_usec(VOID
) {
59 return 1000 * 1000 * ticks
/ freq
;
62 EFI_STATUS
parse_boolean(const CHAR8
*v
, BOOLEAN
*b
) {
64 return EFI_INVALID_PARAMETER
;
66 if (strcmpa(v
, (CHAR8
*)"1") == 0 ||
67 strcmpa(v
, (CHAR8
*)"yes") == 0 ||
68 strcmpa(v
, (CHAR8
*)"y") == 0 ||
69 strcmpa(v
, (CHAR8
*)"true") == 0) {
74 if (strcmpa(v
, (CHAR8
*)"0") == 0 ||
75 strcmpa(v
, (CHAR8
*)"no") == 0 ||
76 strcmpa(v
, (CHAR8
*)"n") == 0 ||
77 strcmpa(v
, (CHAR8
*)"false") == 0) {
82 return EFI_INVALID_PARAMETER
;
85 EFI_STATUS
efivar_set_raw(const EFI_GUID
*vendor
, const CHAR16
*name
, const VOID
*buf
, UINTN size
, BOOLEAN persistent
) {
88 flags
= EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
;
90 flags
|= EFI_VARIABLE_NON_VOLATILE
;
92 return uefi_call_wrapper(RT
->SetVariable
, 5, (CHAR16
*) name
, (EFI_GUID
*)vendor
, flags
, size
, (VOID
*) buf
);
95 EFI_STATUS
efivar_set(const CHAR16
*name
, const CHAR16
*value
, BOOLEAN persistent
) {
96 return efivar_set_raw(&loader_guid
, name
, value
, value
? (StrLen(value
)+1) * sizeof(CHAR16
) : 0, persistent
);
99 EFI_STATUS
efivar_set_int(CHAR16
*name
, UINTN i
, BOOLEAN persistent
) {
102 SPrint(str
, 32, L
"%u", i
);
103 return efivar_set(name
, str
, persistent
);
106 EFI_STATUS
efivar_get(const CHAR16
*name
, CHAR16
**value
) {
107 _cleanup_freepool_ CHAR8
*buf
= NULL
;
112 err
= efivar_get_raw(&loader_guid
, name
, &buf
, &size
);
116 /* Make sure there are no incomplete characters in the buffer */
118 return EFI_INVALID_PARAMETER
;
120 /* Return buffer directly if it happens to be NUL terminated already */
121 if (size
>= 2 && buf
[size
-2] == 0 && buf
[size
-1] == 0) {
122 *value
= (CHAR16
*) buf
;
127 /* Make sure a terminating NUL is available at the end */
128 val
= AllocatePool(size
+ 2);
130 return EFI_OUT_OF_RESOURCES
;
132 CopyMem(val
, buf
, size
);
133 val
[size
/2] = 0; /* NUL terminate */
139 EFI_STATUS
efivar_get_int(const CHAR16
*name
, UINTN
*i
) {
140 _cleanup_freepool_ CHAR16
*val
= NULL
;
143 err
= efivar_get(name
, &val
);
150 EFI_STATUS
efivar_get_raw(const EFI_GUID
*vendor
, const CHAR16
*name
, CHAR8
**buffer
, UINTN
*size
) {
151 _cleanup_freepool_ CHAR8
*buf
= NULL
;
155 l
= sizeof(CHAR16
*) * EFI_MAXIMUM_VARIABLE_SIZE
;
156 buf
= AllocatePool(l
);
158 return EFI_OUT_OF_RESOURCES
;
160 err
= uefi_call_wrapper(RT
->GetVariable
, 5, (CHAR16
*) name
, (EFI_GUID
*)vendor
, NULL
, &l
, buf
);
161 if (!EFI_ERROR(err
)) {
171 VOID
efivar_set_time_usec(CHAR16
*name
, UINT64 usec
) {
179 SPrint(str
, 32, L
"%ld", usec
);
180 efivar_set(name
, str
, FALSE
);
183 static INTN
utf8_to_16(CHAR8
*stra
, CHAR16
*c
) {
190 else if ((stra
[0] & 0xe0) == 0xc0)
192 else if ((stra
[0] & 0xf0) == 0xe0)
194 else if ((stra
[0] & 0xf8) == 0xf0)
196 else if ((stra
[0] & 0xfc) == 0xf8)
198 else if ((stra
[0] & 0xfe) == 0xfc)
208 unichar
= stra
[0] & 0x1f;
211 unichar
= stra
[0] & 0x0f;
214 unichar
= stra
[0] & 0x07;
217 unichar
= stra
[0] & 0x03;
220 unichar
= stra
[0] & 0x01;
224 for (i
= 1; i
< len
; i
++) {
225 if ((stra
[i
] & 0xc0) != 0x80)
228 unichar
|= stra
[i
] & 0x3f;
235 CHAR16
*stra_to_str(CHAR8
*stra
) {
242 str
= AllocatePool((len
+ 1) * sizeof(CHAR16
));
249 utf8len
= utf8_to_16(stra
+ i
, str
+ strlen
);
251 /* invalid utf8 sequence, skip the garbage */
263 CHAR16
*stra_to_path(CHAR8
*stra
) {
270 str
= AllocatePool((len
+ 2) * sizeof(CHAR16
));
278 utf8len
= utf8_to_16(stra
+ i
, str
+ strlen
);
280 /* invalid utf8 sequence, skip the garbage */
285 if (str
[strlen
] == '/')
287 if (str
[strlen
] == '\\' && str
[strlen
-1] == '\\') {
288 /* skip double slashes */
300 CHAR8
*strchra(CHAR8
*s
, CHAR8 c
) {
308 EFI_STATUS
file_read(EFI_FILE_HANDLE dir
, const CHAR16
*name
, UINTN off
, UINTN size
, CHAR8
**content
, UINTN
*content_size
) {
309 EFI_FILE_HANDLE handle
;
310 _cleanup_freepool_ CHAR8
*buf
= NULL
;
313 err
= uefi_call_wrapper(dir
->Open
, 5, dir
, &handle
, (CHAR16
*) name
, EFI_FILE_MODE_READ
, 0ULL);
318 _cleanup_freepool_ EFI_FILE_INFO
*info
;
320 info
= LibFileInfo(handle
);
321 size
= info
->FileSize
+1;
325 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, off
);
330 buf
= AllocatePool(size
+ 1);
331 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &size
, buf
);
332 if (!EFI_ERROR(err
)) {
337 *content_size
= size
;
339 uefi_call_wrapper(handle
->Close
, 1, handle
);