summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2013-12-15 18:37:05 +0100
committerKay Sievers <kay@vrfy.org>2013-12-15 18:42:19 +0100
commit7aea23a8d83e8b34669e11bb6905b78b79761e86 (patch)
treeda1acac72d45551bb2819a97266dbed9c8f0cb5b
parent47088fdab552286b543c42a8a617accb23eaf119 (diff)
split out util.[ch]
-rw-r--r--Makefile.am1
-rw-r--r--src/efi/gummiboot.c293
-rw-r--r--src/efi/util.c313
-rw-r--r--src/efi/util.h42
4 files changed, 357 insertions, 292 deletions
diff --git a/Makefile.am b/Makefile.am
index f3c9cfa..5b53632 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -74,6 +74,7 @@ CLEANFILES += man/gummiboot.8
# flags.
efi_loadername = gummiboot$(MACHINE_TYPE_NAME).efi
efi_sources = \
+ src/efi/util.c \
src/efi/graphics.c \
src/efi/gummiboot.c
diff --git a/src/efi/gummiboot.c b/src/efi/gummiboot.c
index 4bcef87..deaf9e5 100644
--- a/src/efi/gummiboot.c
+++ b/src/efi/gummiboot.c
@@ -28,6 +28,7 @@
#include <efi.h>
#include <efilib.h>
+#include "util.h"
#include "graphics.h"
#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
@@ -41,13 +42,6 @@
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: gummiboot " VERSION " ####";
-/*
- * Allocated random UUID, intended to be shared across tools that implement
- * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
- * associated EFI variables.
- */
-static const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
-
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
enum loader_type {
@@ -86,136 +80,6 @@ typedef struct {
CHAR16 *entries_auto;
} Config;
-static CHAR16 *stra_to_str(CHAR8 *stra);
-
-#ifdef __x86_64__
-static UINT64 ticks_read(void) {
- UINT64 a, d;
- __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
- return (d << 32) | a;
-}
-#else
-static UINT64 ticks_read(void) {
- UINT64 val;
- __asm__ volatile ("rdtsc" : "=A" (val));
- return val;
-}
-#endif
-
-/* count TSC ticks during a millisecond delay */
-static UINT64 ticks_freq(void) {
- UINT64 ticks_start, ticks_end;
-
- ticks_start = ticks_read();
- uefi_call_wrapper(BS->Stall, 1, 1000);
- ticks_end = ticks_read();
-
- return (ticks_end - ticks_start) * 1000;
-}
-
-static UINT64 time_usec(void) {
- UINT64 ticks;
- static UINT64 freq;
-
- ticks = ticks_read();
- if (ticks == 0)
- return 0;
-
- if (freq == 0) {
- freq = ticks_freq();
- if (freq == 0)
- return 0;
- }
-
- return 1000 * 1000 * ticks / freq;
-}
-
-static EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) {
- UINT32 flags;
-
- flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
- if (persistent)
- flags |= EFI_VARIABLE_NON_VOLATILE;
-
- return uefi_call_wrapper(RT->SetVariable, 5, name, (EFI_GUID *)vendor, flags, size, buf);
-}
-
-static EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent) {
- return efivar_set_raw(&loader_guid, name, (CHAR8 *)value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
-}
-
-static EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) {
- CHAR8 *buf;
- UINTN l;
- EFI_STATUS err;
-
- l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
- buf = AllocatePool(l);
- if (!buf)
- return EFI_OUT_OF_RESOURCES;
-
- err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf);
- if (!EFI_ERROR(err)) {
- *buffer = buf;
- if (size)
- *size = l;
- } else
- FreePool(buf);
- return err;
-
-}
-
-static EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
- CHAR8 *buf;
- CHAR16 *val;
- UINTN size;
- EFI_STATUS err;
-
- err = efivar_get_raw(&loader_guid, name, &buf, &size);
- if (EFI_ERROR(err))
- return err;
-
- val = StrDuplicate((CHAR16 *)buf);
- if (!val) {
- FreePool(val);
- return EFI_OUT_OF_RESOURCES;
- }
-
- *value = val;
- return EFI_SUCCESS;
-}
-
-static EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
- CHAR16 str[32];
-
- SPrint(str, 32, L"%d", i);
- return efivar_set(name, str, persistent);
-}
-
-static EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) {
- CHAR16 *val;
- EFI_STATUS err;
-
- err = efivar_get(name, &val);
- if (!EFI_ERROR(err)) {
- *i = Atoi(val);
- FreePool(val);
- }
- return err;
-}
-
-static VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
- CHAR16 str[32];
-
- if (usec == 0)
- usec = time_usec();
- if (usec == 0)
- return;
-
- SPrint(str, 32, L"%ld", usec);
- efivar_set(name, str, FALSE);
-}
-
#define EFI_SHIFT_STATE_VALID 0x80000000
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define EFI_LEFT_CONTROL_PRESSED 0x00000008
@@ -1188,131 +1052,6 @@ static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2)
return StrCmp(os1, os2);
}
-static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
- CHAR16 unichar;
- UINTN len;
- UINTN i;
-
- if (stra[0] < 0x80)
- len = 1;
- else if ((stra[0] & 0xe0) == 0xc0)
- len = 2;
- else if ((stra[0] & 0xf0) == 0xe0)
- len = 3;
- else if ((stra[0] & 0xf8) == 0xf0)
- len = 4;
- else if ((stra[0] & 0xfc) == 0xf8)
- len = 5;
- else if ((stra[0] & 0xfe) == 0xfc)
- len = 6;
- else
- return -1;
-
- switch (len) {
- case 1:
- unichar = stra[0];
- break;
- case 2:
- unichar = stra[0] & 0x1f;
- break;
- case 3:
- unichar = stra[0] & 0x0f;
- break;
- case 4:
- unichar = stra[0] & 0x07;
- break;
- case 5:
- unichar = stra[0] & 0x03;
- break;
- case 6:
- unichar = stra[0] & 0x01;
- break;
- }
-
- for (i = 1; i < len; i++) {
- if ((stra[i] & 0xc0) != 0x80)
- return -1;
- unichar <<= 6;
- unichar |= stra[i] & 0x3f;
- }
-
- *c = unichar;
- return len;
-}
-
-static CHAR16 *stra_to_str(CHAR8 *stra) {
- UINTN strlen;
- UINTN len;
- UINTN i;
- CHAR16 *str;
-
- len = strlena(stra);
- str = AllocatePool((len + 1) * sizeof(CHAR16));
-
- strlen = 0;
- i = 0;
- while (i < len) {
- INTN utf8len;
-
- utf8len = utf8_to_16(stra + i, str + strlen);
- if (utf8len <= 0) {
- /* invalid utf8 sequence, skip the garbage */
- i++;
- continue;
- }
-
- strlen++;
- i += utf8len;
- }
- str[strlen] = '\0';
- return str;
-}
-
-static CHAR16 *stra_to_path(CHAR8 *stra) {
- CHAR16 *str;
- UINTN strlen;
- UINTN len;
- UINTN i;
-
- len = strlena(stra);
- str = AllocatePool((len + 2) * sizeof(CHAR16));
-
- str[0] = '\\';
- strlen = 1;
- i = 0;
- while (i < len) {
- INTN utf8len;
-
- utf8len = utf8_to_16(stra + i, str + strlen);
- if (utf8len <= 0) {
- /* invalid utf8 sequence, skip the garbage */
- i++;
- continue;
- }
-
- if (str[strlen] == '/')
- str[strlen] = '\\';
- if (str[strlen] == '\\' && str[strlen-1] == '\\') {
- /* skip double slashes */
- i += utf8len;
- continue;
- }
-
- strlen++;
- i += utf8len;
- }
- str[strlen] = '\0';
- return str;
-}
-
-static CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
- do {
- if (*s == c)
- return s;
- } while (*s++);
- return NULL;
-}
-
static CHAR8 *line_get_key_value(CHAR8 *content, UINTN *pos, CHAR8 **key_ret, CHAR8 **value_ret) {
CHAR8 *line;
UINTN linelen;
@@ -1552,36 +1291,6 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
config_add_entry(config, entry);
}
-UINTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, CHAR8 **content) {
- EFI_FILE_HANDLE handle;
- EFI_FILE_INFO *info;
- CHAR8 *buf;
- UINTN buflen;
- EFI_STATUS err;
- UINTN len = 0;
-
- err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
- if (EFI_ERROR(err))
- goto out;
-
- info = LibFileInfo(handle);
- buflen = info->FileSize+1;
- buf = AllocatePool(buflen);
-
- err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf);
- if (!EFI_ERROR(err)) {
- buf[buflen] = '\0';
- *content = buf;
- len = buflen;
- } else
- FreePool(buf);
-
- FreePool(info);
- uefi_call_wrapper(handle->Close, 1, handle);
-out:
- return len;
-}
-
static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
EFI_FILE_HANDLE entries_dir;
EFI_STATUS err;
diff --git a/src/efi/util.c b/src/efi/util.c
new file mode 100644
index 0000000..f3ed45f
--- /dev/null
+++ b/src/efi/util.c
@@ -0,0 +1,313 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "util.h"
+
+/*
+ * Allocated random UUID, intended to be shared across tools that implement
+ * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
+ * associated EFI variables.
+ */
+static const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
+
+#ifdef __x86_64__
+UINT64 ticks_read(void) {
+ UINT64 a, d;
+ __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
+ return (d << 32) | a;
+}
+#else
+UINT64 ticks_read(void) {
+ UINT64 val;
+ __asm__ volatile ("rdtsc" : "=A" (val));
+ return val;
+}
+#endif
+
+/* count TSC ticks during a millisecond delay */
+UINT64 ticks_freq(void) {
+ UINT64 ticks_start, ticks_end;
+
+ ticks_start = ticks_read();
+ uefi_call_wrapper(BS->Stall, 1, 1000);
+ ticks_end = ticks_read();
+
+ return (ticks_end - ticks_start) * 1000;
+}
+
+UINT64 time_usec(void) {
+ UINT64 ticks;
+ static UINT64 freq;
+
+ ticks = ticks_read();
+ if (ticks == 0)
+ return 0;
+
+ if (freq == 0) {
+ freq = ticks_freq();
+ if (freq == 0)
+ return 0;
+ }
+
+ return 1000 * 1000 * ticks / freq;
+}
+
+EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) {
+ UINT32 flags;
+
+ flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
+ if (persistent)
+ flags |= EFI_VARIABLE_NON_VOLATILE;
+
+ return uefi_call_wrapper(RT->SetVariable, 5, name, (EFI_GUID *)vendor, flags, size, buf);
+}
+
+EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent) {
+ return efivar_set_raw(&loader_guid, name, (CHAR8 *)value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
+}
+
+EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
+ CHAR8 *buf;
+ CHAR16 *val;
+ UINTN size;
+ EFI_STATUS err;
+
+ err = efivar_get_raw(&loader_guid, name, &buf, &size);
+ if (EFI_ERROR(err))
+ return err;
+
+ val = StrDuplicate((CHAR16 *)buf);
+ if (!val) {
+ FreePool(val);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *value = val;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
+ CHAR16 str[32];
+
+ SPrint(str, 32, L"%d", i);
+ return efivar_set(name, str, persistent);
+}
+
+EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) {
+ CHAR16 *val;
+ EFI_STATUS err;
+
+ err = efivar_get(name, &val);
+ if (!EFI_ERROR(err)) {
+ *i = Atoi(val);
+ FreePool(val);
+ }
+ return err;
+}
+
+EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) {
+ CHAR8 *buf;
+ UINTN l;
+ EFI_STATUS err;
+
+ l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
+ buf = AllocatePool(l);
+ if (!buf)
+ return EFI_OUT_OF_RESOURCES;
+
+ err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf);
+ if (!EFI_ERROR(err)) {
+ *buffer = buf;
+ if (size)
+ *size = l;
+ } else
+ FreePool(buf);
+ return err;
+
+}
+
+VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
+ CHAR16 str[32];
+
+ if (usec == 0)
+ usec = time_usec();
+ if (usec == 0)
+ return;
+
+ SPrint(str, 32, L"%ld", usec);
+ efivar_set(name, str, FALSE);
+}
+
+static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
+ CHAR16 unichar;
+ UINTN len;
+ UINTN i;
+
+ if (stra[0] < 0x80)
+ len = 1;
+ else if ((stra[0] & 0xe0) == 0xc0)
+ len = 2;
+ else if ((stra[0] & 0xf0) == 0xe0)
+ len = 3;
+ else if ((stra[0] & 0xf8) == 0xf0)
+ len = 4;
+ else if ((stra[0] & 0xfc) == 0xf8)
+ len = 5;
+ else if ((stra[0] & 0xfe) == 0xfc)
+ len = 6;
+ else
+ return -1;
+
+ switch (len) {
+ case 1:
+ unichar = stra[0];
+ break;
+ case 2:
+ unichar = stra[0] & 0x1f;
+ break;
+ case 3:
+ unichar = stra[0] & 0x0f;
+ break;
+ case 4:
+ unichar = stra[0] & 0x07;
+ break;
+ case 5:
+ unichar = stra[0] & 0x03;
+ break;
+ case 6:
+ unichar = stra[0] & 0x01;
+ break;
+ }
+
+ for (i = 1; i < len; i++) {
+ if ((stra[i] & 0xc0) != 0x80)
+ return -1;
+ unichar <<= 6;
+ unichar |= stra[i] & 0x3f;
+ }
+
+ *c = unichar;
+ return len;
+}
+
+CHAR16 *stra_to_str(CHAR8 *stra) {
+ UINTN strlen;
+ UINTN len;
+ UINTN i;
+ CHAR16 *str;
+
+ len = strlena(stra);
+ str = AllocatePool((len + 1) * sizeof(CHAR16));
+
+ strlen = 0;
+ i = 0;
+ while (i < len) {
+ INTN utf8len;
+
+ utf8len = utf8_to_16(stra + i, str + strlen);
+ if (utf8len <= 0) {
+ /* invalid utf8 sequence, skip the garbage */
+ i++;
+ continue;
+ }
+
+ strlen++;
+ i += utf8len;
+ }
+ str[strlen] = '\0';
+ return str;
+}
+
+CHAR16 *stra_to_path(CHAR8 *stra) {
+ CHAR16 *str;
+ UINTN strlen;
+ UINTN len;
+ UINTN i;
+
+ len = strlena(stra);
+ str = AllocatePool((len + 2) * sizeof(CHAR16));
+
+ str[0] = '\\';
+ strlen = 1;
+ i = 0;
+ while (i < len) {
+ INTN utf8len;
+
+ utf8len = utf8_to_16(stra + i, str + strlen);
+ if (utf8len <= 0) {
+ /* invalid utf8 sequence, skip the garbage */
+ i++;
+ continue;
+ }
+
+ if (str[strlen] == '/')
+ str[strlen] = '\\';
+ if (str[strlen] == '\\' && str[strlen-1] == '\\') {
+ /* skip double slashes */
+ i += utf8len;
+ continue;
+ }
+
+ strlen++;
+ i += utf8len;
+ }
+ str[strlen] = '\0';
+ return str;
+}
+
+CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
+ do {
+ if (*s == c)
+ return s;
+ } while (*s++);
+ return NULL;
+}
+
+UINTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, CHAR8 **content) {
+ EFI_FILE_HANDLE handle;
+ EFI_FILE_INFO *info;
+ CHAR8 *buf;
+ UINTN buflen;
+ EFI_STATUS err;
+ UINTN len = 0;
+
+ err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(err))
+ goto out;
+
+ info = LibFileInfo(handle);
+ buflen = info->FileSize+1;
+ buf = AllocatePool(buflen);
+
+ err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf);
+ if (!EFI_ERROR(err)) {
+ buf[buflen] = '\0';
+ *content = buf;
+ len = buflen;
+ } else
+ FreePool(buf);
+
+ FreePool(info);
+ uefi_call_wrapper(handle->Close, 1, handle);
+out:
+ return len;
+}
+
+
diff --git a/src/efi/util.h b/src/efi/util.h
new file mode 100644
index 0000000..c2e4e70
--- /dev/null
+++ b/src/efi/util.h
@@ -0,0 +1,42 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ */
+
+#ifndef __GUMMIBOOT_UTIL_H
+#define __GUMMIBOOT_UTIL_H
+
+#include <efi.h>
+#include <efilib.h>
+
+UINT64 ticks_read(void);
+UINT64 ticks_freq(void);
+UINT64 time_usec(void);
+
+EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent);
+EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent);
+EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent);
+VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec);
+
+EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value);
+EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size);
+EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i);
+
+CHAR8 *strchra(CHAR8 *s, CHAR8 c);
+CHAR16 *stra_to_path(CHAR8 *stra);
+CHAR16 *stra_to_str(CHAR8 *stra);
+
+UINTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, CHAR8 **content);
+#endif