} Config;
static VOID cursor_left(UINTN *cursor, UINTN *first) {
+ assert(cursor);
+ assert(first);
+
if ((*cursor) > 0)
(*cursor)--;
else if ((*first) > 0)
UINTN x_max,
UINTN len) {
+ assert(cursor);
+ assert(first);
+
if ((*cursor)+1 < x_max)
(*cursor)++;
else if ((*first) + (*cursor) < len)
UINTN size, len, first, cursor, clear;
BOOLEAN exit, enter;
+ assert(line_out);
+
if (!line_in)
line_in = L"";
size = StrLen(line_in) + 1024;
}
static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
+ assert(config);
+
if (key == 0)
return -1;
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
UINTN x, y;
+ assert(config);
+ assert(loaded_image_path);
+
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
ConfigEntry **chosen_entry,
CHAR16 *loaded_image_path) {
+ assert(config);
+ assert(chosen_entry);
+ assert(loaded_image_path);
+
EFI_STATUS err;
UINTN visible_max;
UINTN idx_highlight;
}
static VOID config_add_entry(Config *config, ConfigEntry *entry) {
+ assert(config);
+ assert(entry);
+
if ((config->entry_count & 15) == 0) {
UINTN i;
CHAR8 *line, *value;
UINTN linelen;
+ assert(content);
+ assert(sep);
+ assert(pos);
+ assert(key_ret);
+ assert(value_ret);
+
skip:
line = content + *pos;
if (*line == '\0')
UINTN pos = 0;
CHAR8 *key, *value;
+ assert(config);
+ assert(content);
+
while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
if (strcmpa((CHAR8 *)"timeout", key) == 0) {
_cleanup_freepool_ CHAR16 *s = NULL;
UINTN left = UINTN_MAX, done = UINTN_MAX, factor = 1, i, next_left, next_done;
_cleanup_freepool_ CHAR16 *prefix = NULL;
+ assert(entry);
+ assert(path);
+ assert(file);
+
/*
* Parses a suffix of two counters (one going down, one going up) in the form "+LEFT-DONE" from the end of the
* filename (but before the .efi/.conf suffix), where the "-DONE" part is optional and may be left out (in
UINTN file_info_size, a, b;
EFI_STATUS r;
+ assert(entry);
+ assert(root_dir);
+
if (entry->tries_left == UINTN_MAX)
return;
EFI_FILE_HANDLE handle;
_cleanup_freepool_ CHAR16 *initrd = NULL;
+ assert(config);
+ assert(device);
+ assert(root_dir);
+ assert(path);
+ assert(file);
+ assert(content);
+ assert(loaded_image_path);
+
entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) {
UINTN sec;
EFI_STATUS err;
+ assert(root_dir);
+
*config = (Config) {
.editor = TRUE,
.auto_entries = TRUE,
EFI_FILE_HANDLE entries_dir;
EFI_STATUS err;
+ assert(config);
+ assert(device);
+ assert(root_dir);
+ assert(loaded_image_path);
+
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, (CHAR16*) L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL);
if (!EFI_ERROR(err)) {
for (;;) {
static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
INTN r;
+ assert(a);
+ assert(b);
+
/* Order entries that have no tries left to the beginning of the list */
if (a->tries_left != 0 && b->tries_left == 0)
return 1;
}
static VOID config_sort_entries(Config *config) {
+ assert(config);
+
for (UINTN i = 1; i < config->entry_count; i++) {
BOOLEAN more;
}
static INTN config_entry_find(Config *config, CHAR16 *id) {
+ assert(config);
+ assert(id);
+
for (UINTN i = 0; i < config->entry_count; i++)
if (StrCmp(config->entries[i]->id, id) == 0)
return (INTN) i;
EFI_STATUS err;
INTN i;
+ assert(config);
+
/*
* The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read.
static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
BOOLEAN non_unique = FALSE;
+ assert(entries);
+
for (UINTN i = 0; i < entry_count; i++)
entries[i]->non_unique = FALSE;
/* generate a unique title, avoiding non-distinguishable menu entries */
static VOID config_title_generate(Config *config) {
+ assert(config);
+
/* set title */
for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *title;
ConfigEntry *entry;
+ assert(config);
+ assert(id);
+ assert(title);
+ assert(call);
+
entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) {
.id = StrDuplicate(id),
ConfigEntry *entry;
+ assert(config);
+ assert(device);
+ assert(id);
+ assert(title);
+ assert(loader);
+
entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) {
.type = type,
ConfigEntry *entry;
EFI_STATUS err;
+ assert(config);
+ assert(device);
+ assert(root_dir);
+ assert(id);
+ assert(title);
+ assert(loader);
+
if (!config->auto_entries)
return FALSE;
UINTN handle_count = 0;
_cleanup_freepool_ EFI_HANDLE *handles = NULL;
+ assert(config);
+
if (!config->auto_entries)
return;
EFI_STATUS err;
ConfigEntry *entry;
+ assert(config);
+ assert(device);
+ assert(root_dir);
+
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, (CHAR16*) L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return;
EFI_DEVICE_PATH *parent;
UINTN len;
+ assert(path);
+ assert(node);
+
len = (UINT8*) NextDevicePathNode(node) - (UINT8*) path;
parent = (EFI_DEVICE_PATH*) AllocatePool(len + sizeof(EFI_DEVICE_PATH));
CopyMem(parent, path, len);
EFI_FILE *root_dir;
EFI_STATUS r;
+ assert(config);
+ assert(device);
+
partition_path = DevicePathFromHandle(device);
if (!partition_path)
return;
CHAR16 *options;
EFI_STATUS err;
+ assert(config);
+ assert(entry);
+
path = FileDevicePath(entry->device, entry->loader);
if (!path)
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path.");
}
static VOID config_free(Config *config) {
+ assert(config);
for (UINTN i = 0; i < config->entry_count; i++)
config_entry_free(config->entries[i]);
FreePool(config->entries);
UINTN sz = 0;
CHAR16 *p;
+ assert(config);
+
for (UINTN i = 0; i < config->entry_count; i++)
sz += StrLen(config->entries[i]->id) + 1;
EFI_INPUT_KEY k;
EFI_STATUS err;
+ assert(key);
+
if (!checked) {
err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
if (EFI_ERROR(err))
EFI_STATUS err;
BOOLEAN keep = FALSE;
+ assert(mode);
+
err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) {
Info = GraphicsOutput->Mode->Info;
}
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) {
+ assert(mode);
+
if (how == CONSOLE_MODE_AUTO)
return mode_auto(mode);
*/
#include "crc32.h"
+#include "macro-fundamental.h"
static const UINT32 crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
const UINT8 *p = buf;
UINT32 crc = seed;
+ assert(buf);
+
while (len > 0) {
crc = crc32_add_char(crc, *p++);
len--;
const UINT8 *p = buf;
UINT32 crc = seed;
+ assert(buf);
+
for (UINTN i = 0; i < len; i++) {
UINT8 x = *p++;
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
EFI_DEVICE_PATH *device_path;
+ assert(handle);
+
/* export the device path this image is started from */
device_path = DevicePathFromHandle(handle);
if (device_path) {
handover_f handover;
UINTN start = (UINTN)params->hdr.code32_start;
+ assert(params);
+
#ifdef __x86_64__
asm volatile ("cli");
start += 512;
EFI_PHYSICAL_ADDRESS addr;
EFI_STATUS err;
+ assert(image);
+ assert(cmdline);
+
image_params = (struct boot_params *) linux_addr;
if (image_params->hdr.boot_flag != 0xAA55 ||
#include <efi.h>
#include <efilib.h>
+#include "macro-fundamental.h"
#include "measure.h"
#define EFI_TCG_GUID \
EFI_PHYSICAL_ADDRESS event_log_last;
UINTN desc_len;
+ assert(tcg);
+ assert(description);
+
desc_len = (StrLen(description) + 1) * sizeof(CHAR16);
tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT));
EFI_TCG2_EVENT *tcg_event;
UINTN desc_len;
+ assert(tcg);
+ assert(description);
+
desc_len = StrLen(description) * sizeof(CHAR16);
tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1);
EFI_TCG *tpm1;
EFI_TCG2 *tpm2;
+ assert(description);
+
tpm2 = tcg2_interface_check();
if (tpm2)
return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
struct PeHeader *pe;
UINTN offset;
+ assert(base);
+ assert(sections);
+
dos = (struct DosFileHeader *)base;
if (CompareMem(dos->Magic, "MZ", 2) != 0)
EFI_STATUS err;
_cleanup_freepool_ CHAR8 *header = NULL;
+ assert(dir);
+ assert(path);
+
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return err;
EFI_RNG_PROTOCOL *rng;
EFI_STATUS err;
+ assert(ret);
+
/* Try to acquire the specified number of bytes from the UEFI RNG */
err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng);
struct sha256_ctx hash;
+ assert(old_seed);
+ assert(rng);
+ assert(system_token);
+
sha256_init_ctx(&hash);
sha256_process_bytes(old_seed, size, &hash);
if (rng)
_cleanup_freepool_ VOID *output = NULL;
+ assert(old_seed);
+ assert(rng);
+ assert(system_token);
+ assert(ret);
+
/* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
* range counter_start…counter_start+n-1. */
EFI_STATUS err;
UINTN n;
+ assert(old_seed);
+ assert(rng);
+ assert(system_token);
+ assert(ret_new_seed);
+ assert(ret_for_kernel);
+
/* This takes the old seed file contents, an (optional) random number acquired from the UEFI RNG, an
* (optional) system 'token' installed once by the OS installer in an EFI variable, and hashes them
* together in counter mode, generating a new seed (to replace the file on disk) and the seed for the
EFI_STATUS err;
UINTN size;
+ assert(ret);
+ assert(ret_size);
+
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND)
static VOID validate_sha256(void) {
-#ifndef __OPTIMIZE__
+#ifdef EFI_DEBUG
/* Let's validate our SHA256 implementation. We stole it from glibc, and converted it to UEFI
* style. We better check whether it does the right stuff. We use the simpler test vectors from the
* SHA spec. Note that we strip this out in optimization builds. */
sha256_process_bytes(array[i].string, strlena((const CHAR8*) array[i].string), &hash);
sha256_finish_ctx(&hash, result);
- if (CompareMem(result, array[i].hash, HASH_VALUE_SIZE) != 0) {
- log_error_stall(L"SHA256 failed validation.");
- return;
- }
+ assert(CompareMem(result, array[i].hash, HASH_VALUE_SIZE) == 0);
}
- Print(L"SHA256 validated\n");
#endif
}
_cleanup_freepool_ EFI_FILE_INFO *info = NULL;
EFI_STATUS err;
+ assert(root_dir);
+
validate_sha256();
if (mode == RANDOM_SEED_OFF)
/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
+#include "macro-fundamental.h"
#include "sha256.h"
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/* Initialize structure containing state of computation.
(FIPS 180-2:5.3.2) */
void sha256_init_ctx(struct sha256_ctx *ctx) {
+ assert(ctx);
+
ctx->H[0] = 0x6a09e667;
ctx->H[1] = 0xbb67ae85;
ctx->H[2] = 0x3c6ef372;
UINT32 bytes = ctx->buflen;
UINTN pad;
+ assert(ctx);
+ assert(resbuf);
+
/* Now count remaining bytes. */
ctx->total64 += bytes;
}
void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
+ assert(buffer);
+ assert(ctx);
+
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
const UINT32 *words = buffer;
UINTN nwords = len / sizeof (UINT32);
+
+ assert(buffer);
+ assert(ctx);
+
UINT32 a = ctx->H[0];
UINT32 b = ctx->H[1];
UINT32 c = ctx->H[2];
VOID *file_buffer, UINTN file_size, BOOLEAN boot_policy) {
EFI_STATUS status;
+ assert(this);
+ assert(device_path);
+ assert(file_buffer);
+
/* Chain original security policy */
status = uefi_call_wrapper(es2fa, 5, this, device_path, file_buffer, file_size, boot_policy);
_cleanup_freepool_ CHAR8 *file_buffer = NULL;
UINTN file_size;
+ assert(this);
+ assert(device_path_const);
+
if (!device_path_const)
return EFI_INVALID_PARAMETER;
struct bmp_map *map;
UINTN row_size;
+ assert(bmp);
+ assert(ret_dib);
+ assert(ret_map);
+ assert(pixmap);
+
if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
return EFI_INVALID_PARAMETER;
static VOID pixel_blend(UINT32 *dst, const UINT32 source) {
UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g;
+ assert(dst);
+
alpha = (source & 0xff);
/* convert src from RGBA to XRGB */
UINT8 *pixmap) {
UINT8 *in;
+ assert(buf);
+ assert(dib);
+ assert(map);
+ assert(pixmap);
+
/* transform and copy pixels */
in = pixmap;
for (UINTN y = 0; y < dib->y; y++) {
UINTN y_pos = 0;
EFI_STATUS err;
+ assert(content);
+
if (!background) {
if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) {
pixel.Red = 0xc0;
}
EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) {
+ assert(b);
+
if (!v)
return EFI_INVALID_PARAMETER;
}
EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags) {
+ assert(vendor);
+ assert(name);
+ assert(buf || size == 0);
+
flags |= EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf);
}
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags) {
+ assert(vendor);
+ assert(name);
+
return efivar_set_raw(vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, flags);
}
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags) {
CHAR16 str[32];
+ assert(vendor);
+ assert(name);
+
SPrint(str, ELEMENTSOF(str), L"%u", i);
return efivar_set(vendor, name, str, flags);
}
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 value, UINT32 flags) {
UINT8 buf[4];
+ assert(vendor);
+ assert(name);
+
buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF);
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags) {
UINT8 buf[8];
+ assert(vendor);
+ assert(name);
+
buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF);
CHAR16 *val;
UINTN size;
+ assert(vendor);
+ assert(name);
+
err = efivar_get_raw(vendor, name, (CHAR8**)&buf, &size);
if (EFI_ERROR(err))
return err;
_cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err;
+ assert(vendor);
+ assert(name);
+ assert(i);
+
err = efivar_get(vendor, name, &val);
- if (!EFI_ERROR(err) && i)
+ if (!EFI_ERROR(err))
*i = Atoi(val);
return err;
UINTN size;
EFI_STATUS err;
+ assert(vendor);
+ assert(name);
+
err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT32))
UINTN size;
EFI_STATUS err;
+ assert(vendor);
+ assert(name);
+
err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT64))
UINTN l;
EFI_STATUS err;
+ assert(vendor);
+ assert(name);
+
l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
buf = AllocatePool(l);
if (!buf)
UINTN size;
EFI_STATUS err;
+ assert(vendor);
+ assert(name);
+ assert(ret);
+
err = efivar_get_raw(vendor, name, &b, &size);
if (!EFI_ERROR(err))
*ret = *b > 0;
VOID efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec) {
CHAR16 str[32];
+ assert(vendor);
+ assert(name);
+
if (usec == 0)
usec = time_usec();
if (usec == 0)
CHAR16 unichar;
UINTN len;
+ assert(stra);
+ assert(c);
+
if (!(stra[0] & 0x80))
len = 1;
else if ((stra[0] & 0xe0) == 0xc0)
UINTN i;
CHAR16 *str;
+ assert(stra);
+
len = strlena(stra);
str = AllocatePool((len + 1) * sizeof(CHAR16));
UINTN len;
UINTN i;
+ assert(stra);
+
len = strlena(stra);
str = AllocatePool((len + 2) * sizeof(CHAR16));
}
CHAR8 *strchra(const CHAR8 *s, CHAR8 c) {
+ assert(s);
do {
if (*s == c)
return (CHAR8*) s;
_cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err;
+ assert(name);
+ assert(ret);
+
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, (CHAR16*) name, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return err;
VOID log_error_stall(const CHAR16 *fmt, ...) {
va_list args;
+ assert(fmt);
+
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
Print(L"\n");