1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
15 * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
24 * Allocated random UUID, intended to be shared across tools that implement
25 * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
26 * associated EFI variables.
28 static const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
31 UINT64 ticks_read(VOID) {
33 __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
37 UINT64 ticks_read(VOID) {
39 __asm__ volatile ("rdtsc" : "=A" (val));
44 /* count TSC ticks during a millisecond delay */
45 UINT64 ticks_freq(VOID) {
46 UINT64 ticks_start, ticks_end;
48 ticks_start = ticks_read();
49 uefi_call_wrapper(BS->Stall, 1, 1000);
50 ticks_end = ticks_read();
52 return (ticks_end - ticks_start) * 1000;
55 UINT64 time_usec(VOID) {
69 return 1000 * 1000 * ticks / freq;
72 EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) {
75 flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
77 flags |= EFI_VARIABLE_NON_VOLATILE;
79 return uefi_call_wrapper(RT->SetVariable, 5, name, (EFI_GUID *)vendor, flags, size, buf);
82 EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent) {
83 return efivar_set_raw(&loader_guid, name, (CHAR8 *)value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
86 EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
89 SPrint(str, 32, L"%d", i);
90 return efivar_set(name, str, persistent);
93 EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
99 err = efivar_get_raw(&loader_guid, name, &buf, &size);
103 val = StrDuplicate((CHAR16 *)buf);
106 return EFI_OUT_OF_RESOURCES;
113 EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) {
117 err = efivar_get(name, &val);
118 if (!EFI_ERROR(err)) {
125 EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) {
130 l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
131 buf = AllocatePool(l);
133 return EFI_OUT_OF_RESOURCES;
135 err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf);
136 if (!EFI_ERROR(err)) {
146 VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
154 SPrint(str, 32, L"%ld", usec);
155 efivar_set(name, str, FALSE);
158 static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
165 else if ((stra[0] & 0xe0) == 0xc0)
167 else if ((stra[0] & 0xf0) == 0xe0)
169 else if ((stra[0] & 0xf8) == 0xf0)
171 else if ((stra[0] & 0xfc) == 0xf8)
173 else if ((stra[0] & 0xfe) == 0xfc)
183 unichar = stra[0] & 0x1f;
186 unichar = stra[0] & 0x0f;
189 unichar = stra[0] & 0x07;
192 unichar = stra[0] & 0x03;
195 unichar = stra[0] & 0x01;
199 for (i = 1; i < len; i++) {
200 if ((stra[i] & 0xc0) != 0x80)
203 unichar |= stra[i] & 0x3f;
210 CHAR16 *stra_to_str(CHAR8 *stra) {
217 str = AllocatePool((len + 1) * sizeof(CHAR16));
224 utf8len = utf8_to_16(stra + i, str + strlen);
226 /* invalid utf8 sequence, skip the garbage */
238 CHAR16 *stra_to_path(CHAR8 *stra) {
245 str = AllocatePool((len + 2) * sizeof(CHAR16));
253 utf8len = utf8_to_16(stra + i, str + strlen);
255 /* invalid utf8 sequence, skip the garbage */
260 if (str[strlen] == '/')
262 if (str[strlen] == '\\' && str[strlen-1] == '\\') {
263 /* skip double slashes */
275 CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
283 INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content) {
284 EFI_FILE_HANDLE handle;
290 err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
297 info = LibFileInfo(handle);
298 buflen = info->FileSize+1;
304 err = uefi_call_wrapper(handle->SetPosition, 2, handle, off);
309 buf = AllocatePool(buflen);
310 err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf);
311 if (!EFI_ERROR(err)) {
320 uefi_call_wrapper(handle->Close, 1, handle);