gummiboot/sd-boot/systemd-boot: rename galore

What used to be gummiboot, was renamed sd-boot when it was merged into
systemd. Let's try to be a bit more consistent with the rest of systemd
and rename it again as follows:

The EFI bootloader is now called 'systemd-bootx64.efi', and its sources are in
'src/boot/efi/'. The drop-in directory where bootctl will find EFI loaders
is now /usr/lib/systemd/boot/efi/.
This commit is contained in:
Tom Gundersen
2015-02-18 15:23:23 +01:00
parent 8d4efa540a
commit e7dd673d1e
18 changed files with 68 additions and 68 deletions
+17 -17
View File
@@ -215,7 +215,7 @@ fail:
return r;
}
/* search for "#### LoaderInfo: sd-boot 218 ####" string inside the binary */
/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
static int get_file_version(FILE *f, char **v) {
struct stat st;
char *buf;
@@ -351,7 +351,7 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) {
r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
if (r == 0)
fprintf(stderr, "sd-boot not installed in ESP.\n");
fprintf(stderr, "systemd-boot not installed in ESP.\n");
else if (r < 0)
return r;
@@ -710,7 +710,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
_cleanup_free_ char *v = NULL;
int r;
if (asprintf(&p, SD_BOOTLIBDIR "/%s", name) < 0) {
if (asprintf(&p, BOOTLIBDIR "/%s", name) < 0) {
fprintf(stderr, "Out of memory.\n");
return -ENOMEM;
}
@@ -722,11 +722,11 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
r = copy_file(p, q, force);
if (startswith(name, "sd-boot")) {
if (startswith(name, "systemd-boot")) {
int k;
/* Create the EFI default boot loader name (specified for removable devices) */
if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("sd-boot")) < 0) {
if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("systemd-boot")) < 0) {
fprintf(stderr, "Out of memory.\n");
return -ENOMEM;
}
@@ -756,9 +756,9 @@ static int install_binaries(const char *esp_path, bool force) {
return r;
}
d = opendir(SD_BOOTLIBDIR);
d = opendir(BOOTLIBDIR);
if (!d) {
fprintf(stderr, "Failed to open "SD_BOOTLIBDIR": %m\n");
fprintf(stderr, "Failed to open "BOOTLIBDIR": %m\n");
return -errno;
}
@@ -814,7 +814,7 @@ static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
if (n_options < 0)
return n_options;
/* find already existing sd-boot entry */
/* find already existing systemd-boot entry */
for (i = 0; i < n_options; i++)
if (same_entry(options[i], uuid, path)) {
new_id = options[i];
@@ -1036,7 +1036,7 @@ static int remove_boot_efi(const char *esp_path) {
if (r < 0)
goto finish;
if (r > 0 && strncmp(v, "sd-boot ", 10) == 0) {
if (r > 0 && strncmp(v, "systemd-boot ", 10) == 0) {
r = unlink(q);
if (r < 0) {
@@ -1089,7 +1089,7 @@ static int remove_binaries(const char *esp_path) {
char *p;
int r, q;
if (asprintf(&p, "%s/EFI/sd-boot", esp_path) < 0) {
if (asprintf(&p, "%s/EFI/systemd-boot", esp_path) < 0) {
fprintf(stderr, "Out of memory.\n");
return -ENOMEM;
}
@@ -1113,7 +1113,7 @@ static int remove_binaries(const char *esp_path) {
if (q < 0 && r == 0)
r = q;
q = rmdir_one(esp_path, "EFI/sd-boot");
q = rmdir_one(esp_path, "EFI/systemd-boot");
if (q < 0 && r == 0)
r = q;
@@ -1196,10 +1196,10 @@ static int help(void) {
" --no-variables Don't touch EFI variables\n"
"\n"
"Comands:\n"
" status Show status of installed sd-boot and EFI variables\n"
" install Install sd-boot to the ESP and EFI variables\n"
" update Update sd-boot in the ESP and EFI variables\n"
" remove Remove sd-boot from the ESP and EFI variables\n",
" status Show status of installed systemd-boot and EFI variables\n"
" install Install systemd-boot to the ESP and EFI variables\n"
" update Update systemd-boot in the ESP and EFI variables\n"
" remove Remove systemd-boot from the ESP and EFI variables\n",
program_invocation_short_name);
return 0;
@@ -1371,7 +1371,7 @@ static int bootctl_main(int argc, char*argv[]) {
if (arg_touch_variables)
r = install_variables(arg_path,
part, pstart, psize, uuid,
"/EFI/systemd/sd-boot" EFI_MACHINE_TYPE_NAME ".efi",
"/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
arg_action == ACTION_INSTALL);
break;
@@ -1379,7 +1379,7 @@ static int bootctl_main(int argc, char*argv[]) {
r = remove_binaries(arg_path);
if (arg_touch_variables) {
q = remove_variables(uuid, "/EFI/systemd/sd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
if (q < 0 && r == 0)
r = q;
}
+2
View File
@@ -0,0 +1,2 @@
/sd_boot.so
/stub.so
+2023
View File
File diff suppressed because it is too large Load Diff
+141
View File
@@ -0,0 +1,141 @@
/*-*- 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"
#include "console.h"
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)(
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
BOOLEAN ExtendedVerification;
);
typedef UINT8 EFI_KEY_TOGGLE_STATE;
typedef struct {
UINT32 KeyShiftState;
EFI_KEY_TOGGLE_STATE KeyToggleState;
} EFI_KEY_STATE;
typedef struct {
EFI_INPUT_KEY Key;
EFI_KEY_STATE KeyState;
} EFI_KEY_DATA;
typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)(
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
EFI_KEY_DATA *KeyData;
);
typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)(
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
EFI_KEY_TOGGLE_STATE *KeyToggleState;
);
typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
EFI_KEY_DATA *KeyData;
);
typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
EFI_KEY_DATA KeyData;
EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction;
VOID **NotifyHandle;
);
typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
VOID *NotificationHandle;
);
typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
EFI_INPUT_RESET_EX Reset;
EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
EFI_EVENT WaitForKeyEx;
EFI_SET_STATE SetState;
EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked;
UINTN index;
EFI_INPUT_KEY k;
EFI_STATUS err;
if (!checked) {
err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx);
if (EFI_ERROR(err))
TextInputEx = NULL;
checked = TRUE;
}
/* wait until key is pressed */
if (wait) {
if (TextInputEx)
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index);
else
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
}
if (TextInputEx) {
EFI_KEY_DATA keydata;
UINT64 keypress;
err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
if (!EFI_ERROR(err)) {
UINT32 shift = 0;
/* do not distinguish between left and right keys */
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
shift |= EFI_CONTROL_PRESSED;
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
shift |= EFI_ALT_PRESSED;
};
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
if (keypress > 0) {
*key = keypress;
return 0;
}
}
}
/* fallback for firmware which does not support SimpleTextInputExProtocol
*
* This is also called in case ReadKeyStrokeEx did not return a key, because
* some broken firmwares offer SimpleTextInputExProtocol, but never acually
* handle any key. */
err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
if (EFI_ERROR(err))
return err;
*key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
/*-*- 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 __SDBOOT_CONSOLE_H
#define __SDBOOT_CONSOLE_H
#define EFI_SHIFT_STATE_VALID 0x80000000
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define EFI_LEFT_CONTROL_PRESSED 0x00000008
#define EFI_RIGHT_ALT_PRESSED 0x00000010
#define EFI_LEFT_ALT_PRESSED 0x00000020
#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)
#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)
#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | ((scan) << 16) | (uni))
#define KEYCHAR(k) ((k) & 0xffff)
#define CHAR_CTRL(c) ((c) - 'a' + 1)
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
#endif
+389
View File
@@ -0,0 +1,389 @@
/*-*- 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>
* Copyright (C) 2013 Intel Corporation
* Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
*/
#include <efi.h>
#include <efilib.h>
#include "util.h"
#include "graphics.h"
EFI_STATUS graphics_mode(BOOLEAN on) {
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
{ 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } };
struct _EFI_CONSOLE_CONTROL_PROTOCOL;
typedef enum {
EfiConsoleControlScreenText,
EfiConsoleControlScreenGraphics,
EfiConsoleControlScreenMaxValue,
} EFI_CONSOLE_CONTROL_SCREEN_MODE;
typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE)(
struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
BOOLEAN *UgaExists,
BOOLEAN *StdInLocked
);
typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE)(
struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
);
typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN)(
struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
CHAR16 *Password
);
typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL {
EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
} EFI_CONSOLE_CONTROL_PROTOCOL;
EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
EFI_CONSOLE_CONTROL_SCREEN_MODE new;
EFI_CONSOLE_CONTROL_SCREEN_MODE current;
BOOLEAN uga_exists;
BOOLEAN stdin_locked;
EFI_STATUS err;
err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl);
if (EFI_ERROR(err)) {
/* console control protocol is nonstandard and might not exist. */
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
}
/* check current mode */
err = uefi_call_wrapper(ConsoleControl->GetMode, 4, ConsoleControl, &current, &uga_exists, &stdin_locked);
if (EFI_ERROR(err))
return err;
/* do not touch the mode */
new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText;
if (new == current)
return EFI_SUCCESS;
err = uefi_call_wrapper(ConsoleControl->SetMode, 2, ConsoleControl, new);
/* some firmware enables the cursor when switching modes */
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
return err;
}
struct bmp_file {
CHAR8 signature[2];
UINT32 size;
UINT16 reserved[2];
UINT32 offset;
} __attribute__((packed));
/* we require at least BITMAPINFOHEADER, later versions are
accepted, but their features ignored */
struct bmp_dib {
UINT32 size;
UINT32 x;
UINT32 y;
UINT16 planes;
UINT16 depth;
UINT32 compression;
UINT32 image_size;
INT32 x_pixel_meter;
INT32 y_pixel_meter;
UINT32 colors_used;
UINT32 colors_important;
} __attribute__((packed));
struct bmp_map {
UINT8 blue;
UINT8 green;
UINT8 red;
UINT8 reserved;
} __attribute__((packed));
EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib,
struct bmp_map **ret_map, UINT8 **pixmap) {
struct bmp_file *file;
struct bmp_dib *dib;
struct bmp_map *map;
UINTN row_size;
if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
return EFI_INVALID_PARAMETER;
/* check file header */
file = (struct bmp_file *)bmp;
if (file->signature[0] != 'B' || file->signature[1] != 'M')
return EFI_INVALID_PARAMETER;
if (file->size != size)
return EFI_INVALID_PARAMETER;
if (file->size < file->offset)
return EFI_INVALID_PARAMETER;
/* check device-independent bitmap */
dib = (struct bmp_dib *)(bmp + sizeof(struct bmp_file));
if (dib->size < sizeof(struct bmp_dib))
return EFI_UNSUPPORTED;
switch (dib->depth) {
case 1:
case 4:
case 8:
case 24:
if (dib->compression != 0)
return EFI_UNSUPPORTED;
break;
case 16:
case 32:
if (dib->compression != 0 && dib->compression != 3)
return EFI_UNSUPPORTED;
break;
default:
return EFI_UNSUPPORTED;
}
row_size = (((dib->depth * dib->x) + 31) / 32) * 4;
if (file->size - file->offset < dib->y * row_size)
return EFI_INVALID_PARAMETER;
if (row_size * dib->y > 64 * 1024 * 1024)
return EFI_INVALID_PARAMETER;
/* check color table */
map = (struct bmp_map *)(bmp + sizeof(struct bmp_file) + dib->size);
if (file->offset < sizeof(struct bmp_file) + dib->size)
return EFI_INVALID_PARAMETER;
if (file->offset > sizeof(struct bmp_file) + dib->size) {
UINT32 map_count;
UINTN map_size;
if (dib->colors_used)
map_count = dib->colors_used;
else {
switch (dib->depth) {
case 1:
case 4:
case 8:
map_count = 1 << dib->depth;
break;
default:
map_count = 0;
break;
}
}
map_size = file->offset - (sizeof(struct bmp_file) + dib->size);
if (map_size != sizeof(struct bmp_map) * map_count)
return EFI_INVALID_PARAMETER;
}
*ret_map = map;
*ret_dib = dib;
*pixmap = bmp + file->offset;
return EFI_SUCCESS;
}
static VOID pixel_blend(UINT32 *dst, const UINT32 source) {
UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g;
alpha = (source & 0xff);
/* convert src from RGBA to XRGB */
src = source >> 8;
/* decompose into RB and G components */
src_rb = (src & 0xff00ff);
src_g = (src & 0x00ff00);
dst_rb = (*dst & 0xff00ff);
dst_g = (*dst & 0x00ff00);
/* blend */
rb = ((((src_rb - dst_rb) * alpha + 0x800080) >> 8) + dst_rb) & 0xff00ff;
g = ((((src_g - dst_g) * alpha + 0x008000) >> 8) + dst_g) & 0x00ff00;
*dst = (rb | g);
}
EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
struct bmp_dib *dib, struct bmp_map *map,
UINT8 *pixmap) {
UINT8 *in;
UINTN y;
/* transform and copy pixels */
in = pixmap;
for (y = 0; y < dib->y; y++) {
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out;
UINTN row_size;
UINTN x;
out = &buf[(dib->y - y - 1) * dib->x];
for (x = 0; x < dib->x; x++, in++, out++) {
switch (dib->depth) {
case 1: {
UINTN i;
for (i = 0; i < 8 && x < dib->x; i++) {
out->Red = map[((*in) >> (7 - i)) & 1].red;
out->Green = map[((*in) >> (7 - i)) & 1].green;
out->Blue = map[((*in) >> (7 - i)) & 1].blue;
out++;
x++;
}
out--;
x--;
break;
}
case 4: {
UINTN i;
i = (*in) >> 4;
out->Red = map[i].red;
out->Green = map[i].green;
out->Blue = map[i].blue;
if (x < (dib->x - 1)) {
out++;
x++;
i = (*in) & 0x0f;
out->Red = map[i].red;
out->Green = map[i].green;
out->Blue = map[i].blue;
}
break;
}
case 8:
out->Red = map[*in].red;
out->Green = map[*in].green;
out->Blue = map[*in].blue;
break;
case 16: {
UINT16 i = *(UINT16 *) in;
out->Red = (i & 0x7c00) >> 7;
out->Green = (i & 0x3e0) >> 2;
out->Blue = (i & 0x1f) << 3;
in += 1;
break;
}
case 24:
out->Red = in[2];
out->Green = in[1];
out->Blue = in[0];
in += 2;
break;
case 32: {
UINT32 i = *(UINT32 *) in;
pixel_blend((UINT32 *)out, i);
in += 3;
break;
}
}
}
/* add row padding; new lines always start at 32 bit boundary */
row_size = in - pixmap;
in += ((row_size + 3) & ~3) - row_size;
}
return EFI_SUCCESS;
}
EFI_STATUS graphics_splash(EFI_FILE *root_dir, CHAR16 *path,
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background) {
EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
UINT8 *content;
INTN len;
struct bmp_dib *dib;
struct bmp_map *map;
UINT8 *pixmap;
UINT64 blt_size;
VOID *blt = NULL;
UINTN x_pos = 0;
UINTN y_pos = 0;
EFI_STATUS err;
err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
if (EFI_ERROR(err))
return err;
len = file_read(root_dir, path, 0, 0, &content);
if (len < 0)
return EFI_LOAD_ERROR;
err = bmp_parse_header(content, len, &dib, &map, &pixmap);
if (EFI_ERROR(err))
goto err;
if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2;
uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)background,
EfiBltVideoFill, 0, 0, 0, 0,
GraphicsOutput->Mode->Info->HorizontalResolution,
GraphicsOutput->Mode->Info->VerticalResolution, 0);
/* EFI buffer */
blt_size = dib->x * dib->y * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
blt = AllocatePool(blt_size);
if (!blt)
return EFI_OUT_OF_RESOURCES;
err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0,
dib->x, dib->y, 0);
if (EFI_ERROR(err))
goto err;
err = bmp_to_blt(blt, dib, map, pixmap);
if (EFI_ERROR(err))
goto err;
err = graphics_mode(TRUE);
if (EFI_ERROR(err))
goto err;
err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos,
dib->x, dib->y, 0);
err:
FreePool(blt);
FreePool(content);
return err;
}
+26
View File
@@ -0,0 +1,26 @@
/*-*- 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>
* Copyright (C) 2013 Intel Corporation
* Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
*/
#ifndef __SDBOOT_GRAPHICS_H
#define __SDBOOT_GRAPHICS_H
EFI_STATUS graphics_mode(BOOLEAN on);
EFI_STATUS graphics_splash(EFI_FILE *root_dir, CHAR16 *path,
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background);
#endif
+130
View File
@@ -0,0 +1,130 @@
/*-*- 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) 2015 Kay Sievers <kay@vrfy.org>
*/
#include <efi.h>
#include <efilib.h>
#include "util.h"
#include "linux.h"
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
struct SetupHeader {
UINT8 boot_sector[0x01f1];
UINT8 setup_secs;
UINT16 root_flags;
UINT32 sys_size;
UINT16 ram_size;
UINT16 video_mode;
UINT16 root_dev;
UINT16 signature;
UINT16 jump;
UINT32 header;
UINT16 version;
UINT16 su_switch;
UINT16 setup_seg;
UINT16 start_sys;
UINT16 kernel_ver;
UINT8 loader_id;
UINT8 load_flags;
UINT16 movesize;
UINT32 code32_start;
UINT32 ramdisk_start;
UINT32 ramdisk_len;
UINT32 bootsect_kludge;
UINT16 heap_end;
UINT8 ext_loader_ver;
UINT8 ext_loader_type;
UINT32 cmd_line_ptr;
UINT32 ramdisk_max;
UINT32 kernel_alignment;
UINT8 relocatable_kernel;
UINT8 min_alignment;
UINT16 xloadflags;
UINT32 cmdline_size;
UINT32 hardware_subarch;
UINT64 hardware_subarch_data;
UINT32 payload_offset;
UINT32 payload_length;
UINT64 setup_data;
UINT64 pref_address;
UINT32 init_size;
UINT32 handover_offset;
} __attribute__((packed));
#ifdef __x86_64__
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup);
static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
handover_f handover;
asm volatile ("cli");
handover = (handover_f)((UINTN)setup->code32_start + 512 + setup->handover_offset);
handover(image, ST, setup);
}
#else
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup) __attribute__((regparm(0)));
static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
handover_f handover;
handover = (handover_f)((UINTN)setup->code32_start + setup->handover_offset);
handover(image, ST, setup);
}
#endif
EFI_STATUS linux_exec(EFI_HANDLE *image,
CHAR8 *cmdline, UINTN cmdline_len,
UINTN linux_addr,
UINTN initrd_addr, UINTN initrd_size) {
struct SetupHeader *image_setup;
struct SetupHeader *boot_setup;
EFI_PHYSICAL_ADDRESS addr;
EFI_STATUS err;
image_setup = (struct SetupHeader *)(linux_addr);
if (image_setup->signature != 0xAA55 || image_setup->header != SETUP_MAGIC)
return EFI_LOAD_ERROR;
if (image_setup->version < 0x20b || !image_setup->relocatable_kernel)
return EFI_LOAD_ERROR;
addr = 0x3fffffff;
err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData,
EFI_SIZE_TO_PAGES(0x4000), &addr);
if (EFI_ERROR(err))
return err;
boot_setup = (struct SetupHeader *)(UINTN)addr;
ZeroMem(boot_setup, 0x4000);
CopyMem(boot_setup, image_setup, sizeof(struct SetupHeader));
boot_setup->loader_id = 0xff;
boot_setup->code32_start = (UINT32)linux_addr + (image_setup->setup_secs+1) * 512;
if (cmdline) {
addr = 0xA0000;
err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData,
EFI_SIZE_TO_PAGES(cmdline_len + 1), &addr);
if (EFI_ERROR(err))
return err;
CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len);
((CHAR8 *)addr)[cmdline_len] = 0;
boot_setup->cmd_line_ptr = (UINT32)addr;
}
boot_setup->ramdisk_start = (UINT32)initrd_addr;
boot_setup->ramdisk_len = (UINT32)initrd_size;
linux_efi_handover(image, boot_setup);
return EFI_LOAD_ERROR;
}
+24
View File
@@ -0,0 +1,24 @@
/*-*- 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) 2015 Kay Sievers <kay@vrfy.org>
*/
#ifndef __SDBOOT_kernel_H
#define __SDBOOT_kernel_H
EFI_STATUS linux_exec(EFI_HANDLE *image,
CHAR8 *cmdline, UINTN cmdline_size,
UINTN linux_addr,
UINTN initrd_addr, UINTN initrd_size);
#endif
+172
View File
@@ -0,0 +1,172 @@
/*-*- 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) 2015 Kay Sievers <kay@vrfy.org>
*/
#include <efi.h>
#include <efilib.h>
#include "util.h"
#include "pefile.h"
struct DosFileHeader {
UINT8 Magic[2];
UINT16 LastSize;
UINT16 nBlocks;
UINT16 nReloc;
UINT16 HdrSize;
UINT16 MinAlloc;
UINT16 MaxAlloc;
UINT16 ss;
UINT16 sp;
UINT16 Checksum;
UINT16 ip;
UINT16 cs;
UINT16 RelocPos;
UINT16 nOverlay;
UINT16 reserved[4];
UINT16 OEMId;
UINT16 OEMInfo;
UINT16 reserved2[10];
UINT32 ExeHeader;
} __attribute__((packed));
#define PE_HEADER_MACHINE_I386 0x014c
#define PE_HEADER_MACHINE_X64 0x8664
struct PeFileHeader {
UINT16 Machine;
UINT16 NumberOfSections;
UINT32 TimeDateStamp;
UINT32 PointerToSymbolTable;
UINT32 NumberOfSymbols;
UINT16 SizeOfOptionalHeader;
UINT16 Characteristics;
} __attribute__((packed));
struct PeSectionHeader {
UINT8 Name[8];
UINT32 VirtualSize;
UINT32 VirtualAddress;
UINT32 SizeOfRawData;
UINT32 PointerToRawData;
UINT32 PointerToRelocations;
UINT32 PointerToLinenumbers;
UINT16 NumberOfRelocations;
UINT16 NumberOfLinenumbers;
UINT32 Characteristics;
} __attribute__((packed));
EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
EFI_FILE_HANDLE handle;
struct DosFileHeader dos;
uint8_t magic[4];
struct PeFileHeader pe;
UINTN len;
UINTN i;
EFI_STATUS err;
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return err;
/* MS-DOS stub */
len = sizeof(dos);
err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos);
if (EFI_ERROR(err))
goto out;
if (len != sizeof(dos)) {
err = EFI_LOAD_ERROR;
goto out;
}
if (CompareMem(dos.Magic, "MZ", 2) != 0) {
err = EFI_LOAD_ERROR;
goto out;
}
err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader);
if (EFI_ERROR(err))
goto out;
/* PE header */
len = sizeof(magic);
err = uefi_call_wrapper(handle->Read, 3, handle, &len, &magic);
if (EFI_ERROR(err))
goto out;
if (len != sizeof(magic)) {
err = EFI_LOAD_ERROR;
goto out;
}
if (CompareMem(magic, "PE\0\0", 2) != 0) {
err = EFI_LOAD_ERROR;
goto out;
}
len = sizeof(pe);
err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe);
if (EFI_ERROR(err))
goto out;
if (len != sizeof(pe)) {
err = EFI_LOAD_ERROR;
goto out;
}
/* PE32+ Subsystem type */
if (pe.Machine != PE_HEADER_MACHINE_X64 &&
pe.Machine != PE_HEADER_MACHINE_I386) {
err = EFI_LOAD_ERROR;
goto out;
}
if (pe.NumberOfSections > 96) {
err = EFI_LOAD_ERROR;
goto out;
}
/* the sections start directly after the headers */
err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader + sizeof(magic) + sizeof(pe) + pe.SizeOfOptionalHeader);
if (EFI_ERROR(err))
goto out;
for (i = 0; i < pe.NumberOfSections; i++) {
struct PeSectionHeader sect;
UINTN j;
len = sizeof(sect);
err = uefi_call_wrapper(handle->Read, 3, handle, &len, &sect);
if (EFI_ERROR(err))
goto out;
if (len != sizeof(sect)) {
err = EFI_LOAD_ERROR;
goto out;
}
for (j = 0; sections[j]; j++) {
if (CompareMem(sect.Name, sections[j], strlena(sections[j])) != 0)
continue;
if (addrs)
addrs[j] = (UINTN)sect.VirtualAddress;
if (offsets)
offsets[j] = (UINTN)sect.PointerToRawData;
if (sizes)
sizes[j] = (UINTN)sect.VirtualSize;
}
}
out:
uefi_call_wrapper(handle->Close, 1, handle);
return err;
}
+22
View File
@@ -0,0 +1,22 @@
/*-*- 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) 2015 Kay Sievers <kay@vrfy.org>
*/
#ifndef __SDBOOT_PEFILE_H
#define __SDBOOT_PEFILE_H
EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path,
CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
#endif
+106
View File
@@ -0,0 +1,106 @@
/*-*- 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) 2015 Kay Sievers <kay@vrfy.org>
*/
#include <efi.h>
#include <efilib.h>
#include "util.h"
#include "pefile.h"
#include "linux.h"
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: stub " VERSION " ####";
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE *loaded_image;
EFI_FILE *root_dir;
CHAR16 *loaded_image_path;
CHAR8 *b;
UINTN size;
BOOLEAN secure = FALSE;
CHAR8 *sections[] = {
(UINT8 *)".cmdline",
(UINT8 *)".linux",
(UINT8 *)".initrd",
NULL
};
UINTN addrs[ELEMENTSOF(sections)-1] = {};
UINTN offs[ELEMENTSOF(sections)-1] = {};
UINTN szs[ELEMENTSOF(sections)-1] = {};
CHAR8 *cmdline = NULL;
UINTN cmdline_len;
EFI_STATUS err;
InitializeLib(image, sys_table);
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) {
Print(L"Unable to open root directory: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_LOAD_ERROR;
}
loaded_image_path = DevicePathToStr(loaded_image->FilePath);
if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
if (*b > 0)
secure = TRUE;
FreePool(b);
}
err = pefile_locate_sections(root_dir, loaded_image_path, sections, addrs, offs, szs);
if (EFI_ERROR(err)) {
Print(L"Unable to locate embedded .linux section: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (szs[0] > 0)
cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]);
cmdline_len = szs[0];
/* if we are not in secure boot mode, accept a custom command line and replace the built-in one */
if (!secure && loaded_image->LoadOptionsSize > 0) {
CHAR16 *options;
CHAR8 *line;
UINTN i;
options = (CHAR16 *)loaded_image->LoadOptions;
cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
line = AllocatePool(cmdline_len);
for (i = 0; i < cmdline_len; i++)
line[i] = options[i];
cmdline = line;
}
err = linux_exec(image, cmdline, cmdline_len,
(UINTN)loaded_image->ImageBase + addrs[1],
(UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
Print(L"Execution of embedded linux image failed: %r\n", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
+322
View File
@@ -0,0 +1,322 @@
/*-*- 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_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(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(buf);
return EFI_OUT_OF_RESOURCES;
}
*value = val;
return EFI_SUCCESS;
}
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;
}
INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content) {
EFI_FILE_HANDLE handle;
CHAR8 *buf;
UINTN buflen;
EFI_STATUS err;
UINTN len;
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return err;
if (size == 0) {
EFI_FILE_INFO *info;
info = LibFileInfo(handle);
buflen = info->FileSize+1;
FreePool(info);
} else
buflen = size;
if (off > 0) {
err = uefi_call_wrapper(handle->SetPosition, 2, handle, off);
if (EFI_ERROR(err))
return err;
}
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 {
len = err;
FreePool(buf);
}
uefi_call_wrapper(handle->Close, 1, handle);
return len;
}
+44
View File
@@ -0,0 +1,44 @@
/*-*- 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 __SDBOOT_UTIL_H
#define __SDBOOT_UTIL_H
#include <efi.h>
#include <efilib.h>
#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
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);
INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content);
#endif