mirror of https://github.com/ventoy/Ventoy.git
1. Optimization for WIMBOOT mode.
2. Add WIMBOOT for UEFI mode.
This commit is contained in:
parent
ca62128f9b
commit
93996cf7e2
|
@ -964,3 +964,20 @@ void * grub_efi_allocate_iso_buf(grub_uint64_t size)
|
|||
|
||||
return (void *)(unsigned long)address;
|
||||
}
|
||||
|
||||
void * grub_efi_allocate_chain_buf(grub_uint64_t size)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_physical_address_t address = 0;
|
||||
grub_efi_uintn_t pages = GRUB_EFI_BYTES_TO_PAGES(size);
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)(unsigned long)address;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,8 @@ static grub_uint64_t g_enumerate_start_time_ms;
|
|||
static grub_uint64_t g_enumerate_finish_time_ms;
|
||||
static int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
|
||||
|
||||
static const char *g_vtoy_winpeshl_ini = "[LaunchApps]\r\nvtoyjump.exe";
|
||||
|
||||
static const char *g_menu_class[] =
|
||||
{
|
||||
"vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
|
||||
|
@ -1020,7 +1022,7 @@ static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc
|
|||
data = (char *)grub_efi_allocate_iso_buf(totlen);
|
||||
#else
|
||||
data = (char *)grub_malloc(totlen);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ventoy_fill_os_param(file, (ventoy_os_param *)data);
|
||||
|
||||
|
@ -1048,36 +1050,52 @@ static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int ar
|
|||
char value[32];
|
||||
char *buf = NULL;
|
||||
grub_file_t file;
|
||||
enum grub_file_type type;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
if (argc != 2)
|
||||
if (argc != 3)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (grub_strcmp(args[0], "nodecompress") == 0)
|
||||
{
|
||||
type = VENTOY_FILE_TYPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GRUB_FILE_TYPE_LINUX_INITRD;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(type, "%s", args[1]);
|
||||
if (file == NULL)
|
||||
{
|
||||
debug("failed to open file <%s>\n", args[0]);
|
||||
debug("failed to open file <%s>\n", args[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
buf = (char *)grub_efi_allocate_iso_buf(file->size);
|
||||
buf = (char *)grub_efi_allocate_chain_buf(file->size);
|
||||
#else
|
||||
buf = (char *)grub_malloc(file->size);
|
||||
#endif
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, buf, file->size);
|
||||
|
||||
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
|
||||
grub_snprintf(name, sizeof(name), "%s_addr", args[2]);
|
||||
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
|
||||
grub_env_set(name, value);
|
||||
|
||||
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
|
||||
grub_snprintf(name, sizeof(name), "%s_size", args[2]);
|
||||
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
|
||||
grub_env_set(name, value);
|
||||
|
||||
|
@ -4349,6 +4367,23 @@ int ventoy_env_init(void)
|
|||
grub_env_export("ventoy_env_param");
|
||||
}
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)g_vtoy_winpeshl_ini);
|
||||
grub_env_set("vtoy_winpeshl_ini_addr", buf);
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini));
|
||||
grub_env_set("vtoy_winpeshl_ini_size", buf);
|
||||
|
||||
grub_env_export("vtoy_winpeshl_ini_addr");
|
||||
grub_env_export("vtoy_winpeshl_ini_size");
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_size);
|
||||
grub_env_set("vtoy_chain_file_size", buf);
|
||||
grub_env_export("vtoy_chain_file_size");
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_read);
|
||||
grub_env_set("vtoy_chain_file_read", buf);
|
||||
grub_env_export("vtoy_chain_file_read");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4470,6 +4505,8 @@ static cmd_para ventoy_cmds[] =
|
|||
{ "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
|
||||
{ "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
|
||||
{ "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
|
||||
{ "vt_is_pe64", ventoy_cmd_is_pe64, 0, NULL, "", "", NULL },
|
||||
{ "vt_sel_wimboot", ventoy_cmd_sel_wimboot, 0, NULL, "", "", NULL },
|
||||
|
||||
};
|
||||
|
||||
|
@ -4484,6 +4521,7 @@ int ventoy_register_all_cmd(void)
|
|||
cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
|
||||
cur->summary, cur->description, cur->parser);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -554,11 +554,13 @@ int ventoy_is_dir_exist(const char *fmt, ...);
|
|||
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_is_pe64(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_wimboot_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_sel_wimboot(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
|
@ -1011,6 +1013,8 @@ int ventoy_load_part_table(const char *diskname);
|
|||
int ventoy_env_init(void);
|
||||
int ventoy_register_all_cmd(void);
|
||||
int ventoy_unregister_all_cmd(void);
|
||||
int ventoy_chain_file_size(const char *path);
|
||||
int ventoy_chain_file_read(const char *path, int offset, int len, void *buf);
|
||||
|
||||
#define VTOY_CMD_CHECK(a) if (33554432 != g_ventoy_disk_part_size[a]) ventoy_syscall0(exit)
|
||||
|
||||
|
|
|
@ -314,6 +314,90 @@ static int ventoy_is_pe64(grub_uint8_t *buffer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_is_pe64(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int ret = 1;
|
||||
grub_file_t file;
|
||||
grub_uint8_t buf[512];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_memset(buf, 0, 512);
|
||||
grub_file_read(file, buf, 512);
|
||||
if (ventoy_is_pe64(buf))
|
||||
{
|
||||
debug("%s is PE64\n", args[0]);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("%s is PE32\n", args[0]);
|
||||
}
|
||||
grub_file_close(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_sel_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int size;
|
||||
char *buf = NULL;
|
||||
char configfile[128];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
debug("select wimboot argc:%d\n", argc);
|
||||
|
||||
buf = (char *)grub_malloc(8192);
|
||||
if (!buf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = (int)grub_snprintf(buf, 8192,
|
||||
"menuentry \"Windows Setup (32-bit)\" {\n"
|
||||
" set vtoy_wimboot_sel=32\n"
|
||||
"}\n"
|
||||
"menuentry \"Windows Setup (64-bit)\" {\n"
|
||||
" set vtoy_wimboot_sel=64\n"
|
||||
"}\n"
|
||||
);
|
||||
buf[size] = 0;
|
||||
|
||||
g_ventoy_menu_esc = 1;
|
||||
g_ventoy_suppress_esc = 1;
|
||||
|
||||
grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, size);
|
||||
grub_script_execute_sourcecode(configfile);
|
||||
|
||||
g_ventoy_menu_esc = 0;
|
||||
g_ventoy_suppress_esc = 0;
|
||||
|
||||
grub_free(buf);
|
||||
|
||||
if (g_ventoy_last_entry == 0)
|
||||
{
|
||||
debug("last entry=%d %s=32\n", g_ventoy_last_entry, args[0]);
|
||||
grub_env_set(args[0], "32");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("last entry=%d %s=64\n", g_ventoy_last_entry, args[0]);
|
||||
grub_env_set(args[0], "64");
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
wim_patch *next = NULL;
|
||||
|
@ -1810,3 +1894,29 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char
|
|||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
int ventoy_chain_file_size(const char *path)
|
||||
{
|
||||
int size;
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_file_open(path, VENTOY_FILE_TYPE);
|
||||
size = (int)(file->size);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int ventoy_chain_file_read(const char *path, int offset, int len, void *buf)
|
||||
{
|
||||
int size;
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_file_open(path, VENTOY_FILE_TYPE);
|
||||
grub_file_seek(file, offset);
|
||||
size = grub_file_read(file, buf, len);
|
||||
grub_file_close(file);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
|
|||
const grub_efi_device_path_t *dp2);
|
||||
|
||||
void * EXPORT_FUNC (grub_efi_allocate_iso_buf) (grub_uint64_t size);
|
||||
void * EXPORT_FUNC (grub_efi_allocate_chain_buf) (grub_uint64_t size);
|
||||
|
||||
|
||||
extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
|
||||
|
|
|
@ -23,7 +23,7 @@ sfs: fshelp
|
|||
reiserfs: fshelp
|
||||
part_sunpc:
|
||||
zstd:
|
||||
gfxmenu: video_colors trig bitmap_scale gfxterm font normal bitmap video
|
||||
gfxmenu: trig video_colors bitmap_scale gfxterm font normal bitmap video
|
||||
jfs:
|
||||
help: extcmd normal
|
||||
configfile: normal
|
||||
|
|
|
@ -535,6 +535,10 @@ function uefi_windows_menu_func {
|
|||
vt_windows_chain_data "${1}${chosen_path}"
|
||||
ventoy_debug_pause
|
||||
|
||||
if vt_check_mode 4; then
|
||||
vtoy_windows_wimboot_func
|
||||
fi
|
||||
|
||||
if [ -n "$vtoy_chain_mem_addr" ]; then
|
||||
ventoy_acpi_param ${vtoy_chain_mem_addr} 2048
|
||||
ventoy_cli_console
|
||||
|
@ -805,23 +809,81 @@ function uefi_iso_memdisk {
|
|||
}
|
||||
|
||||
|
||||
function legacy_windows_wimboot_func {
|
||||
set wimbootfile=(loop)/sources/boot.wim
|
||||
set wimbit=64
|
||||
function vtoy_windows_wimboot_func {
|
||||
if [ -f (loop)/x86/sources/boot.wim -a -f (loop)/x64/sources/boot.wim ]; then
|
||||
vt_sel_wimboot vtoy_wimboot_bit
|
||||
if [ "$vtoy_wimboot_bit" = "32" ]; then
|
||||
set vtoy_wimboot_prefix=(loop)/x86
|
||||
else
|
||||
set vtoy_wimboot_prefix=(loop)/x64
|
||||
fi
|
||||
else
|
||||
set vtoy_wimboot_prefix=(loop)
|
||||
if vt_is_pe64 $vtoy_wimboot_prefix/setup.exe; then
|
||||
set vtoy_wimboot_bit=64
|
||||
else
|
||||
set vtoy_wimboot_bit=32
|
||||
fi
|
||||
fi
|
||||
|
||||
vt_windows_wimboot_data
|
||||
if [ -n "${vtdebug_flag}" ]; then
|
||||
echo vtoy_wimboot_prefix=$vtoy_wimboot_prefix vtoy_wimboot_bit=$vtoy_wimboot_bit
|
||||
fi
|
||||
|
||||
linux16 $vtoy_efi_part/ventoy/wimboot quiet
|
||||
ventoy_debug_pause
|
||||
for wmfile in sources/boot.wim boot/bcd boot/boot.sdi; do
|
||||
if [ ! -f $vtoy_wimboot_prefix/$wmfile ]; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -f $vtoy_wimboot_prefix/sources/install.wim -o -f $vtoy_wimboot_prefix/sources/install.esd ]; then
|
||||
vt_windows_wimboot_data
|
||||
else
|
||||
return
|
||||
fi
|
||||
|
||||
echo Loading files...... (This may take a few minutes, please wait.)
|
||||
initrd16 newc:vtoyjump.exe:$vtoy_efi_part/ventoy/vtoyjump${wimbit}.exe \
|
||||
newc:wimboot.data:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size} \
|
||||
newc:winpeshl.ini:$vtoy_efi_part/ventoy/winpeshl.ini \
|
||||
newc:bcd:(loop)/boot/bcd \
|
||||
newc:boot.sdi:(loop)/boot/boot.sdi \
|
||||
newc:boot.wim:$wimbootfile
|
||||
boot
|
||||
if [ "$grub_platform" = "pc" ]; then
|
||||
set vt_wimkernel=wimboot.x86_64.xz
|
||||
|
||||
linux16 "$vtoy_path/$vt_wimkernel" quiet
|
||||
ventoy_debug_pause
|
||||
|
||||
echo Loading files...... (This may take a few minutes, please wait)
|
||||
initrd16 newc:vtoyjump.exe:$vtoy_path/vtoyjump${vtoy_wimboot_bit}.exe \
|
||||
newc:wimboot.data:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size} \
|
||||
newc:winpeshl.ini:mem:${vtoy_winpeshl_ini_addr}:size:${vtoy_winpeshl_ini_size} \
|
||||
newc:bcd:$vtoy_wimboot_prefix/boot/bcd \
|
||||
newc:boot.sdi:$vtoy_wimboot_prefix/boot/boot.sdi \
|
||||
newc:boot.wim:$vtoy_wimboot_prefix/sources/boot.wim
|
||||
boot
|
||||
else
|
||||
if [ "$grub_cpu" = "i386" ]; then
|
||||
set vt_wimkernel=wimboot.i386.efi.xz
|
||||
else
|
||||
set vt_wimkernel=wimboot.x86_64.xz
|
||||
fi
|
||||
|
||||
echo Loading files...... (This may take a few minutes, please wait)
|
||||
vt_load_file_to_mem "nodecompress" $vtoy_wimboot_prefix/sources/boot.wim vtoy_wimfile_mem
|
||||
if [ $? -eq 0 ]; then
|
||||
set vtoy_wimfile_path=mem:${vtoy_wimfile_mem_addr}:size:${vtoy_wimfile_mem_size}
|
||||
else
|
||||
set vtoy_wimfile_path=$vtoy_wimboot_prefix/sources/boot.wim
|
||||
fi
|
||||
|
||||
ventoy_cli_console
|
||||
chainloader "$vtoy_path/$vt_wimkernel" quiet \
|
||||
"vf=wimboot.data:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size}" \
|
||||
"vf=winpeshl.ini:mem:${vtoy_winpeshl_ini_addr}:size:${vtoy_winpeshl_ini_size}" \
|
||||
"vf=vtoyjump.exe:$vtoy_path/vtoyjump${vtoy_wimboot_bit}.exe" \
|
||||
"vf=bcd:$vtoy_wimboot_prefix/boot/bcd" \
|
||||
"vf=boot.sdi:$vtoy_wimboot_prefix/boot/boot.sdi" \
|
||||
"vf=boot.wim:$vtoy_wimfile_path" \
|
||||
pfsize=$vtoy_chain_file_size \
|
||||
pfread=$vtoy_chain_file_read
|
||||
boot
|
||||
ventoy_gui_console
|
||||
fi
|
||||
}
|
||||
|
||||
function legacy_windows_menu_func {
|
||||
|
@ -854,7 +916,7 @@ function legacy_windows_menu_func {
|
|||
ventoy_debug_pause
|
||||
|
||||
if vt_check_mode 4; then
|
||||
legacy_windows_wimboot_func
|
||||
vtoy_windows_wimboot_func
|
||||
fi
|
||||
|
||||
if [ -n "$vtoy_chain_mem_addr" ]; then
|
||||
|
|
|
@ -26,7 +26,7 @@ sfs: fshelp
|
|||
reiserfs: fshelp
|
||||
part_sunpc:
|
||||
zstd:
|
||||
gfxmenu: video_colors trig bitmap_scale gfxterm font normal bitmap video
|
||||
gfxmenu: trig video_colors bitmap_scale gfxterm font normal bitmap video
|
||||
backtrace:
|
||||
jfs:
|
||||
help: extcmd normal
|
||||
|
|
|
@ -26,7 +26,7 @@ sfs: fshelp
|
|||
reiserfs: fshelp
|
||||
part_sunpc:
|
||||
zstd:
|
||||
gfxmenu: video_colors trig bitmap_scale gfxterm font normal bitmap video
|
||||
gfxmenu: trig video_colors bitmap_scale gfxterm font normal bitmap video
|
||||
backtrace:
|
||||
jfs:
|
||||
help: extcmd normal
|
||||
|
|
Binary file not shown.
|
@ -26,7 +26,7 @@ sfs: fshelp
|
|||
reiserfs: fshelp
|
||||
part_sunpc:
|
||||
zstd:
|
||||
gfxmenu: video_colors trig bitmap_scale gfxterm font normal bitmap video
|
||||
gfxmenu: trig video_colors bitmap_scale gfxterm font normal bitmap video
|
||||
backtrace:
|
||||
jfs:
|
||||
help: extcmd normal
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,2 +0,0 @@
|
|||
[LaunchApps]
|
||||
vtoyjump.exe
|
|
@ -1118,7 +1118,7 @@ int VentoyJumpWimboot(INT argc, CHAR **argv, CHAR *LunchFile)
|
|||
g_64bit_system = TRUE;
|
||||
#endif
|
||||
|
||||
Log("VentoyJumpWimboot 64bit:%u", g_64bit_system);
|
||||
Log("VentoyJumpWimboot %dbit", g_64bit_system ? 64 : 32);
|
||||
|
||||
sprintf_s(LunchFile, MAX_PATH, "X:\\setup.exe");
|
||||
|
||||
|
@ -1187,6 +1187,7 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
|
|||
}
|
||||
|
||||
g_64bit_system = IsPe64(Buffer);
|
||||
Log("VentoyJump %dbit", g_64bit_system ? 64 : 32);
|
||||
|
||||
if (!IsPathExist(TRUE, "ventoy"))
|
||||
{
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
VTOY_PATH=$PWD/../
|
||||
|
||||
cd wimboot-2.7.3/src
|
||||
|
||||
make clean
|
||||
make -j 16
|
||||
|
||||
rm -f *.xz
|
||||
xz wimboot.x86_64
|
||||
xz wimboot.i386.efi
|
||||
|
||||
rm -f $VTOY_PATH/INSTALL/ventoy/wimboot.x86_64.xz
|
||||
rm -f $VTOY_PATH/INSTALL/ventoy/wimboot.i386.efi.xz
|
||||
cp -a wimboot.x86_64.xz $VTOY_PATH/INSTALL/ventoy/
|
||||
cp -a wimboot.i386.efi.xz $VTOY_PATH/INSTALL/ventoy/
|
||||
|
||||
make clean
|
||||
cd ../../
|
|
@ -0,0 +1,10 @@
|
|||
wimboot
|
||||
*.s
|
||||
*.o
|
||||
*.a
|
||||
*.elf
|
||||
*.map
|
||||
*.unsigned
|
||||
*.efi
|
||||
*.cab
|
||||
efireloc
|
|
@ -0,0 +1,187 @@
|
|||
VERSION := v2.7.3
|
||||
|
||||
OBJECTS := prefix.o startup.o callback.o main.o vsprintf.o string.o peloader.o
|
||||
OBJECTS += int13.o vdisk.o cpio.o stdio.o lznt1.o xca.o die.o efi.o efimain.o
|
||||
OBJECTS += efiguid.o efifile.o efipath.o efiboot.o efiblock.o cmdline.o
|
||||
OBJECTS += wimpatch.o huffman.o lzx.o wim.o wimfile.o pause.o sha1.o cookie.o
|
||||
OBJECTS += paging.o memmap.o
|
||||
|
||||
OBJECTS_i386 := $(patsubst %.o,%.i386.o,$(OBJECTS))
|
||||
OBJECTS_x86_64 := $(patsubst %.o,%.x86_64.o,$(OBJECTS))
|
||||
OBJECTS_i386_x86_64 := $(patsubst %.o,%.i386.x86_64.o,$(OBJECTS))
|
||||
|
||||
HEADERS := $(wildcard *.h)
|
||||
|
||||
HOST_CC := $(CC)
|
||||
AS := $(AS)
|
||||
ECHO := echo
|
||||
OBJCOPY := objcopy
|
||||
AR := ar
|
||||
RANLIB := ranlib
|
||||
CP := cp
|
||||
RM := rm
|
||||
GCAB := gcab
|
||||
PESIGN := pesign
|
||||
DIFF := diff
|
||||
CUT := cut
|
||||
BINUTILS_DIR := /usr
|
||||
BFD_DIR := $(BINUTILS_DIR)
|
||||
ZLIB_DIR := /usr
|
||||
|
||||
HOST_CFLAGS += -Wall -W -Werror
|
||||
|
||||
CFLAGS += -Os -ffreestanding -Wall -W -Werror -nostdinc -I. -fshort-wchar
|
||||
CFLAGS += -DVERSION="\"$(VERSION)\""
|
||||
|
||||
CFLAGS_i386 += -m32 -march=i386 -malign-double -fno-pic
|
||||
CFLAGS_x86_64 += -m64 -mno-red-zone -fpie
|
||||
|
||||
# Enable stack protection if available
|
||||
#
|
||||
SPG_TEST = $(CC) -fstack-protector-strong -mstack-protector-guard=global \
|
||||
-x c -c /dev/null -o /dev/null >/dev/null 2>&1
|
||||
SPG_FLAGS := $(shell $(SPG_TEST) && $(ECHO) '-fstack-protector-strong ' \
|
||||
'-mstack-protector-guard=global')
|
||||
CFLAGS += $(SPG_FLAGS)
|
||||
|
||||
# Inhibit unwanted debugging information
|
||||
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
|
||||
-fno-asynchronous-unwind-tables -x c -c /dev/null \
|
||||
-o /dev/null >/dev/null 2>&1
|
||||
CFI_FLAGS := $(shell $(CFI_TEST) && \
|
||||
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
|
||||
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
|
||||
WORKAROUND_CFLAGS += $(CFI_FLAGS)
|
||||
|
||||
# Add -maccumulate-outgoing-args if required by this version of gcc
|
||||
MS_ABI_TEST_CODE := extern void __attribute__ (( ms_abi )) ms_abi(); \
|
||||
void sysv_abi ( void ) { ms_abi(); }
|
||||
MS_ABI_TEST = $(ECHO) '$(MS_ABI_TEST_CODE)' | \
|
||||
$(CC) -m64 -mno-accumulate-outgoing-args -x c -c - -o /dev/null \
|
||||
>/dev/null 2>&1
|
||||
MS_ABI_FLAGS := $(shell $(MS_ABI_TEST) || $(ECHO) '-maccumulate-outgoing-args')
|
||||
WORKAROUND_CFLAGS += $(MS_ABI_FLAGS)
|
||||
|
||||
# Inhibit warnings from taking address of packed struct members
|
||||
WNAPM_TEST = $(CC) -Wno-address-of-packed-member -x c -c /dev/null \
|
||||
-o /dev/null >/dev/null 2>&1
|
||||
WNAPM_FLAGS := $(shell $(WNAPM_TEST) && \
|
||||
$(ECHO) '-Wno-address-of-packed-member')
|
||||
WORKAROUND_CFLAGS += $(WNAPM_FLAGS)
|
||||
|
||||
# Inhibit LTO
|
||||
LTO_TEST = $(CC) -fno-lto -x c -c /dev/null -o /dev/null >/dev/null 2>&1
|
||||
LTO_FLAGS := $(shell $(LTO_TEST) && $(ECHO) '-fno-lto')
|
||||
WORKAROUND_CFLAGS += $(LTO_FLAGS)
|
||||
|
||||
CFLAGS += $(WORKAROUND_CFLAGS)
|
||||
CFLAGS += $(EXTRA_CFLAGS)
|
||||
|
||||
ifneq ($(DEBUG),)
|
||||
CFLAGS += -DDEBUG=$(DEBUG)
|
||||
endif
|
||||
|
||||
CFLAGS += -include compiler.h
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Final targets
|
||||
|
||||
all : wimboot wimboot.i386 wimboot.x86_64 wimboot.cab
|
||||
|
||||
wimboot : wimboot.x86_64 Makefile
|
||||
$(CP) $< $@
|
||||
$(CP) $@ ../$@
|
||||
|
||||
wimboot.%.elf : prefix.%.o lib.%.a script.lds Makefile
|
||||
$(LD) -m elf_$* -T script.lds -o $@ -q -Map wimboot.$*.map \
|
||||
prefix.$*.o lib.$*.a
|
||||
|
||||
wimboot.%.unsigned : wimboot.%.elf efireloc Makefile
|
||||
$(OBJCOPY) -Obinary $< $@
|
||||
./efireloc $< $@
|
||||
|
||||
wimboot.%.unsigned.hash : wimboot.%.unsigned Makefile
|
||||
$(PESIGN) -h -i $< | $(CUT) -d" " -f2- > $@
|
||||
|
||||
wimboot.%.efi : wimboot.%.unsigned Makefile
|
||||
$(CP) $< $@
|
||||
|
||||
wimboot.%.efi.hash : wimboot.%.efi Makefile
|
||||
$(PESIGN) -h -i $< | $(CUT) -d" " -f2- > $@
|
||||
|
||||
wimboot.% : wimboot.%.efi wimboot.%.efi.hash wimboot.%.unsigned.hash Makefile
|
||||
$(DIFF) wimboot.$*.efi.hash wimboot.$*.unsigned.hash
|
||||
$(CP) $< $@
|
||||
|
||||
wimboot.cab : wimboot.i386.efi wimboot.x86_64.efi Makefile
|
||||
$(GCAB) -n -c $@ wimboot.i386.efi wimboot.x86_64.efi
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# i386 objects
|
||||
|
||||
%.i386.s : %.S $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CFLAGS_i386) -DASSEMBLY -Ui386 -E $< -o $@
|
||||
|
||||
%.i386.s : %.c $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CFLAGS_i386) -S $< -o $@
|
||||
|
||||
%.i386.o : %.i386.s i386.i Makefile
|
||||
$(AS) --32 i386.i $< -o $@
|
||||
|
||||
lib.i386.a : $(OBJECTS_i386) Makefile
|
||||
$(RM) -f $@
|
||||
$(AR) r $@ $(OBJECTS_i386)
|
||||
$(RANLIB) $@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# i386 objects to be linked into an x86_64 binary
|
||||
|
||||
%.i386.x86_64.raw.o : %.i386.s i386.i Makefile
|
||||
$(AS) --64 i386.i $< -o $@
|
||||
|
||||
%.i386.x86_64.o : %.i386.x86_64.raw.o Makefile
|
||||
$(OBJCOPY) --prefix-symbols=__i386_ $< $@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64 objects
|
||||
|
||||
%.x86_64.s : %.S $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CFLAGS_x86_64) -DASSEMBLY -Ui386 -E $< -o $@
|
||||
|
||||
%.x86_64.s : %.c $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CFLAGS_x86_64) -S $< -o $@
|
||||
|
||||
%.x86_64.o : %.x86_64.s x86_64.i Makefile
|
||||
$(AS) --64 x86_64.i $< -o $@
|
||||
|
||||
lib.x86_64.a : $(OBJECTS_x86_64) $(OBJECTS_i386_x86_64) Makefile
|
||||
$(RM) -f $@
|
||||
$(AR) r $@ $(OBJECTS_x86_64) $(OBJECTS_i386_x86_64)
|
||||
$(RANLIB) $@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# EFI relocator
|
||||
|
||||
EFIRELOC_CFLAGS := -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \
|
||||
-I$(ZLIB_DIR)/include -idirafter .
|
||||
EFIRELOC_LDFLAGS := -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib -L$(ZLIB_DIR)/lib \
|
||||
-lbfd -ldl -liberty -lz -Wl,--no-warn-search-mismatch
|
||||
|
||||
efireloc : efireloc.c Makefile
|
||||
$(CC) $(HOST_CFLAGS) $(EFIRELOC_CFLAGS) $< $(EFIRELOC_LDFLAGS) -o $@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Cleanup
|
||||
|
||||
clean :
|
||||
$(RM) -f *.s *.o *.a *.elf *.map
|
||||
$(RM) -f efireloc
|
||||
$(RM) -f wimboot wimboot.i386 wimboot.x86_64 ../wimboot
|
||||
$(RM) -f wimboot.i386.unsigned wimboot.x86_64.unsigned
|
||||
$(RM) -f wimboot.i386.efi wimboot.x86_64.efi wimboot.cab
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Assertions
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
|
||||
#define assert(x) do { \
|
||||
if ( DEBUG && ! (x) ) { \
|
||||
die ( "Assertion failed at %s line %d: %s\n", \
|
||||
__FILE__, __LINE__, #x ); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#endif /* _ASSERT_H */
|
|
@ -0,0 +1,318 @@
|
|||
#ifndef _BOOTAPP_H
|
||||
#define _BOOTAPP_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Boot application data structures
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** A segment:offset address */
|
||||
struct segoff {
|
||||
/** Offset */
|
||||
uint16_t offset;
|
||||
/** Segment */
|
||||
uint16_t segment;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A GUID */
|
||||
struct guid {
|
||||
/** 8 hex digits, big-endian */
|
||||
uint32_t a;
|
||||
/** 2 hex digits, big-endian */
|
||||
uint16_t b;
|
||||
/** 2 hex digits, big-endian */
|
||||
uint16_t c;
|
||||
/** 2 hex digits, big-endian */
|
||||
uint16_t d;
|
||||
/** 12 hex digits, big-endian */
|
||||
uint8_t e[6];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Real-mode callback parameters */
|
||||
struct bootapp_callback_params {
|
||||
/** Vector */
|
||||
union {
|
||||
/** Interrupt number */
|
||||
uint32_t interrupt;
|
||||
/** Segment:offset address of real-mode function */
|
||||
struct segoff function;
|
||||
} vector;
|
||||
/** %eax value */
|
||||
union {
|
||||
struct {
|
||||
uint8_t al;
|
||||
uint8_t ah;
|
||||
} __attribute__ (( packed ));
|
||||
uint16_t ax;
|
||||
uint32_t eax;
|
||||
};
|
||||
/** %ebx value */
|
||||
union {
|
||||
struct {
|
||||
uint8_t bl;
|
||||
uint8_t bh;
|
||||
} __attribute__ (( packed ));
|
||||
uint16_t bx;
|
||||
uint32_t ebx;
|
||||
};
|
||||
/** %ecx value */
|
||||
union {
|
||||
struct {
|
||||
uint8_t cl;
|
||||
uint8_t ch;
|
||||
} __attribute__ (( packed ));
|
||||
uint16_t cx;
|
||||
uint32_t ecx;
|
||||
};
|
||||
/** %edx value */
|
||||
union {
|
||||
struct {
|
||||
uint8_t dl;
|
||||
uint8_t dh;
|
||||
} __attribute__ (( packed ));
|
||||
uint16_t dx;
|
||||
uint32_t edx;
|
||||
};
|
||||
/** Placeholder (for %esp?) */
|
||||
uint32_t unused_esp;
|
||||
/** Placeholder (for %ebp?) */
|
||||
uint32_t unused_ebp;
|
||||
/** %esi value */
|
||||
union {
|
||||
uint16_t si;
|
||||
uint32_t esi;
|
||||
};
|
||||
/** %edi value */
|
||||
union {
|
||||
uint16_t di;
|
||||
uint32_t edi;
|
||||
};
|
||||
/** Placeholder (for %cs?) */
|
||||
uint32_t unused_cs;
|
||||
/** %ds value */
|
||||
uint32_t ds;
|
||||
/** Placeholder (for %ss?) */
|
||||
uint32_t unused_ss;
|
||||
/** %es value */
|
||||
uint32_t es;
|
||||
/** %fs value */
|
||||
uint32_t fs;
|
||||
/** %gs value */
|
||||
uint32_t gs;
|
||||
/** eflags value */
|
||||
uint32_t eflags;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** eflags bits */
|
||||
enum eflags {
|
||||
CF = ( 1 << 0 ),
|
||||
PF = ( 1 << 2 ),
|
||||
AF = ( 1 << 4 ),
|
||||
ZF = ( 1 << 6 ),
|
||||
SF = ( 1 << 7 ),
|
||||
OF = ( 1 << 11 ),
|
||||
};
|
||||
|
||||
/** Real-mode callback function table */
|
||||
struct bootapp_callback_functions {
|
||||
/**
|
||||
* Call an arbitrary real-mode interrupt
|
||||
*
|
||||
* @v params Parameters
|
||||
*/
|
||||
void ( * call_interrupt ) ( struct bootapp_callback_params *params );
|
||||
/**
|
||||
* Call an arbitrary real-mode function
|
||||
*
|
||||
* @v params Parameters
|
||||
*/
|
||||
void ( * call_real ) ( struct bootapp_callback_params *params );
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Real-mode callbacks */
|
||||
struct bootapp_callback {
|
||||
/** Real-mode callback function table */
|
||||
struct bootapp_callback_functions *fns;
|
||||
/** Drive number for INT13 calls */
|
||||
uint32_t drive;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Boot application descriptor */
|
||||
struct bootapp_descriptor {
|
||||
/** Signature */
|
||||
char signature[8];
|
||||
/** Version */
|
||||
uint32_t version;
|
||||
/** Total length */
|
||||
uint32_t len;
|
||||
/** COFF machine type */
|
||||
uint32_t arch;
|
||||
/** Reserved */
|
||||
uint32_t reserved_0x14;
|
||||
/** Loaded PE image base address */
|
||||
void *pe_base;
|
||||
/** Reserved */
|
||||
uint32_t reserved_0x1c;
|
||||
/** Length of loaded PE image */
|
||||
uint32_t pe_len;
|
||||
/** Offset to memory descriptor */
|
||||
uint32_t memory;
|
||||
/** Offset to boot application entry descriptor */
|
||||
uint32_t entry;
|
||||
/** Offset to ??? */
|
||||
uint32_t xxx;
|
||||
/** Offset to callback descriptor */
|
||||
uint32_t callback;
|
||||
/** Offset to pointless descriptor */
|
||||
uint32_t pointless;
|
||||
/** Reserved */
|
||||
uint32_t reserved_0x38;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** "BOOT APP" magic signature */
|
||||
#define BOOTAPP_SIGNATURE "BOOT APP"
|
||||
|
||||
/** Boot application descriptor version */
|
||||
#define BOOTAPP_VERSION 2
|
||||
|
||||
/** i386 architecture */
|
||||
#define BOOTAPP_ARCH_I386 0x014c
|
||||
|
||||
/** Memory region descriptor */
|
||||
struct bootapp_memory_region {
|
||||
/** Reserved (for struct list_head?) */
|
||||
uint8_t reserved[8];
|
||||
/** Start page address */
|
||||
uint64_t start_page;
|
||||
/** Reserved */
|
||||
uint8_t reserved_0x10[8];
|
||||
/** Number of pages */
|
||||
uint64_t num_pages;
|
||||
/** Reserved */
|
||||
uint8_t reserved_0x20[4];
|
||||
/** Flags */
|
||||
uint32_t flags;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Memory descriptor */
|
||||
struct bootapp_memory_descriptor {
|
||||
/** Version */
|
||||
uint32_t version;
|
||||
/** Length of descriptor (excluding region descriptors) */
|
||||
uint32_t len;
|
||||
/** Number of regions */
|
||||
uint32_t num_regions;
|
||||
/** Length of each region descriptor */
|
||||
uint32_t region_len;
|
||||
/** Length of reserved area at start of each region descriptor */
|
||||
uint32_t reserved_len;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Boot application memory descriptor version */
|
||||
#define BOOTAPP_MEMORY_VERSION 1
|
||||
|
||||
/** Boot application entry descriptor */
|
||||
struct bootapp_entry_descriptor {
|
||||
/** Signature */
|
||||
char signature[8];
|
||||
/** Flags */
|
||||
uint32_t flags;
|
||||
/** GUID */
|
||||
struct guid guid;
|
||||
/** Reserved */
|
||||
uint8_t reserved[16];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** ??? */
|
||||
struct bootapp_entry_wtf1_descriptor {
|
||||
/** Flags */
|
||||
uint32_t flags;
|
||||
/** Length of descriptor */
|
||||
uint32_t len;
|
||||
/** Total length of following descriptors within BTAPENT */
|
||||
uint32_t extra_len;
|
||||
/** Reserved */
|
||||
uint8_t reserved[12];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** ??? */
|
||||
struct bootapp_entry_wtf2_descriptor {
|
||||
/** GUID */
|
||||
struct guid guid;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** ??? */
|
||||
struct bootapp_entry_wtf3_descriptor {
|
||||
/** Flags */
|
||||
uint32_t flags;
|
||||
/** Reserved */
|
||||
uint32_t reserved_0x04;
|
||||
/** Length of descriptor */
|
||||
uint32_t len;
|
||||
/** Reserved */
|
||||
uint32_t reserved_0x0c;
|
||||
/** Boot partition offset (in bytes) */
|
||||
uint32_t boot_partition_offset;
|
||||
/** Reserved */
|
||||
uint8_t reserved_0x14[16];
|
||||
/** MBR signature present? */
|
||||
uint32_t xxx;
|
||||
/** MBR signature */
|
||||
uint32_t mbr_signature;
|
||||
/** Reserved */
|
||||
uint8_t reserved_0x2c[26];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** "BTAPENT" magic signature */
|
||||
#define BOOTAPP_ENTRY_SIGNATURE "BTAPENT\0"
|
||||
|
||||
/** Boot application entry flags
|
||||
*
|
||||
* pxeboot, etftboot, and fatboot all use a value of 0x21; I have no
|
||||
* idea what it means.
|
||||
*/
|
||||
#define BOOTAPP_ENTRY_FLAGS 0x21
|
||||
|
||||
/** Boot application callback descriptor */
|
||||
struct bootapp_callback_descriptor {
|
||||
/** Real-mode callbacks */
|
||||
struct bootapp_callback *callback;
|
||||
/** Reserved */
|
||||
uint32_t reserved;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Boot application pointless descriptor */
|
||||
struct bootapp_pointless_descriptor {
|
||||
/** Version */
|
||||
uint32_t version;
|
||||
/** Reserved */
|
||||
uint8_t reserved[24];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Boot application pointless descriptor version */
|
||||
#define BOOTAPP_POINTLESS_VERSION 1
|
||||
|
||||
#endif /* _BOOTAPP_H */
|
|
@ -0,0 +1,183 @@
|
|||
#ifndef _BITS_BYTESWAP_H
|
||||
#define _BITS_BYTESWAP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Byte-order swapping functions
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint16_t
|
||||
__bswap_variable_16 ( uint16_t x ) {
|
||||
__asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_16s ( uint16_t *x ) {
|
||||
__asm__ ( "rorw $8, %0" : "+m" ( *x ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint32_t
|
||||
__bswap_variable_32 ( uint32_t x ) {
|
||||
__asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_32s ( uint32_t *x ) {
|
||||
__asm__ ( "bswapl %k0" : "=r" ( *x ) : "0" ( *x ) );
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint64_t
|
||||
__bswap_variable_64 ( uint64_t x ) {
|
||||
__asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
#else /* __x86_64__ */
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint64_t
|
||||
__bswap_variable_64 ( uint64_t x ) {
|
||||
uint32_t in_high = ( x >> 32 );
|
||||
uint32_t in_low = ( x & 0xffffffffUL );
|
||||
uint32_t out_high;
|
||||
uint32_t out_low;
|
||||
|
||||
__asm__ ( "bswapl %0\n\t"
|
||||
"bswapl %1\n\t"
|
||||
"xchgl %0,%1\n\t"
|
||||
: "=r" ( out_high ), "=r" ( out_low )
|
||||
: "0" ( in_high ), "1" ( in_low ) );
|
||||
|
||||
return ( ( ( ( uint64_t ) out_high ) << 32 ) |
|
||||
( ( uint64_t ) out_low ) );
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_64s ( uint64_t *x ) {
|
||||
*x = __bswap_variable_64 ( *x );
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte-swap a 16-bit constant
|
||||
*
|
||||
* @v value Constant value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_constant_16( value ) \
|
||||
( ( ( (value) & 0x00ff ) << 8 ) | \
|
||||
( ( (value) & 0xff00 ) >> 8 ) )
|
||||
|
||||
/**
|
||||
* Byte-swap a 32-bit constant
|
||||
*
|
||||
* @v value Constant value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_constant_32( value ) \
|
||||
( ( ( (value) & 0x000000ffUL ) << 24 ) | \
|
||||
( ( (value) & 0x0000ff00UL ) << 8 ) | \
|
||||
( ( (value) & 0x00ff0000UL ) >> 8 ) | \
|
||||
( ( (value) & 0xff000000UL ) >> 24 ) )
|
||||
|
||||
/**
|
||||
* Byte-swap a 64-bit constant
|
||||
*
|
||||
* @v value Constant value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_constant_64( value ) \
|
||||
( ( ( (value) & 0x00000000000000ffULL ) << 56 ) | \
|
||||
( ( (value) & 0x000000000000ff00ULL ) << 40 ) | \
|
||||
( ( (value) & 0x0000000000ff0000ULL ) << 24 ) | \
|
||||
( ( (value) & 0x00000000ff000000ULL ) << 8 ) | \
|
||||
( ( (value) & 0x000000ff00000000ULL ) >> 8 ) | \
|
||||
( ( (value) & 0x0000ff0000000000ULL ) >> 24 ) | \
|
||||
( ( (value) & 0x00ff000000000000ULL ) >> 40 ) | \
|
||||
( ( (value) & 0xff00000000000000ULL ) >> 56 ) )
|
||||
|
||||
/**
|
||||
* Byte-swap a 16-bit value
|
||||
*
|
||||
* @v value Value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_16( value ) \
|
||||
( __builtin_constant_p (value) ? \
|
||||
( ( uint16_t ) __bswap_constant_16 ( ( uint16_t ) (value) ) ) \
|
||||
: __bswap_variable_16 (value) )
|
||||
#define bswap_16( value ) __bswap_16 (value)
|
||||
|
||||
/**
|
||||
* Byte-swap a 32-bit value
|
||||
*
|
||||
* @v value Value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_32( value ) \
|
||||
( __builtin_constant_p (value) ? \
|
||||
( ( uint32_t ) __bswap_constant_32 ( ( uint32_t ) (value) ) ) \
|
||||
: __bswap_variable_32 (value) )
|
||||
#define bswap_32( value ) __bswap_32 (value)
|
||||
|
||||
/**
|
||||
* Byte-swap a 64-bit value
|
||||
*
|
||||
* @v value Value
|
||||
* @ret swapped Byte-swapped value
|
||||
*/
|
||||
#define __bswap_64( value ) \
|
||||
( __builtin_constant_p (value) ? \
|
||||
( ( uint64_t ) __bswap_constant_64 ( ( uint64_t ) (value) ) ) \
|
||||
: __bswap_variable_64 (value) )
|
||||
#define bswap_64( value ) __bswap_64 (value)
|
||||
|
||||
#define __cpu_to_leNN( bits, value ) (value)
|
||||
#define __cpu_to_beNN( bits, value ) __bswap_ ## bits (value)
|
||||
#define __leNN_to_cpu( bits, value ) (value)
|
||||
#define __beNN_to_cpu( bits, value ) __bswap_ ## bits (value)
|
||||
#define __cpu_to_leNNs( bits, ptr ) do { } while ( 0 )
|
||||
#define __cpu_to_beNNs( bits, ptr ) __bswap_ ## bits ## s (ptr)
|
||||
#define __leNN_to_cpus( bits, ptr ) do { } while ( 0 )
|
||||
#define __beNN_to_cpus( bits, ptr ) __bswap_ ## bits ## s (ptr)
|
||||
|
||||
#define cpu_to_le16( value ) __cpu_to_leNN ( 16, value )
|
||||
#define cpu_to_le32( value ) __cpu_to_leNN ( 32, value )
|
||||
#define cpu_to_le64( value ) __cpu_to_leNN ( 64, value )
|
||||
#define cpu_to_be16( value ) __cpu_to_beNN ( 16, value )
|
||||
#define cpu_to_be32( value ) __cpu_to_beNN ( 32, value )
|
||||
#define cpu_to_be64( value ) __cpu_to_beNN ( 64, value )
|
||||
#define le16_to_cpu( value ) __leNN_to_cpu ( 16, value )
|
||||
#define le32_to_cpu( value ) __leNN_to_cpu ( 32, value )
|
||||
#define le64_to_cpu( value ) __leNN_to_cpu ( 64, value )
|
||||
#define be16_to_cpu( value ) __beNN_to_cpu ( 16, value )
|
||||
#define be32_to_cpu( value ) __beNN_to_cpu ( 32, value )
|
||||
#define be64_to_cpu( value ) __beNN_to_cpu ( 64, value )
|
||||
#define cpu_to_le16s( ptr ) __cpu_to_leNNs ( 16, ptr )
|
||||
#define cpu_to_le32s( ptr ) __cpu_to_leNNs ( 32, ptr )
|
||||
#define cpu_to_le64s( ptr ) __cpu_to_leNNs ( 64, ptr )
|
||||
#define cpu_to_be16s( ptr ) __cpu_to_beNNs ( 16, ptr )
|
||||
#define cpu_to_be32s( ptr ) __cpu_to_beNNs ( 32, ptr )
|
||||
#define cpu_to_be64s( ptr ) __cpu_to_beNNs ( 64, ptr )
|
||||
#define le16_to_cpus( ptr ) __leNN_to_cpus ( 16, ptr )
|
||||
#define le32_to_cpus( ptr ) __leNN_to_cpus ( 32, ptr )
|
||||
#define le64_to_cpus( ptr ) __leNN_to_cpus ( 64, ptr )
|
||||
#define be16_to_cpus( ptr ) __beNN_to_cpus ( 16, ptr )
|
||||
#define be32_to_cpus( ptr ) __beNN_to_cpus ( 32, ptr )
|
||||
#define be64_to_cpus( ptr ) __beNN_to_cpus ( 64, ptr )
|
||||
|
||||
#define htonll( value ) cpu_to_be64 (value)
|
||||
#define ntohll( value ) be64_to_cpu (value)
|
||||
#define htonl( value ) cpu_to_be32 (value)
|
||||
#define ntohl( value ) be32_to_cpu (value)
|
||||
#define htons( value ) cpu_to_be16 (value)
|
||||
#define ntohs( value ) be16_to_cpu (value)
|
||||
|
||||
#endif /* _BITS_BYTESWAP_H */
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Command line
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "wimboot.h"
|
||||
#include "cmdline.h"
|
||||
|
||||
/** Use raw (unpatched) BCD files */
|
||||
int cmdline_rawbcd;
|
||||
|
||||
/** Use raw (unpatched) WIM files */
|
||||
int cmdline_rawwim;
|
||||
|
||||
/** Inhibit debugging output */
|
||||
int cmdline_quiet;
|
||||
|
||||
/** Allow graphical output from bootmgr/bootmgfw */
|
||||
int cmdline_gui;
|
||||
|
||||
/** Pause before booting OS */
|
||||
int cmdline_pause;
|
||||
|
||||
/** Pause without displaying any prompt */
|
||||
int cmdline_pause_quiet;
|
||||
|
||||
/** Use linear (unpaged) memory model */
|
||||
int cmdline_linear;
|
||||
|
||||
/** WIM boot index */
|
||||
unsigned int cmdline_index;
|
||||
|
||||
int cmdline_vf_num;
|
||||
char cmdline_vf_path[MAX_VF][64];
|
||||
|
||||
file_size_pf pfventoy_file_size;
|
||||
file_read_pf pfventoy_file_read;
|
||||
|
||||
/**
|
||||
* Process command line
|
||||
*
|
||||
* @v cmdline Command line
|
||||
*/
|
||||
void process_cmdline ( char *cmdline ) {
|
||||
char *tmp = cmdline;
|
||||
char *key;
|
||||
char *value;
|
||||
char *endp;
|
||||
|
||||
/* Do nothing if we have no command line */
|
||||
if ( ( cmdline == NULL ) || ( cmdline[0] == '\0' ) )
|
||||
return;
|
||||
|
||||
/* Parse command line */
|
||||
while ( *tmp ) {
|
||||
|
||||
/* Skip whitespace */
|
||||
while ( isspace ( *tmp ) )
|
||||
tmp++;
|
||||
|
||||
/* Find value (if any) and end of this argument */
|
||||
key = tmp;
|
||||
value = NULL;
|
||||
while ( *tmp ) {
|
||||
if ( isspace ( *tmp ) ) {
|
||||
*(tmp++) = '\0';
|
||||
break;
|
||||
} else if ( *tmp == '=' ) {
|
||||
*(tmp++) = '\0';
|
||||
value = tmp;
|
||||
} else {
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process this argument */
|
||||
if ( strcmp ( key, "rawbcd" ) == 0 ) {
|
||||
cmdline_rawbcd = 1;
|
||||
} else if ( strcmp ( key, "rawwim" ) == 0 ) {
|
||||
cmdline_rawwim = 1;
|
||||
} else if ( strcmp ( key, "gui" ) == 0 ) {
|
||||
cmdline_gui = 1;
|
||||
}
|
||||
|
||||
else if ((key[0] == 'v') && (key[1] == 'f') ) {
|
||||
if (cmdline_vf_num >= MAX_VF)
|
||||
die("Too many vf\n");
|
||||
snprintf(cmdline_vf_path[cmdline_vf_num], 64, "%s", value);
|
||||
cmdline_vf_num++;
|
||||
}else if ( strcmp ( key, "pfsize" ) == 0 ) {
|
||||
pfventoy_file_size = (file_size_pf)strtoul(value, &endp, 0);
|
||||
} else if ( strcmp ( key, "pfread" ) == 0 ) {
|
||||
pfventoy_file_read = (file_read_pf)strtoul(value, &endp, 0 );
|
||||
}
|
||||
|
||||
else if ( strcmp ( key, "linear" ) == 0 ) {
|
||||
cmdline_linear = 1;
|
||||
} else if ( strcmp ( key, "quiet" ) == 0 ) {
|
||||
cmdline_quiet = 1;
|
||||
} else if ( strcmp ( key, "pause" ) == 0 ) {
|
||||
cmdline_pause = 1;
|
||||
if ( value && ( strcmp ( value, "quiet" ) == 0 ) )
|
||||
cmdline_pause_quiet = 1;
|
||||
} else if ( strcmp ( key, "index" ) == 0 ) {
|
||||
if ( ( ! value ) || ( ! value[0] ) )
|
||||
die ( "Argument \"index\" needs a value\n" );
|
||||
cmdline_index = strtoul ( value, &endp, 0 );
|
||||
if ( *endp )
|
||||
die ( "Invalid index \"%s\"\n", value );
|
||||
} else if ( strcmp ( key, "initrdfile" ) == 0 ) {
|
||||
/* Ignore this keyword to allow for use with syslinux */
|
||||
} else if ( key == cmdline ) {
|
||||
/* Ignore unknown initial arguments, which may
|
||||
* be the program name.
|
||||
*/
|
||||
} else {
|
||||
die ( "Unrecognised argument \"%s%s%s\"\n", key,
|
||||
( value ? "=" : "" ), ( value ? value : "" ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Show command line (after parsing "quiet" option) */
|
||||
DBG ( "Command line: \"%s\" vf=%d pfsize=%p pfread=%p\n",
|
||||
cmdline, cmdline_vf_num, pfventoy_file_size, pfventoy_file_read);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef _CMDLINE_H
|
||||
#define _CMDLINE_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Command line
|
||||
*
|
||||
*/
|
||||
|
||||
extern int cmdline_rawbcd;
|
||||
extern int cmdline_rawwim;
|
||||
extern int cmdline_quiet;
|
||||
extern int cmdline_gui;
|
||||
extern int cmdline_pause;
|
||||
extern int cmdline_pause_quiet;
|
||||
extern int cmdline_linear;
|
||||
extern unsigned int cmdline_index;
|
||||
extern void process_cmdline ( char *cmdline );
|
||||
|
||||
typedef int (*file_size_pf)(const char *path);
|
||||
typedef int (*file_read_pf)(const char *path, int offset, int len, void *buf);
|
||||
extern file_size_pf pfventoy_file_size;
|
||||
extern file_read_pf pfventoy_file_read;
|
||||
#define MAX_VF 16
|
||||
extern char cmdline_vf_path[MAX_VF][64];
|
||||
extern int cmdline_vf_num;
|
||||
|
||||
#endif /* _CMDLINE_H */
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _COMPILER_H
|
||||
#define _COMPILER_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Global compiler definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/* Force visibility of all symbols to "hidden", i.e. inform gcc that
|
||||
* all symbol references resolve strictly within our final binary.
|
||||
* This avoids unnecessary PLT/GOT entries on x86_64.
|
||||
*
|
||||
* This is a stronger claim than specifying "-fvisibility=hidden",
|
||||
* since it also affects symbols marked with "extern".
|
||||
*/
|
||||
#ifndef ASSEMBLY
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /* _COMPILER_H */
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Stack cookie
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
|
||||
/** Stack cookie */
|
||||
unsigned long __stack_chk_guard;
|
||||
|
||||
/**
|
||||
* Construct stack cookie value
|
||||
*
|
||||
*/
|
||||
static __attribute__ (( noinline )) unsigned long make_cookie ( void ) {
|
||||
union {
|
||||
struct {
|
||||
uint32_t eax;
|
||||
uint32_t edx;
|
||||
} __attribute__ (( packed ));
|
||||
unsigned long tsc;
|
||||
} u;
|
||||
unsigned long cookie;
|
||||
|
||||
/* We have no viable source of entropy. Use the CPU timestamp
|
||||
* counter, which will have at least some minimal randomness
|
||||
* in the low bits by the time we are invoked.
|
||||
*/
|
||||
__asm__ ( "rdtsc" : "=a" ( u.eax ), "=d" ( u.edx ) );
|
||||
cookie = u.tsc;
|
||||
|
||||
/* Ensure that the value contains a NUL byte, to act as a
|
||||
* runaway string terminator. Construct the NUL using a shift
|
||||
* rather than a mask, to avoid losing valuable entropy in the
|
||||
* lower-order bits.
|
||||
*/
|
||||
cookie <<= 8;
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise stack cookie
|
||||
*
|
||||
* This function must not itself use stack guard
|
||||
*/
|
||||
void init_cookie ( void ) {
|
||||
|
||||
/* Set stack cookie value
|
||||
*
|
||||
* This function must not itself use stack protection, since
|
||||
* the change in the stack guard value would trigger a false
|
||||
* positive.
|
||||
*
|
||||
* There is unfortunately no way to annotate a function to
|
||||
* exclude the use of stack protection. We must therefore
|
||||
* rely on correctly anticipating the compiler's decision on
|
||||
* the use of stack protection.
|
||||
*/
|
||||
__stack_chk_guard = make_cookie();
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort on stack check failure
|
||||
*
|
||||
*/
|
||||
void __stack_chk_fail ( void ) {
|
||||
|
||||
/* Abort program */
|
||||
die ( "Stack check failed\n" );
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Coverity modelling file
|
||||
*
|
||||
*/
|
||||
|
||||
typedef unsigned short wchar_t;
|
||||
typedef void mbstate_t;
|
||||
|
||||
/* Inhibit use of built-in models for functions where Coverity's
|
||||
* assumptions about the modelled function are incorrect for wimboot.
|
||||
*/
|
||||
int getchar ( void ) {
|
||||
}
|
||||
size_t wcrtomb ( char *buf, wchar_t wc, mbstate_t *ps ) {
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* CPIO archives
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "wimboot.h"
|
||||
#include "cpio.h"
|
||||
|
||||
/**
|
||||
* Align CPIO length to nearest dword
|
||||
*
|
||||
* @v len Length
|
||||
* @ret len Aligned length
|
||||
*/
|
||||
static size_t cpio_align ( size_t len ) {
|
||||
return ( ( len + 0x03 ) & ~0x03 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CPIO field value
|
||||
*
|
||||
* @v field ASCII field
|
||||
* @ret value Field value
|
||||
*/
|
||||
static unsigned long cpio_value ( const char *field ) {
|
||||
char buf[9];
|
||||
|
||||
memcpy ( buf, field, ( sizeof ( buf ) - 1 ) );
|
||||
buf[ sizeof ( buf ) - 1 ] = '\0';
|
||||
return strtoul ( buf, NULL, 16 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract files from CPIO archive
|
||||
*
|
||||
* @v data CPIO archive
|
||||
* @v len Maximum length of CPIO archive
|
||||
* @v file File handler
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int cpio_extract ( void *data, size_t len,
|
||||
int ( * file ) ( const char *name, void *data,
|
||||
size_t len ) ) {
|
||||
const struct cpio_header *cpio;
|
||||
const uint32_t *pad;
|
||||
const char *file_name;
|
||||
void *file_data;
|
||||
size_t file_name_len;
|
||||
size_t file_len;
|
||||
size_t cpio_len;
|
||||
int rc;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
/* Skip over any padding */
|
||||
while ( len >= sizeof ( *pad ) ) {
|
||||
pad = data;
|
||||
if ( *pad )
|
||||
break;
|
||||
data += sizeof ( *pad );
|
||||
len -= sizeof ( *pad );
|
||||
}
|
||||
|
||||
/* Stop if we have reached the end of the archive */
|
||||
if ( ! len )
|
||||
return 0;
|
||||
|
||||
/* Sanity check */
|
||||
if ( len < sizeof ( *cpio ) ) {
|
||||
DBG ( "Truncated CPIO header\n" );
|
||||
return -1;
|
||||
}
|
||||
cpio = data;
|
||||
|
||||
/* Check magic */
|
||||
if ( memcmp ( cpio->c_magic, CPIO_MAGIC,
|
||||
sizeof ( cpio->c_magic ) ) != 0 ) {
|
||||
DBG ( "Bad CPIO magic\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract file parameters */
|
||||
file_name = ( ( void * ) ( cpio + 1 ) );
|
||||
file_name_len = cpio_value ( cpio->c_namesize );
|
||||
file_data = ( data + cpio_align ( sizeof ( *cpio ) +
|
||||
file_name_len ) );
|
||||
file_len = cpio_value ( cpio->c_filesize );
|
||||
cpio_len = ( file_data + file_len - data );
|
||||
if ( cpio_len < len )
|
||||
cpio_len = cpio_align ( cpio_len );
|
||||
if ( cpio_len > len ) {
|
||||
DBG ( "Truncated CPIO file\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we reach the trailer, we're done */
|
||||
if ( strcmp ( file_name, CPIO_TRAILER ) == 0 )
|
||||
return 0;
|
||||
|
||||
/* Process file */
|
||||
if ( ( rc = file ( file_name, file_data, file_len ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Move to next file */
|
||||
data += cpio_len;
|
||||
len -= cpio_len;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef _CPIO_H
|
||||
#define _CPIO_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* CPIO archives
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** A CPIO archive header
|
||||
*
|
||||
* All field are hexadecimal ASCII numbers padded with '0' on the
|
||||
* left to the full width of the field.
|
||||
*/
|
||||
struct cpio_header {
|
||||
/** The string "070701" or "070702" */
|
||||
char c_magic[6];
|
||||
/** File inode number */
|
||||
char c_ino[8];
|
||||
/** File mode and permissions */
|
||||
char c_mode[8];
|
||||
/** File uid */
|
||||
char c_uid[8];
|
||||
/** File gid */
|
||||
char c_gid[8];
|
||||
/** Number of links */
|
||||
char c_nlink[8];
|
||||
/** Modification time */
|
||||
char c_mtime[8];
|
||||
/** Size of data field */
|
||||
char c_filesize[8];
|
||||
/** Major part of file device number */
|
||||
char c_maj[8];
|
||||
/** Minor part of file device number */
|
||||
char c_min[8];
|
||||
/** Major part of device node reference */
|
||||
char c_rmaj[8];
|
||||
/** Minor part of device node reference */
|
||||
char c_rmin[8];
|
||||
/** Length of filename, including final NUL */
|
||||
char c_namesize[8];
|
||||
/** Checksum of data field if c_magic is 070702, othersize zero */
|
||||
char c_chksum[8];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** CPIO magic */
|
||||
#define CPIO_MAGIC "070701"
|
||||
|
||||
/** CPIO trailer */
|
||||
#define CPIO_TRAILER "TRAILER!!!"
|
||||
|
||||
extern int cpio_extract ( void *data, size_t len,
|
||||
int ( * file ) ( const char *name, void *data,
|
||||
size_t len ) );
|
||||
|
||||
#endif /* _CPIO_H */
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Character types
|
||||
*
|
||||
*/
|
||||
|
||||
static inline int islower ( int c ) {
|
||||
return ( ( c >= 'a' ) && ( c <= 'z' ) );
|
||||
}
|
||||
|
||||
static inline int isupper ( int c ) {
|
||||
return ( ( c >= 'A' ) && ( c <= 'Z' ) );
|
||||
}
|
||||
|
||||
static inline int toupper ( int c ) {
|
||||
|
||||
if ( islower ( c ) )
|
||||
c -= ( 'a' - 'A' );
|
||||
return c;
|
||||
}
|
||||
|
||||
extern int isspace ( int c );
|
||||
|
||||
#endif /* _CTYPE_H */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Fatal errors
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "efi.h"
|
||||
|
||||
/**
|
||||
* Handle fatal errors
|
||||
*
|
||||
* @v fmt Error message format string
|
||||
* @v ... Arguments
|
||||
*/
|
||||
void die ( const char *fmt, ... ) {
|
||||
EFI_BOOT_SERVICES *bs;
|
||||
EFI_RUNTIME_SERVICES *rs;
|
||||
va_list args;
|
||||
|
||||
/* Print message */
|
||||
va_start ( args, fmt );
|
||||
vprintf ( fmt, args );
|
||||
va_end ( args );
|
||||
|
||||
/* Reboot or exit as applicable */
|
||||
if ( efi_systab ) {
|
||||
|
||||
/* Exit */
|
||||
bs = efi_systab->BootServices;
|
||||
bs->Exit ( efi_image_handle, EFI_LOAD_ERROR, 0, NULL );
|
||||
printf ( "Failed to exit\n" );
|
||||
rs = efi_systab->RuntimeServices;
|
||||
rs->ResetSystem ( EfiResetWarm, 0, 0, NULL );
|
||||
printf ( "Failed to reboot\n" );
|
||||
|
||||
} else {
|
||||
|
||||
/* Wait for keypress */
|
||||
printf ( "Press a key to reboot..." );
|
||||
getchar();
|
||||
printf ( "\n" );
|
||||
|
||||
/* Reboot system */
|
||||
reboot();
|
||||
}
|
||||
|
||||
/* Should be impossible to reach this */
|
||||
__builtin_unreachable();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI interface
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "efi.h"
|
||||
|
||||
/** EFI system table */
|
||||
EFI_SYSTEM_TABLE *efi_systab;
|
||||
|
||||
/** EFI image handle */
|
||||
EFI_HANDLE efi_image_handle;
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef _EFI_H
|
||||
#define _EFI_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/* EFIAPI definition */
|
||||
#if __x86_64__
|
||||
#define EFIAPI __attribute__ (( ms_abi ))
|
||||
#else
|
||||
#define EFIAPI
|
||||
#endif
|
||||
|
||||
/* EFI headers rudely redefine NULL */
|
||||
#undef NULL
|
||||
|
||||
#include "efi/Uefi.h"
|
||||
#include "efi/Protocol/LoadedImage.h"
|
||||
|
||||
extern EFI_SYSTEM_TABLE *efi_systab;
|
||||
extern EFI_HANDLE efi_image_handle;
|
||||
|
||||
extern EFI_GUID efi_block_io_protocol_guid;
|
||||
extern EFI_GUID efi_device_path_protocol_guid;
|
||||
extern EFI_GUID efi_graphics_output_protocol_guid;
|
||||
extern EFI_GUID efi_loaded_image_protocol_guid;
|
||||
extern EFI_GUID efi_simple_file_system_protocol_guid;
|
||||
|
||||
#endif /* _EFI_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,71 @@
|
|||
/** @file
|
||||
Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.SetInfo()
|
||||
and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information.
|
||||
This GUID is defined in UEFI specification.
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __FILE_INFO_H__
|
||||
#define __FILE_INFO_H__
|
||||
|
||||
#define EFI_FILE_INFO_ID \
|
||||
{ \
|
||||
0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The size of the EFI_FILE_INFO structure, including the Null-terminated FileName string.
|
||||
///
|
||||
UINT64 Size;
|
||||
///
|
||||
/// The size of the file in bytes.
|
||||
///
|
||||
UINT64 FileSize;
|
||||
///
|
||||
/// PhysicalSize The amount of physical space the file consumes on the file system volume.
|
||||
///
|
||||
UINT64 PhysicalSize;
|
||||
///
|
||||
/// The time the file was created.
|
||||
///
|
||||
EFI_TIME CreateTime;
|
||||
///
|
||||
/// The time when the file was last accessed.
|
||||
///
|
||||
EFI_TIME LastAccessTime;
|
||||
///
|
||||
/// The time when the file's contents were last modified.
|
||||
///
|
||||
EFI_TIME ModificationTime;
|
||||
///
|
||||
/// The attribute bits for the file.
|
||||
///
|
||||
UINT64 Attribute;
|
||||
///
|
||||
/// The Null-terminated name of the file.
|
||||
///
|
||||
CHAR16 FileName[1];
|
||||
} EFI_FILE_INFO;
|
||||
|
||||
///
|
||||
/// The FileName field of the EFI_FILE_INFO data structure is variable length.
|
||||
/// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to
|
||||
/// be the size of the data structure without the FileName field. The following macro
|
||||
/// computes this size correctly no matter how big the FileName array is declared.
|
||||
/// This is required to make the EFI_FILE_INFO data structure ANSI compilant.
|
||||
///
|
||||
#define SIZE_OF_EFI_FILE_INFO OFFSET_OF (EFI_FILE_INFO, FileName)
|
||||
|
||||
extern EFI_GUID gEfiFileInfoGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
/** @file
|
||||
Guid used to identify HII FormMap configuration method.
|
||||
|
||||
Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
@par Revision Reference:
|
||||
GUID defined in UEFI 2.2 spec.
|
||||
**/
|
||||
|
||||
#ifndef __EFI_HII_FORMMAP_GUID_H__
|
||||
#define __EFI_HII_FORMMAP_GUID_H__
|
||||
|
||||
#define EFI_HII_STANDARD_FORM_GUID \
|
||||
{ 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } }
|
||||
|
||||
extern EFI_GUID gEfiHiiStandardFormGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/** @file
|
||||
Terminal Device Path Vendor Guid.
|
||||
|
||||
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
@par Revision Reference:
|
||||
GUIDs defined in UEFI 2.0 spec.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PC_ANSI_H__
|
||||
#define __PC_ANSI_H__
|
||||
|
||||
#define EFI_PC_ANSI_GUID \
|
||||
{ \
|
||||
0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
|
||||
}
|
||||
|
||||
#define EFI_VT_100_GUID \
|
||||
{ \
|
||||
0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
|
||||
}
|
||||
|
||||
#define EFI_VT_100_PLUS_GUID \
|
||||
{ \
|
||||
0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \
|
||||
}
|
||||
|
||||
#define EFI_VT_UTF8_GUID \
|
||||
{ \
|
||||
0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \
|
||||
}
|
||||
|
||||
#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \
|
||||
{ \
|
||||
0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \
|
||||
}
|
||||
|
||||
#define EFI_SAS_DEVICE_PATH_GUID \
|
||||
{ \
|
||||
0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \
|
||||
}
|
||||
|
||||
extern EFI_GUID gEfiPcAnsiGuid;
|
||||
extern EFI_GUID gEfiVT100Guid;
|
||||
extern EFI_GUID gEfiVT100PlusGuid;
|
||||
extern EFI_GUID gEfiVTUTF8Guid;
|
||||
extern EFI_GUID gEfiUartDevicePathGuid;
|
||||
extern EFI_GUID gEfiSasDevicePathGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
/** @file
|
||||
GUID for UEFI WIN_CERTIFICATE structure.
|
||||
|
||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
@par Revision Reference:
|
||||
GUID defined in UEFI 2.0 spec.
|
||||
**/
|
||||
|
||||
#ifndef __EFI_WIN_CERTIFICATE_H__
|
||||
#define __EFI_WIN_CERTIFICATE_H__
|
||||
|
||||
//
|
||||
// _WIN_CERTIFICATE.wCertificateType
|
||||
//
|
||||
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||
#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0
|
||||
#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
|
||||
|
||||
///
|
||||
/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The length of the entire certificate,
|
||||
/// including the length of the header, in bytes.
|
||||
///
|
||||
UINT32 dwLength;
|
||||
///
|
||||
/// The revision level of the WIN_CERTIFICATE
|
||||
/// structure. The current revision level is 0x0200.
|
||||
///
|
||||
UINT16 wRevision;
|
||||
///
|
||||
/// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
|
||||
/// certificate types. The UEFI specification reserves the range of
|
||||
/// certificate type values from 0x0EF0 to 0x0EFF.
|
||||
///
|
||||
UINT16 wCertificateType;
|
||||
///
|
||||
/// The following is the actual certificate. The format of
|
||||
/// the certificate depends on wCertificateType.
|
||||
///
|
||||
/// UINT8 bCertificate[ANYSIZE_ARRAY];
|
||||
///
|
||||
} WIN_CERTIFICATE;
|
||||
|
||||
///
|
||||
/// WIN_CERTIFICATE_UEFI_GUID.CertType
|
||||
///
|
||||
#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \
|
||||
{0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }
|
||||
|
||||
///
|
||||
/// WIN_CERTIFICATE_UEFI_GUID.CertData
|
||||
///
|
||||
typedef struct {
|
||||
EFI_GUID HashType;
|
||||
UINT8 PublicKey[256];
|
||||
UINT8 Signature[256];
|
||||
} EFI_CERT_BLOCK_RSA_2048_SHA256;
|
||||
|
||||
|
||||
///
|
||||
/// Certificate which encapsulates a GUID-specific digital signature
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// This is the standard WIN_CERTIFICATE header, where
|
||||
/// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.
|
||||
///
|
||||
WIN_CERTIFICATE Hdr;
|
||||
///
|
||||
/// This is the unique id which determines the
|
||||
/// format of the CertData. .
|
||||
///
|
||||
EFI_GUID CertType;
|
||||
///
|
||||
/// The following is the certificate data. The format of
|
||||
/// the data is determined by the CertType.
|
||||
/// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
|
||||
/// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
|
||||
///
|
||||
UINT8 CertData[1];
|
||||
} WIN_CERTIFICATE_UEFI_GUID;
|
||||
|
||||
|
||||
///
|
||||
/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
|
||||
///
|
||||
/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
|
||||
/// WIN_CERTIFICATE and encapsulate the information needed to
|
||||
/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as
|
||||
/// specified in RFC2437.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// This is the standard WIN_CERTIFICATE header, where
|
||||
/// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.
|
||||
///
|
||||
WIN_CERTIFICATE Hdr;
|
||||
///
|
||||
/// This is the hashing algorithm which was performed on the
|
||||
/// UEFI executable when creating the digital signature.
|
||||
///
|
||||
EFI_GUID HashAlgorithm;
|
||||
///
|
||||
/// The following is the actual digital signature. The
|
||||
/// size of the signature is the same size as the key
|
||||
/// (1024-bit key is 128 bytes) and can be determined by
|
||||
/// subtracting the length of the other parts of this header
|
||||
/// from the total length of the certificate as found in
|
||||
/// Hdr.dwLength.
|
||||
///
|
||||
/// UINT8 Signature[];
|
||||
///
|
||||
} WIN_CERTIFICATE_EFI_PKCS1_15;
|
||||
|
||||
extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,288 @@
|
|||
/** @file
|
||||
Processor or Compiler specific defines and types for IA-32 architecture.
|
||||
|
||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PROCESSOR_BIND_H__
|
||||
#define __PROCESSOR_BIND_H__
|
||||
|
||||
///
|
||||
/// Define the processor type so other code can make processor based choices.
|
||||
///
|
||||
#define MDE_CPU_IA32
|
||||
|
||||
//
|
||||
// Make sure we are using the correct packing rules per EFI specification
|
||||
//
|
||||
#if !defined(__GNUC__)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
//
|
||||
// Disable ICC's remark #869: "Parameter" was never referenced warning.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with -Wall
|
||||
//
|
||||
#pragma warning ( disable : 869 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #1418: external function definition with no prior declaration.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 1418 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #1419: external declaration in primary source file
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 1419 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #593: "Variable" was set but never used.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 593 )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
|
||||
//
|
||||
// Disable warning that make it impossible to compile at /W4
|
||||
// This only works for Microsoft* tools
|
||||
//
|
||||
|
||||
//
|
||||
// Disabling bitfield type checking warnings.
|
||||
//
|
||||
#pragma warning ( disable : 4214 )
|
||||
|
||||
//
|
||||
// Disabling the unreferenced formal parameter warnings.
|
||||
//
|
||||
#pragma warning ( disable : 4100 )
|
||||
|
||||
//
|
||||
// Disable slightly different base types warning as CHAR8 * can not be set
|
||||
// to a constant string.
|
||||
//
|
||||
#pragma warning ( disable : 4057 )
|
||||
|
||||
//
|
||||
// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
|
||||
//
|
||||
#pragma warning ( disable : 4127 )
|
||||
|
||||
//
|
||||
// This warning is caused by functions defined but not used. For precompiled header only.
|
||||
//
|
||||
#pragma warning ( disable : 4505 )
|
||||
|
||||
//
|
||||
// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
|
||||
//
|
||||
#pragma warning ( disable : 4206 )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
|
||||
//
|
||||
// use Microsoft C complier dependent integer width types
|
||||
//
|
||||
|
||||
///
|
||||
/// 8-byte unsigned value.
|
||||
///
|
||||
typedef unsigned __int64 UINT64;
|
||||
///
|
||||
/// 8-byte signed value.
|
||||
///
|
||||
typedef __int64 INT64;
|
||||
///
|
||||
/// 4-byte unsigned value.
|
||||
///
|
||||
typedef unsigned __int32 UINT32;
|
||||
///
|
||||
/// 4-byte signed value.
|
||||
///
|
||||
typedef __int32 INT32;
|
||||
///
|
||||
/// 2-byte unsigned value.
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value.
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value.
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character.
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value.
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#else
|
||||
///
|
||||
/// 8-byte unsigned value.
|
||||
///
|
||||
typedef unsigned long long UINT64;
|
||||
///
|
||||
/// 8-byte signed value.
|
||||
///
|
||||
typedef long long INT64;
|
||||
///
|
||||
/// 4-byte unsigned value.
|
||||
///
|
||||
typedef unsigned int UINT32;
|
||||
///
|
||||
/// 4-byte signed value.
|
||||
///
|
||||
typedef int INT32;
|
||||
///
|
||||
/// 2-byte unsigned value.
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value.
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value.
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;
|
||||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
///
|
||||
typedef UINT32 UINTN;
|
||||
///
|
||||
/// Signed value of native width. (4 bytes on supported 32-bit processor instructions;
|
||||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
///
|
||||
typedef INT32 INTN;
|
||||
|
||||
//
|
||||
// Processor specific defines
|
||||
//
|
||||
|
||||
///
|
||||
/// A value of native width with the highest bit set.
|
||||
///
|
||||
#define MAX_BIT 0x80000000
|
||||
///
|
||||
/// A value of native width with the two highest bits set.
|
||||
///
|
||||
#define MAX_2_BITS 0xC0000000
|
||||
|
||||
///
|
||||
/// Maximum legal IA-32 address.
|
||||
///
|
||||
#define MAX_ADDRESS 0xFFFFFFFF
|
||||
|
||||
///
|
||||
/// Maximum legal IA-32 INTN and UINTN values.
|
||||
///
|
||||
#define MAX_INTN ((INTN)0x7FFFFFFF)
|
||||
#define MAX_UINTN ((UINTN)0xFFFFFFFF)
|
||||
|
||||
///
|
||||
/// The stack alignment required for IA-32.
|
||||
///
|
||||
#define CPU_STACK_ALIGNMENT sizeof(UINTN)
|
||||
|
||||
//
|
||||
// Modifier to ensure that all protocol member functions and EFI intrinsics
|
||||
// use the correct C calling convention. All protocol member functions and
|
||||
// EFI intrinsics are required to modify their member functions with EFIAPI.
|
||||
//
|
||||
#ifdef EFIAPI
|
||||
///
|
||||
/// If EFIAPI is already defined, then we use that definition.
|
||||
///
|
||||
#elif defined(_MSC_EXTENSIONS)
|
||||
///
|
||||
/// Microsoft* compiler specific method for EFIAPI calling convention.
|
||||
///
|
||||
#define EFIAPI __cdecl
|
||||
#elif defined(__GNUC__)
|
||||
///
|
||||
/// GCC specific method for EFIAPI calling convention.
|
||||
///
|
||||
#define EFIAPI __attribute__((cdecl))
|
||||
#else
|
||||
///
|
||||
/// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI
|
||||
/// is the standard.
|
||||
///
|
||||
#define EFIAPI
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
///
|
||||
/// For GNU assembly code, .global or .globl can declare global symbols.
|
||||
/// Define this macro to unify the usage.
|
||||
///
|
||||
#define ASM_GLOBAL .globl
|
||||
#endif
|
||||
|
||||
/**
|
||||
Return the pointer to the first instruction of a function given a function pointer.
|
||||
On IA-32 CPU architectures, these two pointer values are the same,
|
||||
so the implementation of this macro is very simple.
|
||||
|
||||
@param FunctionPointer A pointer to a function.
|
||||
|
||||
@return The pointer to the first instruction of a function given a function pointer.
|
||||
|
||||
**/
|
||||
#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,756 @@
|
|||
/** @file
|
||||
EFI image format for PE32, PE32+ and TE. Please note some data structures are
|
||||
different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
|
||||
EFI_IMAGE_NT_HEADERS64 is for PE32+.
|
||||
|
||||
This file is coded to the Visual Studio, Microsoft Portable Executable and
|
||||
Common Object File Format Specification, Revision 8.3 - February 6, 2013.
|
||||
This file also includes some definitions in PI Specification, Revision 1.0.
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PE_IMAGE_H__
|
||||
#define __PE_IMAGE_H__
|
||||
|
||||
//
|
||||
// PE32+ Subsystem type for EFI images
|
||||
//
|
||||
#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
|
||||
#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
|
||||
#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
|
||||
#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0
|
||||
|
||||
|
||||
//
|
||||
// PE32+ Machine type for EFI images
|
||||
//
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_IA64 0x0200
|
||||
#define IMAGE_FILE_MACHINE_EBC 0x0EBC
|
||||
#define IMAGE_FILE_MACHINE_X64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
|
||||
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
|
||||
|
||||
//
|
||||
// EXE file formats
|
||||
//
|
||||
#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
|
||||
#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E')
|
||||
#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E')
|
||||
#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
|
||||
|
||||
///
|
||||
/// PE images can start with an optional DOS header, so if an image is run
|
||||
/// under DOS it can print an error message.
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 e_magic; ///< Magic number.
|
||||
UINT16 e_cblp; ///< Bytes on last page of file.
|
||||
UINT16 e_cp; ///< Pages in file.
|
||||
UINT16 e_crlc; ///< Relocations.
|
||||
UINT16 e_cparhdr; ///< Size of header in paragraphs.
|
||||
UINT16 e_minalloc; ///< Minimum extra paragraphs needed.
|
||||
UINT16 e_maxalloc; ///< Maximum extra paragraphs needed.
|
||||
UINT16 e_ss; ///< Initial (relative) SS value.
|
||||
UINT16 e_sp; ///< Initial SP value.
|
||||
UINT16 e_csum; ///< Checksum.
|
||||
UINT16 e_ip; ///< Initial IP value.
|
||||
UINT16 e_cs; ///< Initial (relative) CS value.
|
||||
UINT16 e_lfarlc; ///< File address of relocation table.
|
||||
UINT16 e_ovno; ///< Overlay number.
|
||||
UINT16 e_res[4]; ///< Reserved words.
|
||||
UINT16 e_oemid; ///< OEM identifier (for e_oeminfo).
|
||||
UINT16 e_oeminfo; ///< OEM information; e_oemid specific.
|
||||
UINT16 e_res2[10]; ///< Reserved words.
|
||||
UINT32 e_lfanew; ///< File address of new exe header.
|
||||
} EFI_IMAGE_DOS_HEADER;
|
||||
|
||||
///
|
||||
/// COFF File Header (Object and Image).
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Machine;
|
||||
UINT16 NumberOfSections;
|
||||
UINT32 TimeDateStamp;
|
||||
UINT32 PointerToSymbolTable;
|
||||
UINT32 NumberOfSymbols;
|
||||
UINT16 SizeOfOptionalHeader;
|
||||
UINT16 Characteristics;
|
||||
} EFI_IMAGE_FILE_HEADER;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_FILE_HEADER.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
|
||||
|
||||
//
|
||||
// Characteristics
|
||||
//
|
||||
#define EFI_IMAGE_FILE_RELOCS_STRIPPED BIT0 ///< 0x0001 Relocation info stripped from file.
|
||||
#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references).
|
||||
#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line nunbers stripped from file.
|
||||
#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file.
|
||||
#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed.
|
||||
#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine.
|
||||
#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file.
|
||||
#define EFI_IMAGE_FILE_SYSTEM BIT12 ///< 0x1000 System File.
|
||||
#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL.
|
||||
#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed.
|
||||
|
||||
///
|
||||
/// Header Data Directories.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 VirtualAddress;
|
||||
UINT32 Size;
|
||||
} EFI_IMAGE_DATA_DIRECTORY;
|
||||
|
||||
//
|
||||
// Directory Entries
|
||||
//
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
|
||||
#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
|
||||
|
||||
#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
|
||||
|
||||
///
|
||||
/// @attention
|
||||
/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
|
||||
/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
|
||||
/// after NT additional fields.
|
||||
///
|
||||
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
|
||||
|
||||
///
|
||||
/// Optional Header Standard Fields for PE32.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Standard fields.
|
||||
///
|
||||
UINT16 Magic;
|
||||
UINT8 MajorLinkerVersion;
|
||||
UINT8 MinorLinkerVersion;
|
||||
UINT32 SizeOfCode;
|
||||
UINT32 SizeOfInitializedData;
|
||||
UINT32 SizeOfUninitializedData;
|
||||
UINT32 AddressOfEntryPoint;
|
||||
UINT32 BaseOfCode;
|
||||
UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+.
|
||||
///
|
||||
/// Optional Header Windows-Specific Fields.
|
||||
///
|
||||
UINT32 ImageBase;
|
||||
UINT32 SectionAlignment;
|
||||
UINT32 FileAlignment;
|
||||
UINT16 MajorOperatingSystemVersion;
|
||||
UINT16 MinorOperatingSystemVersion;
|
||||
UINT16 MajorImageVersion;
|
||||
UINT16 MinorImageVersion;
|
||||
UINT16 MajorSubsystemVersion;
|
||||
UINT16 MinorSubsystemVersion;
|
||||
UINT32 Win32VersionValue;
|
||||
UINT32 SizeOfImage;
|
||||
UINT32 SizeOfHeaders;
|
||||
UINT32 CheckSum;
|
||||
UINT16 Subsystem;
|
||||
UINT16 DllCharacteristics;
|
||||
UINT32 SizeOfStackReserve;
|
||||
UINT32 SizeOfStackCommit;
|
||||
UINT32 SizeOfHeapReserve;
|
||||
UINT32 SizeOfHeapCommit;
|
||||
UINT32 LoaderFlags;
|
||||
UINT32 NumberOfRvaAndSizes;
|
||||
EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
|
||||
} EFI_IMAGE_OPTIONAL_HEADER32;
|
||||
|
||||
///
|
||||
/// @attention
|
||||
/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
|
||||
/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
|
||||
/// after NT additional fields.
|
||||
///
|
||||
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
||||
|
||||
///
|
||||
/// Optional Header Standard Fields for PE32+.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Standard fields.
|
||||
///
|
||||
UINT16 Magic;
|
||||
UINT8 MajorLinkerVersion;
|
||||
UINT8 MinorLinkerVersion;
|
||||
UINT32 SizeOfCode;
|
||||
UINT32 SizeOfInitializedData;
|
||||
UINT32 SizeOfUninitializedData;
|
||||
UINT32 AddressOfEntryPoint;
|
||||
UINT32 BaseOfCode;
|
||||
///
|
||||
/// Optional Header Windows-Specific Fields.
|
||||
///
|
||||
UINT64 ImageBase;
|
||||
UINT32 SectionAlignment;
|
||||
UINT32 FileAlignment;
|
||||
UINT16 MajorOperatingSystemVersion;
|
||||
UINT16 MinorOperatingSystemVersion;
|
||||
UINT16 MajorImageVersion;
|
||||
UINT16 MinorImageVersion;
|
||||
UINT16 MajorSubsystemVersion;
|
||||
UINT16 MinorSubsystemVersion;
|
||||
UINT32 Win32VersionValue;
|
||||
UINT32 SizeOfImage;
|
||||
UINT32 SizeOfHeaders;
|
||||
UINT32 CheckSum;
|
||||
UINT16 Subsystem;
|
||||
UINT16 DllCharacteristics;
|
||||
UINT64 SizeOfStackReserve;
|
||||
UINT64 SizeOfStackCommit;
|
||||
UINT64 SizeOfHeapReserve;
|
||||
UINT64 SizeOfHeapCommit;
|
||||
UINT32 LoaderFlags;
|
||||
UINT32 NumberOfRvaAndSizes;
|
||||
EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
|
||||
} EFI_IMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
|
||||
///
|
||||
/// @attention
|
||||
/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
EFI_IMAGE_FILE_HEADER FileHeader;
|
||||
EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
|
||||
} EFI_IMAGE_NT_HEADERS32;
|
||||
|
||||
#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
|
||||
|
||||
///
|
||||
/// @attention
|
||||
/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
EFI_IMAGE_FILE_HEADER FileHeader;
|
||||
EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} EFI_IMAGE_NT_HEADERS64;
|
||||
|
||||
#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
|
||||
|
||||
//
|
||||
// Other Windows Subsystem Values
|
||||
//
|
||||
#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
|
||||
#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
|
||||
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
||||
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
||||
#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
|
||||
#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
|
||||
|
||||
///
|
||||
/// Length of ShortName.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
///
|
||||
/// Section Table. This table immediately follows the optional header.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
|
||||
union {
|
||||
UINT32 PhysicalAddress;
|
||||
UINT32 VirtualSize;
|
||||
} Misc;
|
||||
UINT32 VirtualAddress;
|
||||
UINT32 SizeOfRawData;
|
||||
UINT32 PointerToRawData;
|
||||
UINT32 PointerToRelocations;
|
||||
UINT32 PointerToLinenumbers;
|
||||
UINT16 NumberOfRelocations;
|
||||
UINT16 NumberOfLinenumbers;
|
||||
UINT32 Characteristics;
|
||||
} EFI_IMAGE_SECTION_HEADER;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_SECTION_HEADER.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
|
||||
|
||||
//
|
||||
// Section Flags Values
|
||||
//
|
||||
#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved.
|
||||
#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020
|
||||
#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040
|
||||
#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080
|
||||
|
||||
#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved.
|
||||
#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information.
|
||||
#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image.
|
||||
#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000
|
||||
|
||||
#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000
|
||||
#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000
|
||||
#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000
|
||||
#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000
|
||||
#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000
|
||||
#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000
|
||||
#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000
|
||||
|
||||
#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000
|
||||
#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000
|
||||
#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000
|
||||
#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000
|
||||
#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000
|
||||
#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000
|
||||
#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000
|
||||
|
||||
///
|
||||
/// Size of a Symbol Table Record.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_SYMBOL 18
|
||||
|
||||
//
|
||||
// Symbols have a section number of the section in which they are
|
||||
// defined. Otherwise, section numbers have the following meanings:
|
||||
//
|
||||
#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common.
|
||||
#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value.
|
||||
#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item.
|
||||
|
||||
//
|
||||
// Symbol Type (fundamental) values.
|
||||
//
|
||||
#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type.
|
||||
#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type.
|
||||
#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character.
|
||||
#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer.
|
||||
#define EFI_IMAGE_SYM_TYPE_INT 4
|
||||
#define EFI_IMAGE_SYM_TYPE_LONG 5
|
||||
#define EFI_IMAGE_SYM_TYPE_FLOAT 6
|
||||
#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
|
||||
#define EFI_IMAGE_SYM_TYPE_STRUCT 8
|
||||
#define EFI_IMAGE_SYM_TYPE_UNION 9
|
||||
#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration.
|
||||
#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration.
|
||||
#define EFI_IMAGE_SYM_TYPE_BYTE 12
|
||||
#define EFI_IMAGE_SYM_TYPE_WORD 13
|
||||
#define EFI_IMAGE_SYM_TYPE_UINT 14
|
||||
#define EFI_IMAGE_SYM_TYPE_DWORD 15
|
||||
|
||||
//
|
||||
// Symbol Type (derived) values.
|
||||
//
|
||||
#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type.
|
||||
#define EFI_IMAGE_SYM_DTYPE_POINTER 1
|
||||
#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
|
||||
#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
|
||||
|
||||
//
|
||||
// Storage classes.
|
||||
//
|
||||
#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1)
|
||||
#define EFI_IMAGE_SYM_CLASS_NULL 0
|
||||
#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
|
||||
#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
|
||||
#define EFI_IMAGE_SYM_CLASS_STATIC 3
|
||||
#define EFI_IMAGE_SYM_CLASS_REGISTER 4
|
||||
#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
|
||||
#define EFI_IMAGE_SYM_CLASS_LABEL 6
|
||||
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
|
||||
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
|
||||
#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
|
||||
#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
|
||||
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
|
||||
#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
|
||||
#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
|
||||
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
|
||||
#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
|
||||
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
|
||||
#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
|
||||
#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
|
||||
#define EFI_IMAGE_SYM_CLASS_BLOCK 100
|
||||
#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
|
||||
#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
|
||||
#define EFI_IMAGE_SYM_CLASS_FILE 103
|
||||
#define EFI_IMAGE_SYM_CLASS_SECTION 104
|
||||
#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
|
||||
|
||||
//
|
||||
// type packing constants
|
||||
//
|
||||
#define EFI_IMAGE_N_BTMASK 017
|
||||
#define EFI_IMAGE_N_TMASK 060
|
||||
#define EFI_IMAGE_N_TMASK1 0300
|
||||
#define EFI_IMAGE_N_TMASK2 0360
|
||||
#define EFI_IMAGE_N_BTSHFT 4
|
||||
#define EFI_IMAGE_N_TSHIFT 2
|
||||
|
||||
//
|
||||
// Communal selection types.
|
||||
//
|
||||
#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
|
||||
#define EFI_IMAGE_COMDAT_SELECT_ANY 2
|
||||
#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
|
||||
#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
|
||||
#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
|
||||
|
||||
//
|
||||
// the following values only be referred in PeCoff, not defined in PECOFF.
|
||||
//
|
||||
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
|
||||
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
|
||||
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
|
||||
|
||||
///
|
||||
/// Relocation format.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 VirtualAddress;
|
||||
UINT32 SymbolTableIndex;
|
||||
UINT16 Type;
|
||||
} EFI_IMAGE_RELOCATION;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_RELOCATION
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_RELOCATION 10
|
||||
|
||||
//
|
||||
// I386 relocation types.
|
||||
//
|
||||
#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary.
|
||||
#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address.
|
||||
#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address.
|
||||
#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address.
|
||||
#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included.
|
||||
#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
|
||||
#define EFI_IMAGE_REL_I386_SECTION 0x000A
|
||||
#define EFI_IMAGE_REL_I386_SECREL 0x000B
|
||||
#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address.
|
||||
|
||||
//
|
||||
// x64 processor relocation types.
|
||||
//
|
||||
#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
|
||||
#define IMAGE_REL_AMD64_ADDR64 0x0001
|
||||
#define IMAGE_REL_AMD64_ADDR32 0x0002
|
||||
#define IMAGE_REL_AMD64_ADDR32NB 0x0003
|
||||
#define IMAGE_REL_AMD64_REL32 0x0004
|
||||
#define IMAGE_REL_AMD64_REL32_1 0x0005
|
||||
#define IMAGE_REL_AMD64_REL32_2 0x0006
|
||||
#define IMAGE_REL_AMD64_REL32_3 0x0007
|
||||
#define IMAGE_REL_AMD64_REL32_4 0x0008
|
||||
#define IMAGE_REL_AMD64_REL32_5 0x0009
|
||||
#define IMAGE_REL_AMD64_SECTION 0x000A
|
||||
#define IMAGE_REL_AMD64_SECREL 0x000B
|
||||
#define IMAGE_REL_AMD64_SECREL7 0x000C
|
||||
#define IMAGE_REL_AMD64_TOKEN 0x000D
|
||||
#define IMAGE_REL_AMD64_SREL32 0x000E
|
||||
#define IMAGE_REL_AMD64_PAIR 0x000F
|
||||
#define IMAGE_REL_AMD64_SSPAN32 0x0010
|
||||
|
||||
///
|
||||
/// Based relocation format.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 VirtualAddress;
|
||||
UINT32 SizeOfBlock;
|
||||
} EFI_IMAGE_BASE_RELOCATION;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_BASE_RELOCATION.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
|
||||
|
||||
//
|
||||
// Based relocation types.
|
||||
//
|
||||
#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
|
||||
#define EFI_IMAGE_REL_BASED_HIGH 1
|
||||
#define EFI_IMAGE_REL_BASED_LOW 2
|
||||
#define EFI_IMAGE_REL_BASED_HIGHLOW 3
|
||||
#define EFI_IMAGE_REL_BASED_HIGHADJ 4
|
||||
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
|
||||
#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
|
||||
#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
|
||||
#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
|
||||
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
|
||||
#define EFI_IMAGE_REL_BASED_DIR64 10
|
||||
|
||||
///
|
||||
/// Line number format.
|
||||
///
|
||||
typedef struct {
|
||||
union {
|
||||
UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
|
||||
UINT32 VirtualAddress; ///< Virtual address of line number.
|
||||
} Type;
|
||||
UINT16 Linenumber; ///< Line number.
|
||||
} EFI_IMAGE_LINENUMBER;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_LINENUMBER.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_LINENUMBER 6
|
||||
|
||||
//
|
||||
// Archive format.
|
||||
//
|
||||
#define EFI_IMAGE_ARCHIVE_START_SIZE 8
|
||||
#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
|
||||
#define EFI_IMAGE_ARCHIVE_END "`\n"
|
||||
#define EFI_IMAGE_ARCHIVE_PAD "\n"
|
||||
#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
|
||||
#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
|
||||
|
||||
///
|
||||
/// Archive Member Headers
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Name[16]; ///< File member name - `/' terminated.
|
||||
UINT8 Date[12]; ///< File member date - decimal.
|
||||
UINT8 UserID[6]; ///< File member user id - decimal.
|
||||
UINT8 GroupID[6]; ///< File member group id - decimal.
|
||||
UINT8 Mode[8]; ///< File member mode - octal.
|
||||
UINT8 Size[10]; ///< File member size - decimal.
|
||||
UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
|
||||
} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
|
||||
|
||||
///
|
||||
/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
|
||||
///
|
||||
#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
|
||||
|
||||
|
||||
//
|
||||
// DLL Support
|
||||
//
|
||||
|
||||
///
|
||||
/// Export Directory Table.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Characteristics;
|
||||
UINT32 TimeDateStamp;
|
||||
UINT16 MajorVersion;
|
||||
UINT16 MinorVersion;
|
||||
UINT32 Name;
|
||||
UINT32 Base;
|
||||
UINT32 NumberOfFunctions;
|
||||
UINT32 NumberOfNames;
|
||||
UINT32 AddressOfFunctions;
|
||||
UINT32 AddressOfNames;
|
||||
UINT32 AddressOfNameOrdinals;
|
||||
} EFI_IMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
///
|
||||
/// Hint/Name Table.
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Hint;
|
||||
UINT8 Name[1];
|
||||
} EFI_IMAGE_IMPORT_BY_NAME;
|
||||
|
||||
///
|
||||
/// Import Address Table RVA (Thunk Table).
|
||||
///
|
||||
typedef struct {
|
||||
union {
|
||||
UINT32 Function;
|
||||
UINT32 Ordinal;
|
||||
EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
|
||||
} u1;
|
||||
} EFI_IMAGE_THUNK_DATA;
|
||||
|
||||
#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32.
|
||||
#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
|
||||
#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
|
||||
|
||||
///
|
||||
/// Import Directory Table
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Characteristics;
|
||||
UINT32 TimeDateStamp;
|
||||
UINT32 ForwarderChain;
|
||||
UINT32 Name;
|
||||
EFI_IMAGE_THUNK_DATA *FirstThunk;
|
||||
} EFI_IMAGE_IMPORT_DESCRIPTOR;
|
||||
|
||||
|
||||
///
|
||||
/// Debug Directory Format.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Characteristics;
|
||||
UINT32 TimeDateStamp;
|
||||
UINT16 MajorVersion;
|
||||
UINT16 MinorVersion;
|
||||
UINT32 Type;
|
||||
UINT32 SizeOfData;
|
||||
UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base.
|
||||
UINT32 FileOffset; ///< The file pointer to the debug data.
|
||||
} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
|
||||
|
||||
#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
|
||||
|
||||
///
|
||||
/// Debug Data Structure defined in Microsoft C++.
|
||||
///
|
||||
#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0')
|
||||
typedef struct {
|
||||
UINT32 Signature; ///< "NB10"
|
||||
UINT32 Unknown;
|
||||
UINT32 Unknown2;
|
||||
UINT32 Unknown3;
|
||||
//
|
||||
// Filename of .PDB goes here
|
||||
//
|
||||
} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
|
||||
|
||||
///
|
||||
/// Debug Data Structure defined in Microsoft C++.
|
||||
///
|
||||
#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S')
|
||||
typedef struct {
|
||||
UINT32 Signature; ///< "RSDS".
|
||||
UINT32 Unknown;
|
||||
UINT32 Unknown2;
|
||||
UINT32 Unknown3;
|
||||
UINT32 Unknown4;
|
||||
UINT32 Unknown5;
|
||||
//
|
||||
// Filename of .PDB goes here
|
||||
//
|
||||
} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
|
||||
|
||||
|
||||
///
|
||||
/// Debug Data Structure defined by Apple Mach-O to Coff utility.
|
||||
///
|
||||
#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C')
|
||||
typedef struct {
|
||||
UINT32 Signature; ///< "MTOC".
|
||||
GUID MachOUuid;
|
||||
//
|
||||
// Filename of .DLL (Mach-O with debug info) goes here
|
||||
//
|
||||
} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
|
||||
|
||||
///
|
||||
/// Resource format.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Characteristics;
|
||||
UINT32 TimeDateStamp;
|
||||
UINT16 MajorVersion;
|
||||
UINT16 MinorVersion;
|
||||
UINT16 NumberOfNamedEntries;
|
||||
UINT16 NumberOfIdEntries;
|
||||
//
|
||||
// Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
|
||||
//
|
||||
} EFI_IMAGE_RESOURCE_DIRECTORY;
|
||||
|
||||
///
|
||||
/// Resource directory entry format.
|
||||
///
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
UINT32 NameOffset:31;
|
||||
UINT32 NameIsString:1;
|
||||
} s;
|
||||
UINT32 Id;
|
||||
} u1;
|
||||
union {
|
||||
UINT32 OffsetToData;
|
||||
struct {
|
||||
UINT32 OffsetToDirectory:31;
|
||||
UINT32 DataIsDirectory:1;
|
||||
} s;
|
||||
} u2;
|
||||
} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
|
||||
|
||||
///
|
||||
/// Resource directory entry for string.
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Length;
|
||||
CHAR16 String[1];
|
||||
} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
|
||||
|
||||
///
|
||||
/// Resource directory entry for data array.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 OffsetToData;
|
||||
UINT32 Size;
|
||||
UINT32 CodePage;
|
||||
UINT32 Reserved;
|
||||
} EFI_IMAGE_RESOURCE_DATA_ENTRY;
|
||||
|
||||
///
|
||||
/// Header format for TE images, defined in the PI Specification, 1.0.
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Signature; ///< The signature for TE format = "VZ".
|
||||
UINT16 Machine; ///< From the original file header.
|
||||
UINT8 NumberOfSections; ///< From the original file header.
|
||||
UINT8 Subsystem; ///< From original optional header.
|
||||
UINT16 StrippedSize; ///< Number of bytes we removed from the header.
|
||||
UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header.
|
||||
UINT32 BaseOfCode; ///< From original image -- required for ITP debug.
|
||||
UINT64 ImageBase; ///< From original file header.
|
||||
EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory.
|
||||
} EFI_TE_IMAGE_HEADER;
|
||||
|
||||
|
||||
#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z')
|
||||
|
||||
//
|
||||
// Data directory indexes in our TE image header
|
||||
//
|
||||
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
|
||||
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
|
||||
|
||||
|
||||
///
|
||||
/// Union of PE32, PE32+, and TE headers.
|
||||
///
|
||||
typedef union {
|
||||
EFI_IMAGE_NT_HEADERS32 Pe32;
|
||||
EFI_IMAGE_NT_HEADERS64 Pe32Plus;
|
||||
EFI_TE_IMAGE_HEADER Te;
|
||||
} EFI_IMAGE_OPTIONAL_HEADER_UNION;
|
||||
|
||||
typedef union {
|
||||
EFI_IMAGE_NT_HEADERS32 *Pe32;
|
||||
EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
|
||||
EFI_TE_IMAGE_HEADER *Te;
|
||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
|
||||
} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _WIMBOOT_EFI_PROCESSOR_BIND_H
|
||||
#define _WIMBOOT_EFI_PROCESSOR_BIND_H
|
||||
|
||||
/*
|
||||
* EFI header files rely on having the CPU architecture directory
|
||||
* present in the search path in order to pick up ProcessorBind.h. We
|
||||
* use this header file as a quick indirection layer.
|
||||
*
|
||||
*/
|
||||
|
||||
#if __i386__
|
||||
#include <efi/Ia32/ProcessorBind.h>
|
||||
#endif
|
||||
|
||||
#if __x86_64__
|
||||
#include <efi/X64/ProcessorBind.h>
|
||||
#endif
|
||||
|
||||
#endif /* _WIMBOOT_EFI_PROCESSOR_BIND_H */
|
|
@ -0,0 +1,241 @@
|
|||
/** @file
|
||||
Block IO protocol as defined in the UEFI 2.0 specification.
|
||||
|
||||
The Block IO protocol is used to abstract block devices like hard drives,
|
||||
DVD-ROMs and floppy drives.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __BLOCK_IO_H__
|
||||
#define __BLOCK_IO_H__
|
||||
|
||||
#define EFI_BLOCK_IO_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL;
|
||||
|
||||
///
|
||||
/// Protocol GUID name defined in EFI1.1.
|
||||
///
|
||||
#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID
|
||||
|
||||
///
|
||||
/// Protocol defined in EFI1.1.
|
||||
///
|
||||
typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO;
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_RESET)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_READ)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the write request is for.
|
||||
@param Lba The starting logical block address to be written. The caller is
|
||||
responsible for writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_WRITE)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writting back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_FLUSH)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Block IO read only mode data and updated only via members of BlockIO
|
||||
**/
|
||||
typedef struct {
|
||||
///
|
||||
/// The curent media Id. If the media changes, this value is changed.
|
||||
///
|
||||
UINT32 MediaId;
|
||||
|
||||
///
|
||||
/// TRUE if the media is removable; otherwise, FALSE.
|
||||
///
|
||||
BOOLEAN RemovableMedia;
|
||||
|
||||
///
|
||||
/// TRUE if there is a media currently present in the device;
|
||||
/// othersise, FALSE. THis field shows the media present status
|
||||
/// as of the most recent ReadBlocks() or WriteBlocks() call.
|
||||
///
|
||||
BOOLEAN MediaPresent;
|
||||
|
||||
///
|
||||
/// TRUE if LBA 0 is the first block of a partition; otherwise
|
||||
/// FALSE. For media with only one partition this would be TRUE.
|
||||
///
|
||||
BOOLEAN LogicalPartition;
|
||||
|
||||
///
|
||||
/// TRUE if the media is marked read-only otherwise, FALSE.
|
||||
/// This field shows the read-only status as of the most recent WriteBlocks () call.
|
||||
///
|
||||
BOOLEAN ReadOnly;
|
||||
|
||||
///
|
||||
/// TRUE if the WriteBlock () function caches write data.
|
||||
///
|
||||
BOOLEAN WriteCaching;
|
||||
|
||||
///
|
||||
/// The intrinsic block size of the device. If the media changes, then
|
||||
/// this field is updated.
|
||||
///
|
||||
UINT32 BlockSize;
|
||||
|
||||
///
|
||||
/// Supplies the alignment requirement for any buffer to read or write block(s).
|
||||
///
|
||||
UINT32 IoAlign;
|
||||
|
||||
///
|
||||
/// The last logical block address on the device.
|
||||
/// If the media changes, then this field is updated.
|
||||
///
|
||||
EFI_LBA LastBlock;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to
|
||||
/// a physical block boundary.
|
||||
///
|
||||
EFI_LBA LowestAlignedLba;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks
|
||||
/// per physical block.
|
||||
///
|
||||
UINT32 LogicalBlocksPerPhysicalBlock;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length
|
||||
/// granularity as a number of logical blocks.
|
||||
///
|
||||
UINT32 OptimalTransferLengthGranularity;
|
||||
} EFI_BLOCK_IO_MEDIA;
|
||||
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
|
||||
|
||||
///
|
||||
/// Revision defined in EFI1.1.
|
||||
///
|
||||
#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION
|
||||
|
||||
///
|
||||
/// This protocol provides control over block devices.
|
||||
///
|
||||
struct _EFI_BLOCK_IO_PROTOCOL {
|
||||
///
|
||||
/// The revision to which the block IO interface adheres. All future
|
||||
/// revisions must be backwards compatible. If a future version is not
|
||||
/// back wards compatible, it is not the same GUID.
|
||||
///
|
||||
UINT64 Revision;
|
||||
///
|
||||
/// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
|
||||
///
|
||||
EFI_BLOCK_IO_MEDIA *Media;
|
||||
|
||||
EFI_BLOCK_RESET Reset;
|
||||
EFI_BLOCK_READ ReadBlocks;
|
||||
EFI_BLOCK_WRITE WriteBlocks;
|
||||
EFI_BLOCK_FLUSH FlushBlocks;
|
||||
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiBlockIoProtocolGuid;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,276 @@
|
|||
/** @file
|
||||
Graphics Output Protocol from the UEFI 2.0 specification.
|
||||
|
||||
Abstraction of a very simple graphics device.
|
||||
|
||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __GRAPHICS_OUTPUT_H__
|
||||
#define __GRAPHICS_OUTPUT_H__
|
||||
|
||||
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||
|
||||
typedef struct {
|
||||
UINT32 RedMask;
|
||||
UINT32 GreenMask;
|
||||
UINT32 BlueMask;
|
||||
UINT32 ReservedMask;
|
||||
} EFI_PIXEL_BITMASK;
|
||||
|
||||
typedef enum {
|
||||
///
|
||||
/// A pixel is 32-bits and byte zero represents red, byte one represents green,
|
||||
/// byte two represents blue, and byte three is reserved. This is the definition
|
||||
/// for the physical frame buffer. The byte values for the red, green, and blue
|
||||
/// components represent the color intensity. This color intensity value range
|
||||
/// from a minimum intensity of 0 to maximum intensity of 255.
|
||||
///
|
||||
PixelRedGreenBlueReserved8BitPerColor,
|
||||
///
|
||||
/// A pixel is 32-bits and byte zero represents blue, byte one represents green,
|
||||
/// byte two represents red, and byte three is reserved. This is the definition
|
||||
/// for the physical frame buffer. The byte values for the red, green, and blue
|
||||
/// components represent the color intensity. This color intensity value range
|
||||
/// from a minimum intensity of 0 to maximum intensity of 255.
|
||||
///
|
||||
PixelBlueGreenRedReserved8BitPerColor,
|
||||
///
|
||||
/// The Pixel definition of the physical frame buffer.
|
||||
///
|
||||
PixelBitMask,
|
||||
///
|
||||
/// This mode does not support a physical frame buffer.
|
||||
///
|
||||
PixelBltOnly,
|
||||
///
|
||||
/// Valid EFI_GRAPHICS_PIXEL_FORMAT enum values are less than this value.
|
||||
///
|
||||
PixelFormatMax
|
||||
} EFI_GRAPHICS_PIXEL_FORMAT;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The version of this data structure. A value of zero represents the
|
||||
/// EFI_GRAPHICS_OUTPUT_MODE_INFORMATION structure as defined in this specification.
|
||||
///
|
||||
UINT32 Version;
|
||||
///
|
||||
/// The size of video screen in pixels in the X dimension.
|
||||
///
|
||||
UINT32 HorizontalResolution;
|
||||
///
|
||||
/// The size of video screen in pixels in the Y dimension.
|
||||
///
|
||||
UINT32 VerticalResolution;
|
||||
///
|
||||
/// Enumeration that defines the physical format of the pixel. A value of PixelBltOnly
|
||||
/// implies that a linear frame buffer is not available for this mode.
|
||||
///
|
||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
||||
///
|
||||
/// This bit-mask is only valid if PixelFormat is set to PixelPixelBitMask.
|
||||
/// A bit being set defines what bits are used for what purpose such as Red, Green, Blue, or Reserved.
|
||||
///
|
||||
EFI_PIXEL_BITMASK PixelInformation;
|
||||
///
|
||||
/// Defines the number of pixel elements per video memory line.
|
||||
///
|
||||
UINT32 PixelsPerScanLine;
|
||||
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
||||
|
||||
/**
|
||||
Returns information for an available graphics mode that the graphics device
|
||||
and the set of active video output devices supports.
|
||||
|
||||
@param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
|
||||
@param ModeNumber The mode number to return information on.
|
||||
@param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
|
||||
@param Info A pointer to callee allocated buffer that returns information about ModeNumber.
|
||||
|
||||
@retval EFI_SUCCESS Valid mode information was returned.
|
||||
@retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
|
||||
@retval EFI_INVALID_PARAMETER ModeNumber is not valid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber,
|
||||
OUT UINTN *SizeOfInfo,
|
||||
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
||||
);
|
||||
|
||||
/**
|
||||
Set the video device into the specified mode and clears the visible portions of
|
||||
the output display to black.
|
||||
|
||||
@param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
|
||||
@param ModeNumber Abstraction that defines the current video mode.
|
||||
|
||||
@retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
UINT8 Blue;
|
||||
UINT8 Green;
|
||||
UINT8 Red;
|
||||
UINT8 Reserved;
|
||||
} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
|
||||
|
||||
typedef union {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel;
|
||||
UINT32 Raw;
|
||||
} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION;
|
||||
|
||||
///
|
||||
/// actions for BltOperations
|
||||
///
|
||||
typedef enum {
|
||||
///
|
||||
/// Write data from the BltBuffer pixel (0, 0)
|
||||
/// directly to every pixel of the video display rectangle
|
||||
/// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
|
||||
/// Only one pixel will be used from the BltBuffer. Delta is NOT used.
|
||||
///
|
||||
EfiBltVideoFill,
|
||||
|
||||
///
|
||||
/// Read data from the video display rectangle
|
||||
/// (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
|
||||
/// the BltBuffer rectangle (DestinationX, DestinationY )
|
||||
/// (DestinationX + Width, DestinationY + Height). If DestinationX or
|
||||
/// DestinationY is not zero then Delta must be set to the length in bytes
|
||||
/// of a row in the BltBuffer.
|
||||
///
|
||||
EfiBltVideoToBltBuffer,
|
||||
|
||||
///
|
||||
/// Write data from the BltBuffer rectangle
|
||||
/// (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
|
||||
/// video display rectangle (DestinationX, DestinationY)
|
||||
/// (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
|
||||
/// not zero then Delta must be set to the length in bytes of a row in the
|
||||
/// BltBuffer.
|
||||
///
|
||||
EfiBltBufferToVideo,
|
||||
|
||||
///
|
||||
/// Copy from the video display rectangle (SourceX, SourceY)
|
||||
/// (SourceX + Width, SourceY + Height) to the video display rectangle
|
||||
/// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
|
||||
/// The BltBuffer and Delta are not used in this mode.
|
||||
///
|
||||
EfiBltVideoToVideo,
|
||||
|
||||
EfiGraphicsOutputBltOperationMax
|
||||
} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
|
||||
|
||||
/**
|
||||
Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param BltBuffer The data to transfer to the graphics screen.
|
||||
Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
|
||||
@param BltOperation The operation to perform when copying BltBuffer on to the graphics screen.
|
||||
@param SourceX The X coordinate of source for the BltOperation.
|
||||
@param SourceY The Y coordinate of source for the BltOperation.
|
||||
@param DestinationX The X coordinate of destination for the BltOperation.
|
||||
@param DestinationY The Y coordinate of destination for the BltOperation.
|
||||
@param Width The width of a rectangle in the blt rectangle in pixels.
|
||||
@param Height The height of a rectangle in the blt rectangle in pixels.
|
||||
@param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation.
|
||||
If a Delta of zero is used, the entire BltBuffer is being operated on.
|
||||
If a subrectangle of the BltBuffer is being used then Delta
|
||||
represents the number of bytes in a row of the BltBuffer.
|
||||
|
||||
@retval EFI_SUCCESS BltBuffer was drawn to the graphics screen.
|
||||
@retval EFI_INVALID_PARAMETER BltOperation is not valid.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)(
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
|
||||
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
|
||||
IN UINTN SourceX,
|
||||
IN UINTN SourceY,
|
||||
IN UINTN DestinationX,
|
||||
IN UINTN DestinationY,
|
||||
IN UINTN Width,
|
||||
IN UINTN Height,
|
||||
IN UINTN Delta OPTIONAL
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The number of modes supported by QueryMode() and SetMode().
|
||||
///
|
||||
UINT32 MaxMode;
|
||||
///
|
||||
/// Current Mode of the graphics device. Valid mode numbers are 0 to MaxMode -1.
|
||||
///
|
||||
UINT32 Mode;
|
||||
///
|
||||
/// Pointer to read-only EFI_GRAPHICS_OUTPUT_MODE_INFORMATION data.
|
||||
///
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
||||
///
|
||||
/// Size of Info structure in bytes.
|
||||
///
|
||||
UINTN SizeOfInfo;
|
||||
///
|
||||
/// Base address of graphics linear frame buffer.
|
||||
/// Offset zero in FrameBufferBase represents the upper left pixel of the display.
|
||||
///
|
||||
EFI_PHYSICAL_ADDRESS FrameBufferBase;
|
||||
///
|
||||
/// Amount of frame buffer needed to support the active mode as defined by
|
||||
/// PixelsPerScanLine xVerticalResolution x PixelElementSize.
|
||||
///
|
||||
UINTN FrameBufferSize;
|
||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
||||
|
||||
///
|
||||
/// Provides a basic abstraction to set video modes and copy pixels to and from
|
||||
/// the graphics controller's frame buffer. The linear address of the hardware
|
||||
/// frame buffer is also exposed so software can write directly to the video hardware.
|
||||
///
|
||||
struct _EFI_GRAPHICS_OUTPUT_PROTOCOL {
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
|
||||
///
|
||||
/// Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data.
|
||||
///
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiGraphicsOutputProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,88 @@
|
|||
/** @file
|
||||
UEFI 2.0 Loaded image protocol definition.
|
||||
|
||||
Every EFI driver and application is passed an image handle when it is loaded.
|
||||
This image handle will contain a Loaded Image Protocol.
|
||||
|
||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __LOADED_IMAGE_PROTOCOL_H__
|
||||
#define __LOADED_IMAGE_PROTOCOL_H__
|
||||
|
||||
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \
|
||||
}
|
||||
|
||||
#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \
|
||||
{ \
|
||||
0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \
|
||||
}
|
||||
|
||||
///
|
||||
/// Protocol GUID defined in EFI1.1.
|
||||
///
|
||||
#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
|
||||
|
||||
///
|
||||
/// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h
|
||||
///
|
||||
#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
|
||||
|
||||
///
|
||||
/// Revision defined in EFI1.1.
|
||||
///
|
||||
#define EFI_LOADED_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION
|
||||
|
||||
///
|
||||
/// Can be used on any image handle to obtain information about the loaded image.
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure.
|
||||
///< All future revisions will be backward compatible to the current revision.
|
||||
EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from
|
||||
///< the firmware's boot manager.
|
||||
EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer.
|
||||
|
||||
//
|
||||
// Source location of image
|
||||
//
|
||||
EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from.
|
||||
EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle
|
||||
///< that the EFI Image was loaded from.
|
||||
VOID *Reserved; ///< Reserved. DO NOT USE.
|
||||
|
||||
//
|
||||
// Images load options
|
||||
//
|
||||
UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions.
|
||||
VOID *LoadOptions; ///< A pointer to the image's binary load options.
|
||||
|
||||
//
|
||||
// Location of where image was loaded
|
||||
//
|
||||
VOID *ImageBase; ///< The base address at which the image was loaded.
|
||||
UINT64 ImageSize; ///< The size in bytes of the loaded image.
|
||||
EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as.
|
||||
EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as.
|
||||
EFI_IMAGE_UNLOAD Unload;
|
||||
} EFI_LOADED_IMAGE_PROTOCOL;
|
||||
|
||||
//
|
||||
// For backward-compatible with EFI1.1.
|
||||
//
|
||||
typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE;
|
||||
|
||||
extern EFI_GUID gEfiLoadedImageProtocolGuid;
|
||||
extern EFI_GUID gEfiLoadedImageDevicePathProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,562 @@
|
|||
/** @file
|
||||
SimpleFileSystem protocol as defined in the UEFI 2.0 specification.
|
||||
|
||||
The SimpleFileSystem protocol is the programmatic access to the FAT (12,16,32)
|
||||
file system specified in UEFI 2.0. It can also be used to abstract a file
|
||||
system other than FAT.
|
||||
|
||||
UEFI 2.0 can boot from any valid EFI image contained in a SimpleFileSystem.
|
||||
|
||||
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __SIMPLE_FILE_SYSTEM_H__
|
||||
#define __SIMPLE_FILE_SYSTEM_H__
|
||||
|
||||
#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||
|
||||
typedef struct _EFI_FILE_PROTOCOL EFI_FILE_PROTOCOL;
|
||||
typedef struct _EFI_FILE_PROTOCOL *EFI_FILE_HANDLE;
|
||||
|
||||
///
|
||||
/// Protocol GUID name defined in EFI1.1.
|
||||
///
|
||||
#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID
|
||||
|
||||
///
|
||||
/// Protocol name defined in EFI1.1.
|
||||
///
|
||||
typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE;
|
||||
typedef EFI_FILE_PROTOCOL EFI_FILE;
|
||||
|
||||
/**
|
||||
Open the root directory on a volume.
|
||||
|
||||
@param This A pointer to the volume to open the root directory.
|
||||
@param Root A pointer to the location to return the opened file handle for the
|
||||
root directory.
|
||||
|
||||
@retval EFI_SUCCESS The device was opened.
|
||||
@retval EFI_UNSUPPORTED This volume does not support the requested file system type.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_ACCESS_DENIED The service denied access to the file.
|
||||
@retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
|
||||
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
|
||||
longer supported. Any existing file handles for this volume are
|
||||
no longer valid. To access the files on the new medium, the
|
||||
volume must be reopened with OpenVolume().
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)(
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
);
|
||||
|
||||
#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000
|
||||
|
||||
///
|
||||
/// Revision defined in EFI1.1
|
||||
///
|
||||
#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
|
||||
|
||||
struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
|
||||
///
|
||||
/// The version of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. The version
|
||||
/// specified by this specification is 0x00010000. All future revisions
|
||||
/// must be backwards compatible.
|
||||
///
|
||||
UINT64 Revision;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
|
||||
};
|
||||
|
||||
/**
|
||||
Opens a new file relative to the source file's location.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to the source location. This would typically be an open
|
||||
handle to a directory.
|
||||
@param NewHandle A pointer to the location to return the opened handle for the new
|
||||
file.
|
||||
@param FileName The Null-terminated string of the name of the file to be opened.
|
||||
The file name may contain the following path modifiers: "\", ".",
|
||||
and "..".
|
||||
@param OpenMode The mode to open the file. The only valid combinations that the
|
||||
file may be opened with are: Read, Read/Write, or Create/Read/Write.
|
||||
@param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
|
||||
attribute bits for the newly created file.
|
||||
|
||||
@retval EFI_SUCCESS The file was opened.
|
||||
@retval EFI_NOT_FOUND The specified file could not be found on the device.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
|
||||
longer supported.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
|
||||
when the media is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The service denied access to the file.
|
||||
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_OPEN)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **NewHandle,
|
||||
IN CHAR16 *FileName,
|
||||
IN UINT64 OpenMode,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
//
|
||||
// Open modes
|
||||
//
|
||||
#define EFI_FILE_MODE_READ 0x0000000000000001ULL
|
||||
#define EFI_FILE_MODE_WRITE 0x0000000000000002ULL
|
||||
#define EFI_FILE_MODE_CREATE 0x8000000000000000ULL
|
||||
|
||||
//
|
||||
// File attributes
|
||||
//
|
||||
#define EFI_FILE_READ_ONLY 0x0000000000000001ULL
|
||||
#define EFI_FILE_HIDDEN 0x0000000000000002ULL
|
||||
#define EFI_FILE_SYSTEM 0x0000000000000004ULL
|
||||
#define EFI_FILE_RESERVED 0x0000000000000008ULL
|
||||
#define EFI_FILE_DIRECTORY 0x0000000000000010ULL
|
||||
#define EFI_FILE_ARCHIVE 0x0000000000000020ULL
|
||||
#define EFI_FILE_VALID_ATTR 0x0000000000000037ULL
|
||||
|
||||
/**
|
||||
Closes a specified file handle.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to close.
|
||||
|
||||
@retval EFI_SUCCESS The file was closed.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_CLOSE)(
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Close and delete the file handle.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the
|
||||
handle to the file to delete.
|
||||
|
||||
@retval EFI_SUCCESS The file was closed and deleted, and the handle was closed.
|
||||
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_DELETE)(
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Reads data from a file.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to read data from.
|
||||
@param BufferSize On input, the size of the Buffer. On output, the amount of data
|
||||
returned in Buffer. In both cases, the size is measured in bytes.
|
||||
@param Buffer The buffer into which the data is read.
|
||||
|
||||
@retval EFI_SUCCESS Data was read.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
|
||||
@retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
|
||||
entry. BufferSize has been updated with the size
|
||||
needed to complete the request.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_READ)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Writes data to a file.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to write data to.
|
||||
@param BufferSize On input, the size of the Buffer. On output, the amount of data
|
||||
actually written. In both cases, the size is measured in bytes.
|
||||
@param Buffer The buffer of data to write.
|
||||
|
||||
@retval EFI_SUCCESS Data was written.
|
||||
@retval EFI_UNSUPPORTED Writes to open directory files are not supported.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED The file or medium is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The file was opened read only.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_WRITE)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Sets a file's current position.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the
|
||||
file handle to set the requested position on.
|
||||
@param Position The byte position from the start of the file to set.
|
||||
|
||||
@retval EFI_SUCCESS The position was set.
|
||||
@retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open
|
||||
directories.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_SET_POSITION)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN UINT64 Position
|
||||
);
|
||||
|
||||
/**
|
||||
Returns a file's current position.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to get the current position on.
|
||||
@param Position The address to return the file's current position value.
|
||||
|
||||
@retval EFI_SUCCESS The position was returned.
|
||||
@retval EFI_UNSUPPORTED The request is not valid on open directories.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_GET_POSITION)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT UINT64 *Position
|
||||
);
|
||||
|
||||
/**
|
||||
Returns information about a file.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle the requested information is for.
|
||||
@param InformationType The type identifier for the information being requested.
|
||||
@param BufferSize On input, the size of Buffer. On output, the amount of data
|
||||
returned in Buffer. In both cases, the size is measured in bytes.
|
||||
@param Buffer A pointer to the data buffer to return. The buffer's type is
|
||||
indicated by InformationType.
|
||||
|
||||
@retval EFI_SUCCESS The information was returned.
|
||||
@retval EFI_UNSUPPORTED The InformationType is not known.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
|
||||
BufferSize has been updated with the size needed to complete
|
||||
the request.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_GET_INFO)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Sets information about a file.
|
||||
|
||||
@param File A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle the information is for.
|
||||
@param InformationType The type identifier for the information being set.
|
||||
@param BufferSize The size, in bytes, of Buffer.
|
||||
@param Buffer A pointer to the data buffer to write. The buffer's type is
|
||||
indicated by InformationType.
|
||||
|
||||
@retval EFI_SUCCESS The information was set.
|
||||
@retval EFI_UNSUPPORTED The InformationType is not known.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the media is
|
||||
read-only.
|
||||
@retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_PROTOCOL_SYSTEM_INFO_ID
|
||||
and the media is read only.
|
||||
@retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_SYSTEM_VOLUME_LABEL_ID
|
||||
and the media is read-only.
|
||||
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a
|
||||
file that is already present.
|
||||
@retval EFI_ACCESS_DENIED An attempt is being made to change the EFI_FILE_DIRECTORY
|
||||
Attribute.
|
||||
@retval EFI_ACCESS_DENIED An attempt is being made to change the size of a directory.
|
||||
@retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the file was opened
|
||||
read-only and an attempt is being made to modify a field
|
||||
other than Attribute.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
@retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type indicated
|
||||
by InformationType.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_SET_INFO)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flushes all modified data associated with a file to a device.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to flush.
|
||||
|
||||
@retval EFI_SUCCESS The data was flushed.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED The file or medium is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The file was opened read-only.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_FLUSH)(
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
//
|
||||
// If Event is NULL, then blocking I/O is performed.
|
||||
// If Event is not NULL and non-blocking I/O is supported, then non-blocking I/O is performed,
|
||||
// and Event will be signaled when the read request is completed.
|
||||
// The caller must be prepared to handle the case where the callback associated with Event
|
||||
// occurs before the original asynchronous I/O request call returns.
|
||||
//
|
||||
EFI_EVENT Event;
|
||||
|
||||
//
|
||||
// Defines whether or not the signaled event encountered an error.
|
||||
//
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// For OpenEx(): Not Used, ignored.
|
||||
// For ReadEx(): On input, the size of the Buffer. On output, the amount of data returned in Buffer.
|
||||
// In both cases, the size is measured in bytes.
|
||||
// For WriteEx(): On input, the size of the Buffer. On output, the amount of data actually written.
|
||||
// In both cases, the size is measured in bytes.
|
||||
// For FlushEx(): Not used, ignored.
|
||||
//
|
||||
UINTN BufferSize;
|
||||
|
||||
//
|
||||
// For OpenEx(): Not Used, ignored.
|
||||
// For ReadEx(): The buffer into which the data is read.
|
||||
// For WriteEx(): The buffer of data to write.
|
||||
// For FlushEx(): Not Used, ignored.
|
||||
//
|
||||
VOID *Buffer;
|
||||
} EFI_FILE_IO_TOKEN;
|
||||
|
||||
/**
|
||||
Opens a new file relative to the source directory's location.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to the source location.
|
||||
@param NewHandle A pointer to the location to return the opened handle for the new
|
||||
file.
|
||||
@param FileName The Null-terminated string of the name of the file to be opened.
|
||||
The file name may contain the following path modifiers: "\", ".",
|
||||
and "..".
|
||||
@param OpenMode The mode to open the file. The only valid combinations that the
|
||||
file may be opened with are: Read, Read/Write, or Create/Read/Write.
|
||||
@param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
|
||||
attribute bits for the newly created file.
|
||||
@param Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
|
||||
If Event is not NULL (asynchronous I/O): The request was successfully
|
||||
queued for processing.
|
||||
@retval EFI_NOT_FOUND The specified file could not be found on the device.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
|
||||
longer supported.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
|
||||
when the media is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The service denied access to the file.
|
||||
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_OPEN_EX)(
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **NewHandle,
|
||||
IN CHAR16 *FileName,
|
||||
IN UINT64 OpenMode,
|
||||
IN UINT64 Attributes,
|
||||
IN OUT EFI_FILE_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Reads data from a file.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to read data from.
|
||||
@param Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
|
||||
If Event is not NULL (asynchronous I/O): The request was successfully
|
||||
queued for processing.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
|
||||
@retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_READ_EX) (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT EFI_FILE_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Writes data to a file.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to write data to.
|
||||
@param Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
|
||||
If Event is not NULL (asynchronous I/O): The request was successfully
|
||||
queued for processing.
|
||||
@retval EFI_UNSUPPORTED Writes to open directory files are not supported.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED The file or medium is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The file was opened read only.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
@retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_WRITE_EX) (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT EFI_FILE_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Flushes all modified data associated with a file to a device.
|
||||
|
||||
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to flush.
|
||||
@param Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
|
||||
If Event is not NULL (asynchronous I/O): The request was successfully
|
||||
queued for processing.
|
||||
@retval EFI_NO_MEDIA The device has no medium.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
||||
@retval EFI_WRITE_PROTECTED The file or medium is write-protected.
|
||||
@retval EFI_ACCESS_DENIED The file was opened read-only.
|
||||
@retval EFI_VOLUME_FULL The volume is full.
|
||||
@retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_FILE_FLUSH_EX) (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT EFI_FILE_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
#define EFI_FILE_PROTOCOL_REVISION 0x00010000
|
||||
#define EFI_FILE_PROTOCOL_REVISION2 0x00020000
|
||||
#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2
|
||||
|
||||
//
|
||||
// Revision defined in EFI1.1.
|
||||
//
|
||||
#define EFI_FILE_REVISION EFI_FILE_PROTOCOL_REVISION
|
||||
|
||||
///
|
||||
/// The EFI_FILE_PROTOCOL provides file IO access to supported file systems.
|
||||
/// An EFI_FILE_PROTOCOL provides access to a file's or directory's contents,
|
||||
/// and is also a reference to a location in the directory tree of the file system
|
||||
/// in which the file resides. With any given file handle, other files may be opened
|
||||
/// relative to this file's location, yielding new file handles.
|
||||
///
|
||||
struct _EFI_FILE_PROTOCOL {
|
||||
///
|
||||
/// The version of the EFI_FILE_PROTOCOL interface. The version specified
|
||||
/// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
|
||||
/// Future versions are required to be backward compatible to version 1.0.
|
||||
///
|
||||
UINT64 Revision;
|
||||
EFI_FILE_OPEN Open;
|
||||
EFI_FILE_CLOSE Close;
|
||||
EFI_FILE_DELETE Delete;
|
||||
EFI_FILE_READ Read;
|
||||
EFI_FILE_WRITE Write;
|
||||
EFI_FILE_GET_POSITION GetPosition;
|
||||
EFI_FILE_SET_POSITION SetPosition;
|
||||
EFI_FILE_GET_INFO GetInfo;
|
||||
EFI_FILE_SET_INFO SetInfo;
|
||||
EFI_FILE_FLUSH Flush;
|
||||
EFI_FILE_OPEN_EX OpenEx;
|
||||
EFI_FILE_READ_EX ReadEx;
|
||||
EFI_FILE_WRITE_EX WriteEx;
|
||||
EFI_FILE_FLUSH_EX FlushEx;
|
||||
};
|
||||
|
||||
|
||||
extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/** @file
|
||||
Simple Text Input protocol from the UEFI 2.0 specification.
|
||||
|
||||
Abstraction of a very simple input device like a keyboard or serial
|
||||
terminal.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__
|
||||
#define __SIMPLE_TEXT_IN_PROTOCOL_H__
|
||||
|
||||
#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
|
||||
|
||||
///
|
||||
/// Protocol GUID name defined in EFI1.1.
|
||||
///
|
||||
#define SIMPLE_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID
|
||||
|
||||
///
|
||||
/// Protocol name in EFI1.1 for backward-compatible.
|
||||
///
|
||||
typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE;
|
||||
|
||||
///
|
||||
/// The keystroke information for the key that was pressed.
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 ScanCode;
|
||||
CHAR16 UnicodeChar;
|
||||
} EFI_INPUT_KEY;
|
||||
|
||||
//
|
||||
// Required unicode control chars
|
||||
//
|
||||
#define CHAR_NULL 0x0000
|
||||
#define CHAR_BACKSPACE 0x0008
|
||||
#define CHAR_TAB 0x0009
|
||||
#define CHAR_LINEFEED 0x000A
|
||||
#define CHAR_CARRIAGE_RETURN 0x000D
|
||||
|
||||
//
|
||||
// EFI Scan codes
|
||||
//
|
||||
#define SCAN_NULL 0x0000
|
||||
#define SCAN_UP 0x0001
|
||||
#define SCAN_DOWN 0x0002
|
||||
#define SCAN_RIGHT 0x0003
|
||||
#define SCAN_LEFT 0x0004
|
||||
#define SCAN_HOME 0x0005
|
||||
#define SCAN_END 0x0006
|
||||
#define SCAN_INSERT 0x0007
|
||||
#define SCAN_DELETE 0x0008
|
||||
#define SCAN_PAGE_UP 0x0009
|
||||
#define SCAN_PAGE_DOWN 0x000A
|
||||
#define SCAN_F1 0x000B
|
||||
#define SCAN_F2 0x000C
|
||||
#define SCAN_F3 0x000D
|
||||
#define SCAN_F4 0x000E
|
||||
#define SCAN_F5 0x000F
|
||||
#define SCAN_F6 0x0010
|
||||
#define SCAN_F7 0x0011
|
||||
#define SCAN_F8 0x0012
|
||||
#define SCAN_F9 0x0013
|
||||
#define SCAN_F10 0x0014
|
||||
#define SCAN_ESC 0x0017
|
||||
|
||||
/**
|
||||
Reset the input device and optionally run diagnostics
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_INPUT_RESET)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Reads the next keystroke from the input device. The WaitForKey Event can
|
||||
be used to test for existence of a keystroke via WaitForEvent () call.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param Key A pointer to a buffer that is filled in with the keystroke
|
||||
information for the key that was pressed.
|
||||
|
||||
@retval EFI_SUCCESS The keystroke information was returned.
|
||||
@retval EFI_NOT_READY There was no keystroke data available.
|
||||
@retval EFI_DEVICE_ERROR The keystroke information was not returned due to
|
||||
hardware errors.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_INPUT_READ_KEY)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
|
||||
OUT EFI_INPUT_KEY *Key
|
||||
);
|
||||
|
||||
///
|
||||
/// The EFI_SIMPLE_TEXT_INPUT_PROTOCOL is used on the ConsoleIn device.
|
||||
/// It is the minimum required protocol for ConsoleIn.
|
||||
///
|
||||
struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
|
||||
EFI_INPUT_RESET Reset;
|
||||
EFI_INPUT_READ_KEY ReadKeyStroke;
|
||||
///
|
||||
/// Event to use with WaitForEvent() to wait for a key to be available
|
||||
///
|
||||
EFI_EVENT WaitForKey;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiSimpleTextInProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,325 @@
|
|||
/** @file
|
||||
Simple Text Input Ex protocol from the UEFI 2.0 specification.
|
||||
|
||||
This protocol defines an extension to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
|
||||
which exposes much more state and modifier information from the input device,
|
||||
also allows one to register a notification for a particular keystroke.
|
||||
|
||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __SIMPLE_TEXT_IN_EX_H__
|
||||
#define __SIMPLE_TEXT_IN_EX_H__
|
||||
|
||||
#include "efi/Protocol/SimpleTextIn.h"
|
||||
|
||||
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
|
||||
{0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
|
||||
|
||||
|
||||
typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
|
||||
|
||||
/**
|
||||
The Reset() function resets the input device hardware. As part
|
||||
of initialization process, the firmware/device will make a quick
|
||||
but reasonable attempt to verify that the device is functioning.
|
||||
If the ExtendedVerification flag is TRUE the firmware may take
|
||||
an extended amount of time to verify the device is operating on
|
||||
reset. Otherwise the reset operation is to occur as quickly as
|
||||
possible. The hardware verification process is not defined by
|
||||
this specification and is left up to the platform firmware or
|
||||
driver to implement.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
|
||||
|
||||
@param ExtendedVerification Indicates that the driver may
|
||||
perform a more exhaustive
|
||||
verification operation of the
|
||||
device during reset.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning
|
||||
correctly and could not be reset.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_INPUT_RESET_EX)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
|
||||
///
|
||||
/// EFI_KEY_TOGGLE_STATE. The toggle states are defined.
|
||||
/// They are: EFI_TOGGLE_STATE_VALID, EFI_SCROLL_LOCK_ACTIVE
|
||||
/// EFI_NUM_LOCK_ACTIVE, EFI_CAPS_LOCK_ACTIVE
|
||||
///
|
||||
typedef UINT8 EFI_KEY_TOGGLE_STATE;
|
||||
|
||||
typedef struct _EFI_KEY_STATE {
|
||||
///
|
||||
/// Reflects the currently pressed shift
|
||||
/// modifiers for the input device. The
|
||||
/// returned value is valid only if the high
|
||||
/// order bit has been set.
|
||||
///
|
||||
UINT32 KeyShiftState;
|
||||
///
|
||||
/// Reflects the current internal state of
|
||||
/// various toggled attributes. The returned
|
||||
/// value is valid only if the high order
|
||||
/// bit has been set.
|
||||
///
|
||||
EFI_KEY_TOGGLE_STATE KeyToggleState;
|
||||
} EFI_KEY_STATE;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The EFI scan code and Unicode value returned from the input device.
|
||||
///
|
||||
EFI_INPUT_KEY Key;
|
||||
///
|
||||
/// The current state of various toggled attributes as well as input modifier values.
|
||||
///
|
||||
EFI_KEY_STATE KeyState;
|
||||
} EFI_KEY_DATA;
|
||||
|
||||
//
|
||||
// Any Shift or Toggle State that is valid should have
|
||||
// high order bit set.
|
||||
//
|
||||
// Shift state
|
||||
//
|
||||
#define EFI_SHIFT_STATE_VALID 0x80000000
|
||||
#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
|
||||
#define EFI_LEFT_SHIFT_PRESSED 0x00000002
|
||||
#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_RIGHT_LOGO_PRESSED 0x00000040
|
||||
#define EFI_LEFT_LOGO_PRESSED 0x00000080
|
||||
#define EFI_MENU_KEY_PRESSED 0x00000100
|
||||
#define EFI_SYS_REQ_PRESSED 0x00000200
|
||||
|
||||
//
|
||||
// Toggle state
|
||||
//
|
||||
#define EFI_TOGGLE_STATE_VALID 0x80
|
||||
#define EFI_KEY_STATE_EXPOSED 0x40
|
||||
#define EFI_SCROLL_LOCK_ACTIVE 0x01
|
||||
#define EFI_NUM_LOCK_ACTIVE 0x02
|
||||
#define EFI_CAPS_LOCK_ACTIVE 0x04
|
||||
|
||||
//
|
||||
// EFI Scan codes
|
||||
//
|
||||
#define SCAN_F11 0x0015
|
||||
#define SCAN_F12 0x0016
|
||||
#define SCAN_PAUSE 0x0048
|
||||
#define SCAN_F13 0x0068
|
||||
#define SCAN_F14 0x0069
|
||||
#define SCAN_F15 0x006A
|
||||
#define SCAN_F16 0x006B
|
||||
#define SCAN_F17 0x006C
|
||||
#define SCAN_F18 0x006D
|
||||
#define SCAN_F19 0x006E
|
||||
#define SCAN_F20 0x006F
|
||||
#define SCAN_F21 0x0070
|
||||
#define SCAN_F22 0x0071
|
||||
#define SCAN_F23 0x0072
|
||||
#define SCAN_F24 0x0073
|
||||
#define SCAN_MUTE 0x007F
|
||||
#define SCAN_VOLUME_UP 0x0080
|
||||
#define SCAN_VOLUME_DOWN 0x0081
|
||||
#define SCAN_BRIGHTNESS_UP 0x0100
|
||||
#define SCAN_BRIGHTNESS_DOWN 0x0101
|
||||
#define SCAN_SUSPEND 0x0102
|
||||
#define SCAN_HIBERNATE 0x0103
|
||||
#define SCAN_TOGGLE_DISPLAY 0x0104
|
||||
#define SCAN_RECOVERY 0x0105
|
||||
#define SCAN_EJECT 0x0106
|
||||
|
||||
/**
|
||||
The function reads the next keystroke from the input device. If
|
||||
there is no pending keystroke the function returns
|
||||
EFI_NOT_READY. If there is a pending keystroke, then
|
||||
KeyData.Key.ScanCode is the EFI scan code defined in Error!
|
||||
Reference source not found. The KeyData.Key.UnicodeChar is the
|
||||
actual printable character or is zero if the key does not
|
||||
represent a printable character (control key, function key,
|
||||
etc.). The KeyData.KeyState is shift state for the character
|
||||
reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode .
|
||||
When interpreting the data from this function, it should be
|
||||
noted that if a class of printable characters that are
|
||||
normally adjusted by shift modifiers (e.g. Shift Key + "f"
|
||||
key) would be presented solely as a KeyData.Key.UnicodeChar
|
||||
without the associated shift state. So in the previous example
|
||||
of a Shift Key + "f" key being pressed, the only pertinent
|
||||
data returned would be KeyData.Key.UnicodeChar with the value
|
||||
of "F". This of course would not typically be the case for
|
||||
non-printable characters such as the pressing of the Right
|
||||
Shift Key + F10 key since the corresponding returned data
|
||||
would be reflected both in the KeyData.KeyState.KeyShiftState
|
||||
and KeyData.Key.ScanCode values. UEFI drivers which implement
|
||||
the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return
|
||||
KeyData.Key and KeyData.KeyState values. These drivers must
|
||||
always return the most current state of
|
||||
KeyData.KeyState.KeyShiftState and
|
||||
KeyData.KeyState.KeyToggleState. It should also be noted that
|
||||
certain input devices may not be able to produce shift or toggle
|
||||
state information, and in those cases the high order bit in the
|
||||
respective Toggle and Shift state fields should not be active.
|
||||
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
|
||||
|
||||
@param KeyData A pointer to a buffer that is filled in with
|
||||
the keystroke state data for the key that was
|
||||
pressed.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The keystroke information was
|
||||
returned.
|
||||
|
||||
@retval EFI_NOT_READY There was no keystroke data available.
|
||||
EFI_DEVICE_ERROR The keystroke
|
||||
information was not returned due to
|
||||
hardware errors.
|
||||
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_INPUT_READ_KEY_EX)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
||||
OUT EFI_KEY_DATA *KeyData
|
||||
);
|
||||
|
||||
/**
|
||||
The SetState() function allows the input device hardware to
|
||||
have state settings adjusted.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
|
||||
|
||||
@param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to
|
||||
set the state for the input device.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The device state was set appropriately.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning
|
||||
correctly and could not have the
|
||||
setting adjusted.
|
||||
|
||||
@retval EFI_UNSUPPORTED The device does not support the
|
||||
ability to have its state set.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SET_STATE)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
||||
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
|
||||
);
|
||||
|
||||
///
|
||||
/// The function will be called when the key sequence is typed specified by KeyData.
|
||||
///
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
|
||||
IN EFI_KEY_DATA *KeyData
|
||||
);
|
||||
|
||||
/**
|
||||
The RegisterKeystrokeNotify() function registers a function
|
||||
which will be called when a specified keystroke will occur.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
|
||||
|
||||
@param KeyData A pointer to a buffer that is filled in with
|
||||
the keystroke information for the key that was
|
||||
pressed.
|
||||
|
||||
@param KeyNotificationFunction Points to the function to be
|
||||
called when the key sequence
|
||||
is typed specified by KeyData.
|
||||
|
||||
|
||||
@param NotifyHandle Points to the unique handle assigned to
|
||||
the registered notification.
|
||||
|
||||
@retval EFI_SUCCESS The device state was set
|
||||
appropriately.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
|
||||
data structures.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
||||
IN EFI_KEY_DATA *KeyData,
|
||||
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
|
||||
OUT VOID **NotifyHandle
|
||||
);
|
||||
|
||||
/**
|
||||
The UnregisterKeystrokeNotify() function removes the
|
||||
notification which was previously registered.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
|
||||
|
||||
@param NotificationHandle The handle of the notification
|
||||
function being unregistered.
|
||||
|
||||
@retval EFI_SUCCESS The device state was set appropriately.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The NotificationHandle is
|
||||
invalid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
|
||||
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
||||
IN VOID *NotificationHandle
|
||||
);
|
||||
|
||||
|
||||
///
|
||||
/// The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is used on the ConsoleIn
|
||||
/// device. It is an extension to the Simple Text Input protocol
|
||||
/// which allows a variety of extended shift state information to be
|
||||
/// returned.
|
||||
///
|
||||
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{
|
||||
EFI_INPUT_RESET_EX Reset;
|
||||
EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
|
||||
///
|
||||
/// Event to use with WaitForEvent() to wait for a key to be available.
|
||||
///
|
||||
EFI_EVENT WaitForKeyEx;
|
||||
EFI_SET_STATE SetState;
|
||||
EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
|
||||
EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
|
||||
};
|
||||
|
||||
|
||||
extern EFI_GUID gEfiSimpleTextInputExProtocolGuid;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
/** @file
|
||||
Simple Text Out protocol from the UEFI 2.0 specification.
|
||||
|
||||
Abstraction of a very simple text based output device like VGA text mode or
|
||||
a serial terminal. The Simple Text Out protocol instance can represent
|
||||
a single hardware device or a virtual device that is an aggregation
|
||||
of multiple physical devices.
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __SIMPLE_TEXT_OUT_H__
|
||||
#define __SIMPLE_TEXT_OUT_H__
|
||||
|
||||
#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
///
|
||||
/// Protocol GUID defined in EFI1.1.
|
||||
///
|
||||
#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID
|
||||
|
||||
typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||
|
||||
///
|
||||
/// Backward-compatible with EFI1.1.
|
||||
///
|
||||
typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
|
||||
|
||||
//
|
||||
// Define's for required EFI Unicode Box Draw characters
|
||||
//
|
||||
#define BOXDRAW_HORIZONTAL 0x2500
|
||||
#define BOXDRAW_VERTICAL 0x2502
|
||||
#define BOXDRAW_DOWN_RIGHT 0x250c
|
||||
#define BOXDRAW_DOWN_LEFT 0x2510
|
||||
#define BOXDRAW_UP_RIGHT 0x2514
|
||||
#define BOXDRAW_UP_LEFT 0x2518
|
||||
#define BOXDRAW_VERTICAL_RIGHT 0x251c
|
||||
#define BOXDRAW_VERTICAL_LEFT 0x2524
|
||||
#define BOXDRAW_DOWN_HORIZONTAL 0x252c
|
||||
#define BOXDRAW_UP_HORIZONTAL 0x2534
|
||||
#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c
|
||||
#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
|
||||
#define BOXDRAW_DOUBLE_VERTICAL 0x2551
|
||||
#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
|
||||
#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
|
||||
#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
|
||||
#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
|
||||
#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
|
||||
#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
|
||||
#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
|
||||
#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
|
||||
#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a
|
||||
#define BOXDRAW_UP_LEFT_DOUBLE 0x255b
|
||||
#define BOXDRAW_UP_DOUBLE_LEFT 0x255c
|
||||
#define BOXDRAW_DOUBLE_UP_LEFT 0x255d
|
||||
#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e
|
||||
#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f
|
||||
#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
|
||||
#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
|
||||
#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
|
||||
#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
|
||||
#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
|
||||
#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
|
||||
#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
|
||||
#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
|
||||
#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
|
||||
#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
|
||||
#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a
|
||||
#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b
|
||||
#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c
|
||||
|
||||
//
|
||||
// EFI Required Block Elements Code Chart
|
||||
//
|
||||
#define BLOCKELEMENT_FULL_BLOCK 0x2588
|
||||
#define BLOCKELEMENT_LIGHT_SHADE 0x2591
|
||||
|
||||
//
|
||||
// EFI Required Geometric Shapes Code Chart
|
||||
//
|
||||
#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2
|
||||
#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba
|
||||
#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc
|
||||
#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4
|
||||
|
||||
//
|
||||
// EFI Required Arrow shapes
|
||||
//
|
||||
#define ARROW_LEFT 0x2190
|
||||
#define ARROW_UP 0x2191
|
||||
#define ARROW_RIGHT 0x2192
|
||||
#define ARROW_DOWN 0x2193
|
||||
|
||||
//
|
||||
// EFI Console Colours
|
||||
//
|
||||
#define EFI_BLACK 0x00
|
||||
#define EFI_BLUE 0x01
|
||||
#define EFI_GREEN 0x02
|
||||
#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
|
||||
#define EFI_RED 0x04
|
||||
#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
|
||||
#define EFI_BROWN (EFI_GREEN | EFI_RED)
|
||||
#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
|
||||
#define EFI_BRIGHT 0x08
|
||||
#define EFI_DARKGRAY (EFI_BRIGHT)
|
||||
#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
|
||||
#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
|
||||
#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
|
||||
#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
|
||||
#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
|
||||
#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
|
||||
#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
|
||||
|
||||
#define EFI_TEXT_ATTR(f, b) ((f) | ((b) << 4))
|
||||
|
||||
#define EFI_BACKGROUND_BLACK 0x00
|
||||
#define EFI_BACKGROUND_BLUE 0x10
|
||||
#define EFI_BACKGROUND_GREEN 0x20
|
||||
#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
|
||||
#define EFI_BACKGROUND_RED 0x40
|
||||
#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
|
||||
#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
|
||||
#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
|
||||
|
||||
//
|
||||
// We currently define attributes from 0 - 7F for color manipulations
|
||||
// To internally handle the local display characteristics for a particular character,
|
||||
// Bit 7 signifies the local glyph representation for a character. If turned on, glyphs will be
|
||||
// pulled from the wide glyph database and will display locally as a wide character (16 X 19 versus 8 X 19)
|
||||
// If bit 7 is off, the narrow glyph database will be used. This does NOT affect information that is sent to
|
||||
// non-local displays, such as serial or LAN consoles.
|
||||
//
|
||||
#define EFI_WIDE_ATTRIBUTE 0x80
|
||||
|
||||
/**
|
||||
Reset the text output device hardware and optionaly run diagnostics
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param ExtendedVerification Driver may perform more exhaustive verfication
|
||||
operation of the device during reset.
|
||||
|
||||
@retval EFI_SUCCESS The text output device was reset.
|
||||
@retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
|
||||
could not be reset.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_RESET)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Write a string to the output device.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param String The NULL-terminated string to be displayed on the output
|
||||
device(s). All output devices must also support the Unicode
|
||||
drawing character codes defined in this file.
|
||||
|
||||
@retval EFI_SUCCESS The string was output to the device.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting to output
|
||||
the text.
|
||||
@retval EFI_UNSUPPORTED The output device's mode is not currently in a
|
||||
defined text mode.
|
||||
@retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
|
||||
characters in the string could not be
|
||||
rendered and were skipped.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_STRING)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN CHAR16 *String
|
||||
);
|
||||
|
||||
/**
|
||||
Verifies that all characters in a string can be output to the
|
||||
target device.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param String The NULL-terminated string to be examined for the output
|
||||
device(s).
|
||||
|
||||
@retval EFI_SUCCESS The device(s) are capable of rendering the output string.
|
||||
@retval EFI_UNSUPPORTED Some of the characters in the string cannot be
|
||||
rendered by one or more of the output devices mapped
|
||||
by the EFI handle.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_TEST_STRING)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN CHAR16 *String
|
||||
);
|
||||
|
||||
/**
|
||||
Returns information for an available text mode that the output device(s)
|
||||
supports.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param ModeNumber The mode number to return information on.
|
||||
@param Columns Returns the geometry of the text output device for the
|
||||
requested ModeNumber.
|
||||
@param Rows Returns the geometry of the text output device for the
|
||||
requested ModeNumber.
|
||||
|
||||
@retval EFI_SUCCESS The requested mode information was returned.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED The mode number was not valid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_QUERY_MODE)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN UINTN ModeNumber,
|
||||
OUT UINTN *Columns,
|
||||
OUT UINTN *Rows
|
||||
);
|
||||
|
||||
/**
|
||||
Sets the output device(s) to a specified mode.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param ModeNumber The mode number to set.
|
||||
|
||||
@retval EFI_SUCCESS The requested text mode was set.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED The mode number was not valid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_SET_MODE)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN UINTN ModeNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Sets the background and foreground colors for the OutputString () and
|
||||
ClearScreen () functions.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param Attribute The attribute to set. Bits 0..3 are the foreground color, and
|
||||
bits 4..6 are the background color. All other bits are undefined
|
||||
and must be zero. The valid Attributes are defined in this file.
|
||||
|
||||
@retval EFI_SUCCESS The attribute was set.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED The attribute requested is not defined.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_SET_ATTRIBUTE)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN UINTN Attribute
|
||||
);
|
||||
|
||||
/**
|
||||
Clears the output device(s) display to the currently selected background
|
||||
color.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED The output device is not in a valid text mode.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_CLEAR_SCREEN)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Sets the current coordinates of the cursor position
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param Column The position to set the cursor to. Must be greater than or
|
||||
equal to zero and less than the number of columns and rows
|
||||
by QueryMode ().
|
||||
@param Row The position to set the cursor to. Must be greater than or
|
||||
equal to zero and less than the number of columns and rows
|
||||
by QueryMode ().
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
||||
@retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
|
||||
cursor position is invalid for the current mode.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN UINTN Column,
|
||||
IN UINTN Row
|
||||
);
|
||||
|
||||
/**
|
||||
Makes the cursor visible or invisible
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
|
||||
set to be invisible.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_DEVICE_ERROR The device had an error and could not complete the
|
||||
request, or the device does not support changing
|
||||
the cursor mode.
|
||||
@retval EFI_UNSUPPORTED The output device is not in a valid text mode.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TEXT_ENABLE_CURSOR)(
|
||||
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||||
IN BOOLEAN Visible
|
||||
);
|
||||
|
||||
/**
|
||||
@par Data Structure Description:
|
||||
Mode Structure pointed to by Simple Text Out protocol.
|
||||
**/
|
||||
typedef struct {
|
||||
///
|
||||
/// The number of modes supported by QueryMode () and SetMode ().
|
||||
///
|
||||
INT32 MaxMode;
|
||||
|
||||
//
|
||||
// current settings
|
||||
//
|
||||
|
||||
///
|
||||
/// The text mode of the output device(s).
|
||||
///
|
||||
INT32 Mode;
|
||||
///
|
||||
/// The current character output attribute.
|
||||
///
|
||||
INT32 Attribute;
|
||||
///
|
||||
/// The cursor's column.
|
||||
///
|
||||
INT32 CursorColumn;
|
||||
///
|
||||
/// The cursor's row.
|
||||
///
|
||||
INT32 CursorRow;
|
||||
///
|
||||
/// The cursor is currently visbile or not.
|
||||
///
|
||||
BOOLEAN CursorVisible;
|
||||
} EFI_SIMPLE_TEXT_OUTPUT_MODE;
|
||||
|
||||
///
|
||||
/// The SIMPLE_TEXT_OUTPUT protocol is used to control text-based output devices.
|
||||
/// It is the minimum required protocol for any handle supplied as the ConsoleOut
|
||||
/// or StandardError device. In addition, the minimum supported text mode of such
|
||||
/// devices is at least 80 x 25 characters.
|
||||
///
|
||||
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
|
||||
EFI_TEXT_RESET Reset;
|
||||
|
||||
EFI_TEXT_STRING OutputString;
|
||||
EFI_TEXT_TEST_STRING TestString;
|
||||
|
||||
EFI_TEXT_QUERY_MODE QueryMode;
|
||||
EFI_TEXT_SET_MODE SetMode;
|
||||
EFI_TEXT_SET_ATTRIBUTE SetAttribute;
|
||||
|
||||
EFI_TEXT_CLEAR_SCREEN ClearScreen;
|
||||
EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
|
||||
EFI_TEXT_ENABLE_CURSOR EnableCursor;
|
||||
|
||||
///
|
||||
/// Pointer to SIMPLE_TEXT_OUTPUT_MODE data.
|
||||
///
|
||||
EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiSimpleTextOutProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/** @file
|
||||
|
||||
Root include file for Mde Package UEFI, UEFI_APPLICATION type modules.
|
||||
|
||||
This is the include file for any module of type UEFI and UEFI_APPLICATION. Uefi modules only use
|
||||
types defined via this include file and can be ported easily to any
|
||||
environment.
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PI_UEFI_H__
|
||||
#define __PI_UEFI_H__
|
||||
|
||||
#include "efi/Uefi/UefiBaseType.h"
|
||||
#include "efi/Uefi/UefiSpec.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
/** @file
|
||||
Defines data types and constants introduced in UEFI.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __UEFI_BASETYPE_H__
|
||||
#define __UEFI_BASETYPE_H__
|
||||
|
||||
#include "efi/Base.h"
|
||||
|
||||
//
|
||||
// Basic data type definitions introduced in UEFI.
|
||||
//
|
||||
|
||||
///
|
||||
/// 128-bit buffer containing a unique identifier value.
|
||||
///
|
||||
typedef GUID EFI_GUID;
|
||||
///
|
||||
/// Function return status for EFI API.
|
||||
///
|
||||
typedef RETURN_STATUS EFI_STATUS;
|
||||
///
|
||||
/// A collection of related interfaces.
|
||||
///
|
||||
typedef VOID *EFI_HANDLE;
|
||||
///
|
||||
/// Handle to an event structure.
|
||||
///
|
||||
typedef VOID *EFI_EVENT;
|
||||
///
|
||||
/// Task priority level.
|
||||
///
|
||||
typedef UINTN EFI_TPL;
|
||||
///
|
||||
/// Logical block address.
|
||||
///
|
||||
typedef UINT64 EFI_LBA;
|
||||
|
||||
///
|
||||
/// 64-bit physical memory address.
|
||||
///
|
||||
typedef UINT64 EFI_PHYSICAL_ADDRESS;
|
||||
|
||||
///
|
||||
/// 64-bit virtual memory address.
|
||||
///
|
||||
typedef UINT64 EFI_VIRTUAL_ADDRESS;
|
||||
|
||||
///
|
||||
/// EFI Time Abstraction:
|
||||
/// Year: 1900 - 9999
|
||||
/// Month: 1 - 12
|
||||
/// Day: 1 - 31
|
||||
/// Hour: 0 - 23
|
||||
/// Minute: 0 - 59
|
||||
/// Second: 0 - 59
|
||||
/// Nanosecond: 0 - 999,999,999
|
||||
/// TimeZone: -1440 to 1440 or 2047
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Year;
|
||||
UINT8 Month;
|
||||
UINT8 Day;
|
||||
UINT8 Hour;
|
||||
UINT8 Minute;
|
||||
UINT8 Second;
|
||||
UINT8 Pad1;
|
||||
UINT32 Nanosecond;
|
||||
INT16 TimeZone;
|
||||
UINT8 Daylight;
|
||||
UINT8 Pad2;
|
||||
} EFI_TIME;
|
||||
|
||||
|
||||
///
|
||||
/// 4-byte buffer. An IPv4 internet protocol address.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Addr[4];
|
||||
} EFI_IPv4_ADDRESS;
|
||||
|
||||
///
|
||||
/// 16-byte buffer. An IPv6 internet protocol address.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Addr[16];
|
||||
} EFI_IPv6_ADDRESS;
|
||||
|
||||
///
|
||||
/// 32-byte buffer containing a network Media Access Control address.
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Addr[32];
|
||||
} EFI_MAC_ADDRESS;
|
||||
|
||||
///
|
||||
/// 16-byte buffer aligned on a 4-byte boundary.
|
||||
/// An IPv4 or IPv6 internet protocol address.
|
||||
///
|
||||
typedef union {
|
||||
UINT32 Addr[4];
|
||||
EFI_IPv4_ADDRESS v4;
|
||||
EFI_IPv6_ADDRESS v6;
|
||||
} EFI_IP_ADDRESS;
|
||||
|
||||
|
||||
///
|
||||
/// Enumeration of EFI_STATUS.
|
||||
///@{
|
||||
#define EFI_SUCCESS RETURN_SUCCESS
|
||||
#define EFI_LOAD_ERROR RETURN_LOAD_ERROR
|
||||
#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER
|
||||
#define EFI_UNSUPPORTED RETURN_UNSUPPORTED
|
||||
#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE
|
||||
#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL
|
||||
#define EFI_NOT_READY RETURN_NOT_READY
|
||||
#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR
|
||||
#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED
|
||||
#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES
|
||||
#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED
|
||||
#define EFI_VOLUME_FULL RETURN_VOLUME_FULL
|
||||
#define EFI_NO_MEDIA RETURN_NO_MEDIA
|
||||
#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED
|
||||
#define EFI_NOT_FOUND RETURN_NOT_FOUND
|
||||
#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED
|
||||
#define EFI_NO_RESPONSE RETURN_NO_RESPONSE
|
||||
#define EFI_NO_MAPPING RETURN_NO_MAPPING
|
||||
#define EFI_TIMEOUT RETURN_TIMEOUT
|
||||
#define EFI_NOT_STARTED RETURN_NOT_STARTED
|
||||
#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED
|
||||
#define EFI_ABORTED RETURN_ABORTED
|
||||
#define EFI_ICMP_ERROR RETURN_ICMP_ERROR
|
||||
#define EFI_TFTP_ERROR RETURN_TFTP_ERROR
|
||||
#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR
|
||||
#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION
|
||||
#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION
|
||||
#define EFI_CRC_ERROR RETURN_CRC_ERROR
|
||||
#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA
|
||||
#define EFI_END_OF_FILE RETURN_END_OF_FILE
|
||||
#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE
|
||||
#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA
|
||||
|
||||
#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH
|
||||
#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE
|
||||
#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE
|
||||
#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL
|
||||
#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA
|
||||
///@}
|
||||
|
||||
///
|
||||
/// Define macro to encode the status code.
|
||||
///
|
||||
#define EFIERR(_a) ENCODE_ERROR(_a)
|
||||
|
||||
#define EFI_ERROR(A) RETURN_ERROR(A)
|
||||
|
||||
///
|
||||
/// ICMP error definitions
|
||||
///@{
|
||||
#define EFI_NETWORK_UNREACHABLE EFIERR(100)
|
||||
#define EFI_HOST_UNREACHABLE EFIERR(101)
|
||||
#define EFI_PROTOCOL_UNREACHABLE EFIERR(102)
|
||||
#define EFI_PORT_UNREACHABLE EFIERR(103)
|
||||
///@}
|
||||
|
||||
///
|
||||
/// Tcp connection status definitions
|
||||
///@{
|
||||
#define EFI_CONNECTION_FIN EFIERR(104)
|
||||
#define EFI_CONNECTION_RESET EFIERR(105)
|
||||
#define EFI_CONNECTION_REFUSED EFIERR(106)
|
||||
///@}
|
||||
|
||||
//
|
||||
// The EFI memory allocation functions work in units of EFI_PAGEs that are
|
||||
// 4KB. This should in no way be confused with the page size of the processor.
|
||||
// An EFI_PAGE is just the quanta of memory in EFI.
|
||||
//
|
||||
#define EFI_PAGE_SIZE SIZE_4KB
|
||||
#define EFI_PAGE_MASK 0xFFF
|
||||
#define EFI_PAGE_SHIFT 12
|
||||
|
||||
/**
|
||||
Macro that converts a size, in bytes, to a number of EFI_PAGESs.
|
||||
|
||||
@param Size A size in bytes. This parameter is assumed to be type UINTN.
|
||||
Passing in a parameter that is larger than UINTN may produce
|
||||
unexpected results.
|
||||
|
||||
@return The number of EFI_PAGESs associated with the number of bytes specified
|
||||
by Size.
|
||||
|
||||
**/
|
||||
#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0))
|
||||
|
||||
/**
|
||||
Macro that converts a number of EFI_PAGEs to a size in bytes.
|
||||
|
||||
@param Pages The number of EFI_PAGES. This parameter is assumed to be
|
||||
type UINTN. Passing in a parameter that is larger than
|
||||
UINTN may produce unexpected results.
|
||||
|
||||
@return The number of bytes associated with the number of EFI_PAGEs specified
|
||||
by Pages.
|
||||
|
||||
**/
|
||||
#define EFI_PAGES_TO_SIZE(Pages) ((Pages) << EFI_PAGE_SHIFT)
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for IA32 UEFI images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_IA32 0x014C
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for IA64 UEFI images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_IA64 0x0200
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for EBC UEFI images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_EBC 0x0EBC
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for X64 UEFI images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_X64 0x8664
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for ARM mixed ARM and Thumb/Thumb2 images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
|
||||
|
||||
///
|
||||
/// PE32+ Machine type for AARCH64 A64 images.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_AARCH64 0xAA64
|
||||
|
||||
|
||||
#if defined (MDE_CPU_IA32)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
|
||||
(((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
|
||||
|
||||
#elif defined (MDE_CPU_IPF)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
|
||||
(((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
|
||||
|
||||
#elif defined (MDE_CPU_X64)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
|
||||
(((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
|
||||
|
||||
#elif defined (MDE_CPU_ARM)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
|
||||
(((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)
|
||||
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
|
||||
(((Machine) == EFI_IMAGE_MACHINE_AARCH64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
|
||||
|
||||
#elif defined (MDE_CPU_EBC)
|
||||
|
||||
///
|
||||
/// This is just to make sure you can cross compile with the EBC compiler.
|
||||
/// It does not make sense to have a PE loader coded in EBC.
|
||||
///
|
||||
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
|
||||
|
||||
#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
|
||||
|
||||
#else
|
||||
#error Unknown Processor Type
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,141 @@
|
|||
/** @file
|
||||
EFI Guid Partition Table Format Definition.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __UEFI_GPT_H__
|
||||
#define __UEFI_GPT_H__
|
||||
|
||||
///
|
||||
/// The primary GUID Partition Table Header must be
|
||||
/// located in LBA 1 (i.e., the second logical block).
|
||||
///
|
||||
#define PRIMARY_PART_HEADER_LBA 1
|
||||
///
|
||||
/// EFI Partition Table Signature: "EFI PART".
|
||||
///
|
||||
#define EFI_PTAB_HEADER_ID SIGNATURE_64 ('E','F','I',' ','P','A','R','T')
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
///
|
||||
/// GPT Partition Table Header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The table header for the GPT partition Table.
|
||||
/// This header contains EFI_PTAB_HEADER_ID.
|
||||
///
|
||||
EFI_TABLE_HEADER Header;
|
||||
///
|
||||
/// The LBA that contains this data structure.
|
||||
///
|
||||
EFI_LBA MyLBA;
|
||||
///
|
||||
/// LBA address of the alternate GUID Partition Table Header.
|
||||
///
|
||||
EFI_LBA AlternateLBA;
|
||||
///
|
||||
/// The first usable logical block that may be used
|
||||
/// by a partition described by a GUID Partition Entry.
|
||||
///
|
||||
EFI_LBA FirstUsableLBA;
|
||||
///
|
||||
/// The last usable logical block that may be used
|
||||
/// by a partition described by a GUID Partition Entry.
|
||||
///
|
||||
EFI_LBA LastUsableLBA;
|
||||
///
|
||||
/// GUID that can be used to uniquely identify the disk.
|
||||
///
|
||||
EFI_GUID DiskGUID;
|
||||
///
|
||||
/// The starting LBA of the GUID Partition Entry array.
|
||||
///
|
||||
EFI_LBA PartitionEntryLBA;
|
||||
///
|
||||
/// The number of Partition Entries in the GUID Partition Entry array.
|
||||
///
|
||||
UINT32 NumberOfPartitionEntries;
|
||||
///
|
||||
/// The size, in bytes, of each the GUID Partition
|
||||
/// Entry structures in the GUID Partition Entry
|
||||
/// array. This field shall be set to a value of 128 x 2^n where n is
|
||||
/// an integer greater than or equal to zero (e.g., 128, 256, 512, etc.).
|
||||
///
|
||||
UINT32 SizeOfPartitionEntry;
|
||||
///
|
||||
/// The CRC32 of the GUID Partition Entry array.
|
||||
/// Starts at PartitionEntryLBA and is
|
||||
/// computed over a byte length of
|
||||
/// NumberOfPartitionEntries * SizeOfPartitionEntry.
|
||||
///
|
||||
UINT32 PartitionEntryArrayCRC32;
|
||||
} EFI_PARTITION_TABLE_HEADER;
|
||||
|
||||
///
|
||||
/// GPT Partition Entry.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Unique ID that defines the purpose and type of this Partition. A value of
|
||||
/// zero defines that this partition entry is not being used.
|
||||
///
|
||||
EFI_GUID PartitionTypeGUID;
|
||||
///
|
||||
/// GUID that is unique for every partition entry. Every partition ever
|
||||
/// created will have a unique GUID.
|
||||
/// This GUID must be assigned when the GUID Partition Entry is created.
|
||||
///
|
||||
EFI_GUID UniquePartitionGUID;
|
||||
///
|
||||
/// Starting LBA of the partition defined by this entry
|
||||
///
|
||||
EFI_LBA StartingLBA;
|
||||
///
|
||||
/// Ending LBA of the partition defined by this entry.
|
||||
///
|
||||
EFI_LBA EndingLBA;
|
||||
///
|
||||
/// Attribute bits, all bits reserved by UEFI
|
||||
/// Bit 0: If this bit is set, the partition is required for the platform to function. The owner/creator of the
|
||||
/// partition indicates that deletion or modification of the contents can result in loss of platform
|
||||
/// features or failure for the platform to boot or operate. The system cannot function normally if
|
||||
/// this partition is removed, and it should be considered part of the hardware of the system.
|
||||
/// Actions such as running diagnostics, system recovery, or even OS install or boot, could
|
||||
/// potentially stop working if this partition is removed. Unless OS software or firmware
|
||||
/// recognizes this partition, it should never be removed or modified as the UEFI firmware or
|
||||
/// platform hardware may become non-functional.
|
||||
/// Bit 1: If this bit is set, then firmware must not produce an EFI_BLOCK_IO_PROTOCOL device for
|
||||
/// this partition. By not producing an EFI_BLOCK_IO_PROTOCOL partition, file system
|
||||
/// mappings will not be created for this partition in UEFI.
|
||||
/// Bit 2: This bit is set aside to let systems with traditional PC-AT BIOS firmware implementations
|
||||
/// inform certain limited, special-purpose software running on these systems that a GPT
|
||||
/// partition may be bootable. The UEFI boot manager must ignore this bit when selecting
|
||||
/// a UEFI-compliant application, e.g., an OS loader.
|
||||
/// Bits 3-47: Undefined and must be zero. Reserved for expansion by future versions of the UEFI
|
||||
/// specification.
|
||||
/// Bits 48-63: Reserved for GUID specific use. The use of these bits will vary depending on the
|
||||
/// PartitionTypeGUID. Only the owner of the PartitionTypeGUID is allowed
|
||||
/// to modify these bits. They must be preserved if Bits 0-47 are modified..
|
||||
///
|
||||
UINT64 Attributes;
|
||||
///
|
||||
/// Null-terminated name of the partition.
|
||||
///
|
||||
CHAR16 PartitionName[36];
|
||||
} EFI_PARTITION_ENTRY;
|
||||
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,193 @@
|
|||
/** @file
|
||||
This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __UEFI_MULTIPHASE_H__
|
||||
#define __UEFI_MULTIPHASE_H__
|
||||
|
||||
#include "efi/Guid/WinCertificate.h"
|
||||
///
|
||||
/// Enumeration of memory types introduced in UEFI.
|
||||
///
|
||||
typedef enum {
|
||||
///
|
||||
/// Not used.
|
||||
///
|
||||
EfiReservedMemoryType,
|
||||
///
|
||||
/// The code portions of a loaded application.
|
||||
/// (Note that UEFI OS loaders are UEFI applications.)
|
||||
///
|
||||
EfiLoaderCode,
|
||||
///
|
||||
/// The data portions of a loaded application and the default data allocation
|
||||
/// type used by an application to allocate pool memory.
|
||||
///
|
||||
EfiLoaderData,
|
||||
///
|
||||
/// The code portions of a loaded Boot Services Driver.
|
||||
///
|
||||
EfiBootServicesCode,
|
||||
///
|
||||
/// The data portions of a loaded Boot Serves Driver, and the default data
|
||||
/// allocation type used by a Boot Services Driver to allocate pool memory.
|
||||
///
|
||||
EfiBootServicesData,
|
||||
///
|
||||
/// The code portions of a loaded Runtime Services Driver.
|
||||
///
|
||||
EfiRuntimeServicesCode,
|
||||
///
|
||||
/// The data portions of a loaded Runtime Services Driver and the default
|
||||
/// data allocation type used by a Runtime Services Driver to allocate pool memory.
|
||||
///
|
||||
EfiRuntimeServicesData,
|
||||
///
|
||||
/// Free (unallocated) memory.
|
||||
///
|
||||
EfiConventionalMemory,
|
||||
///
|
||||
/// Memory in which errors have been detected.
|
||||
///
|
||||
EfiUnusableMemory,
|
||||
///
|
||||
/// Memory that holds the ACPI tables.
|
||||
///
|
||||
EfiACPIReclaimMemory,
|
||||
///
|
||||
/// Address space reserved for use by the firmware.
|
||||
///
|
||||
EfiACPIMemoryNVS,
|
||||
///
|
||||
/// Used by system firmware to request that a memory-mapped IO region
|
||||
/// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.
|
||||
///
|
||||
EfiMemoryMappedIO,
|
||||
///
|
||||
/// System memory-mapped IO region that is used to translate memory
|
||||
/// cycles to IO cycles by the processor.
|
||||
///
|
||||
EfiMemoryMappedIOPortSpace,
|
||||
///
|
||||
/// Address space reserved by the firmware for code that is part of the processor.
|
||||
///
|
||||
EfiPalCode,
|
||||
EfiMaxMemoryType
|
||||
} EFI_MEMORY_TYPE;
|
||||
|
||||
///
|
||||
/// Data structure that precedes all of the standard EFI table types.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// A 64-bit signature that identifies the type of table that follows.
|
||||
/// Unique signatures have been generated for the EFI System Table,
|
||||
/// the EFI Boot Services Table, and the EFI Runtime Services Table.
|
||||
///
|
||||
UINT64 Signature;
|
||||
///
|
||||
/// The revision of the EFI Specification to which this table
|
||||
/// conforms. The upper 16 bits of this field contain the major
|
||||
/// revision value, and the lower 16 bits contain the minor revision
|
||||
/// value. The minor revision values are limited to the range of 00..99.
|
||||
///
|
||||
UINT32 Revision;
|
||||
///
|
||||
/// The size, in bytes, of the entire table including the EFI_TABLE_HEADER.
|
||||
///
|
||||
UINT32 HeaderSize;
|
||||
///
|
||||
/// The 32-bit CRC for the entire table. This value is computed by
|
||||
/// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes.
|
||||
///
|
||||
UINT32 CRC32;
|
||||
///
|
||||
/// Reserved field that must be set to 0.
|
||||
///
|
||||
UINT32 Reserved;
|
||||
} EFI_TABLE_HEADER;
|
||||
|
||||
///
|
||||
/// Attributes of variable.
|
||||
///
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
|
||||
///
|
||||
/// This attribute is identified by the mnemonic 'HR'
|
||||
/// elsewhere in this specification.
|
||||
///
|
||||
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
|
||||
///
|
||||
/// Attributes of Authenticated Variable
|
||||
///
|
||||
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
|
||||
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
|
||||
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
||||
|
||||
|
||||
///
|
||||
/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
|
||||
/// WIN_CERTIFICATE_UEFI_GUID and the CertType
|
||||
/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies
|
||||
/// authenticated access, then the Data buffer should begin with an
|
||||
/// authentication descriptor prior to the data payload and DataSize
|
||||
/// should reflect the the data.and descriptor size. The caller
|
||||
/// shall digest the Monotonic Count value and the associated data
|
||||
/// for the variable update using the SHA-256 1-way hash algorithm.
|
||||
/// The ensuing the 32-byte digest will be signed using the private
|
||||
/// key associated w/ the public/private 2048-bit RSA key-pair. The
|
||||
/// WIN_CERTIFICATE shall be used to describe the signature of the
|
||||
/// Variable data *Data. In addition, the signature will also
|
||||
/// include the MonotonicCount value to guard against replay attacks.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Included in the signature of
|
||||
/// AuthInfo.Used to ensure freshness/no
|
||||
/// replay. Incremented during each
|
||||
/// "Write" access.
|
||||
///
|
||||
UINT64 MonotonicCount;
|
||||
///
|
||||
/// Provides the authorization for the variable
|
||||
/// access. It is a signature across the
|
||||
/// variable data and the Monotonic Count
|
||||
/// value. Caller uses Private key that is
|
||||
/// associated with a public key that has been
|
||||
/// provisioned via the key exchange.
|
||||
///
|
||||
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
|
||||
} EFI_VARIABLE_AUTHENTICATION;
|
||||
|
||||
///
|
||||
/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
|
||||
/// set, then the Data buffer shall begin with an instance of a complete (and serialized)
|
||||
/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
|
||||
/// variable value and DataSize shall reflect the combined size of the descriptor and the new
|
||||
/// variable value. The authentication descriptor is not part of the variable data and is not
|
||||
/// returned by subsequent calls to GetVariable().
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and
|
||||
/// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT.
|
||||
///
|
||||
EFI_TIME TimeStamp;
|
||||
///
|
||||
/// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted.
|
||||
///
|
||||
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
|
||||
} EFI_VARIABLE_AUTHENTICATION_2;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,294 @@
|
|||
/** @file
|
||||
Processor or Compiler specific defines and types x64 (Intel 64, AMD64).
|
||||
|
||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PROCESSOR_BIND_H__
|
||||
#define __PROCESSOR_BIND_H__
|
||||
|
||||
///
|
||||
/// Define the processor type so other code can make processor based choices
|
||||
///
|
||||
#define MDE_CPU_X64
|
||||
|
||||
//
|
||||
// Make sure we are using the correct packing rules per EFI specification
|
||||
//
|
||||
#if !defined(__GNUC__)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
//
|
||||
// Disable ICC's remark #869: "Parameter" was never referenced warning.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with -Wall
|
||||
//
|
||||
#pragma warning ( disable : 869 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #1418: external function definition with no prior declaration.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 1418 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #1419: external declaration in primary source file
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 1419 )
|
||||
|
||||
//
|
||||
// Disable ICC's remark #593: "Variable" was set but never used.
|
||||
// This is legal ANSI C code so we disable the remark that is turned on with /W4
|
||||
//
|
||||
#pragma warning ( disable : 593 )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
|
||||
//
|
||||
// Disable warning that make it impossible to compile at /W4
|
||||
// This only works for Microsoft* tools
|
||||
//
|
||||
|
||||
//
|
||||
// Disabling bitfield type checking warnings.
|
||||
//
|
||||
#pragma warning ( disable : 4214 )
|
||||
|
||||
//
|
||||
// Disabling the unreferenced formal parameter warnings.
|
||||
//
|
||||
#pragma warning ( disable : 4100 )
|
||||
|
||||
//
|
||||
// Disable slightly different base types warning as CHAR8 * can not be set
|
||||
// to a constant string.
|
||||
//
|
||||
#pragma warning ( disable : 4057 )
|
||||
|
||||
//
|
||||
// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
|
||||
//
|
||||
#pragma warning ( disable : 4127 )
|
||||
|
||||
//
|
||||
// This warning is caused by functions defined but not used. For precompiled header only.
|
||||
//
|
||||
#pragma warning ( disable : 4505 )
|
||||
|
||||
//
|
||||
// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
|
||||
//
|
||||
#pragma warning ( disable : 4206 )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
//
|
||||
// use Microsoft C complier dependent integer width types
|
||||
//
|
||||
|
||||
///
|
||||
/// 8-byte unsigned value
|
||||
///
|
||||
typedef unsigned __int64 UINT64;
|
||||
///
|
||||
/// 8-byte signed value
|
||||
///
|
||||
typedef __int64 INT64;
|
||||
///
|
||||
/// 4-byte unsigned value
|
||||
///
|
||||
typedef unsigned __int32 UINT32;
|
||||
///
|
||||
/// 4-byte signed value
|
||||
///
|
||||
typedef __int32 INT32;
|
||||
///
|
||||
/// 2-byte unsigned value
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#else
|
||||
///
|
||||
/// 8-byte unsigned value
|
||||
///
|
||||
typedef unsigned long long UINT64;
|
||||
///
|
||||
/// 8-byte signed value
|
||||
///
|
||||
typedef long long INT64;
|
||||
///
|
||||
/// 4-byte unsigned value
|
||||
///
|
||||
typedef unsigned int UINT32;
|
||||
///
|
||||
/// 4-byte signed value
|
||||
///
|
||||
typedef int INT32;
|
||||
///
|
||||
/// 2-byte unsigned value
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
|
||||
/// 8 bytes on supported 64-bit processor instructions)
|
||||
///
|
||||
typedef UINT64 UINTN;
|
||||
///
|
||||
/// Signed value of native width. (4 bytes on supported 32-bit processor instructions,
|
||||
/// 8 bytes on supported 64-bit processor instructions)
|
||||
///
|
||||
typedef INT64 INTN;
|
||||
|
||||
|
||||
//
|
||||
// Processor specific defines
|
||||
//
|
||||
|
||||
///
|
||||
/// A value of native width with the highest bit set.
|
||||
///
|
||||
#define MAX_BIT 0x8000000000000000ULL
|
||||
///
|
||||
/// A value of native width with the two highest bits set.
|
||||
///
|
||||
#define MAX_2_BITS 0xC000000000000000ULL
|
||||
|
||||
///
|
||||
/// Maximum legal x64 address
|
||||
///
|
||||
#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
|
||||
|
||||
///
|
||||
/// Maximum legal x64 INTN and UINTN values.
|
||||
///
|
||||
#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
|
||||
#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
|
||||
|
||||
///
|
||||
/// The stack alignment required for x64
|
||||
///
|
||||
#define CPU_STACK_ALIGNMENT 16
|
||||
|
||||
//
|
||||
// Modifier to ensure that all protocol member functions and EFI intrinsics
|
||||
// use the correct C calling convention. All protocol member functions and
|
||||
// EFI intrinsics are required to modify their member functions with EFIAPI.
|
||||
//
|
||||
#ifdef EFIAPI
|
||||
///
|
||||
/// If EFIAPI is already defined, then we use that definition.
|
||||
///
|
||||
#elif defined(_MSC_EXTENSIONS)
|
||||
///
|
||||
/// Microsoft* compiler specific method for EFIAPI calling convension
|
||||
///
|
||||
#define EFIAPI __cdecl
|
||||
#elif defined(__GNUC__)
|
||||
///
|
||||
/// Define the standard calling convention reguardless of optimization level.
|
||||
/// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI
|
||||
/// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64)
|
||||
/// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for
|
||||
/// x64. Warning the assembly code in the MDE x64 does not follow the correct
|
||||
/// ABI for the standard x64 (x86-64) GCC.
|
||||
///
|
||||
#define EFIAPI
|
||||
#else
|
||||
///
|
||||
/// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI
|
||||
/// is the standard.
|
||||
///
|
||||
#define EFIAPI
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
///
|
||||
/// For GNU assembly code, .global or .globl can declare global symbols.
|
||||
/// Define this macro to unify the usage.
|
||||
///
|
||||
#define ASM_GLOBAL .globl
|
||||
#endif
|
||||
|
||||
/**
|
||||
Return the pointer to the first instruction of a function given a function pointer.
|
||||
On x64 CPU architectures, these two pointer values are the same,
|
||||
so the implementation of this macro is very simple.
|
||||
|
||||
@param FunctionPointer A pointer to a function.
|
||||
|
||||
@return The pointer to the first instruction of a function given a function pointer.
|
||||
|
||||
**/
|
||||
#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
=head1 NAME
|
||||
|
||||
import.pl
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
import.pl [options] /path/to/edk2/edk2
|
||||
|
||||
Options:
|
||||
|
||||
-h,--help Display brief help message
|
||||
-v,--verbose Increase verbosity
|
||||
-q,--quiet Decrease verbosity
|
||||
|
||||
=cut
|
||||
|
||||
use File::Spec::Functions qw ( :ALL );
|
||||
use File::Find;
|
||||
use File::Path;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use FindBin;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $verbosity = 0;
|
||||
|
||||
sub try_import_file {
|
||||
my $wimbootdir = shift;
|
||||
my $edktop = shift;
|
||||
my $edkdirs = shift;
|
||||
my $filename = shift;
|
||||
|
||||
# Skip everything except headers
|
||||
return unless $filename =~ /\.h$/;
|
||||
|
||||
# Skip files that are wimboot native headers
|
||||
my $outfile = catfile ( $wimbootdir, $filename );
|
||||
if ( -s $outfile ) {
|
||||
open my $outfh, "<$outfile" or die "Could not open $outfile: $!\n";
|
||||
my $line = <$outfh>;
|
||||
close $outfh;
|
||||
chomp $line;
|
||||
return if $line =~ /^\#ifndef\s+_WIMBOOT_\S+_H$/;
|
||||
}
|
||||
|
||||
# Search for importable header
|
||||
foreach my $edkdir ( @$edkdirs ) {
|
||||
my $infile = catfile ( $edktop, $edkdir, $filename );
|
||||
if ( -e $infile ) {
|
||||
# We have found a matching source file - import it
|
||||
print "$filename <- ".catfile ( $edkdir, $filename )."\n"
|
||||
if $verbosity >= 1;
|
||||
open my $infh, "<$infile" or die "Could not open $infile: $!\n";
|
||||
( undef, my $outdir, undef ) = splitpath ( $outfile );
|
||||
mkpath ( $outdir );
|
||||
open my $outfh, ">$outfile" or die "Could not open $outfile: $!\n";
|
||||
my @dependencies = ();
|
||||
while ( <$infh> ) {
|
||||
# Strip CR and trailing whitespace
|
||||
s/\r//g;
|
||||
s/\s*$//g;
|
||||
chomp;
|
||||
# Update include lines, and record included files
|
||||
if ( s/^\#include\s+[<\"](\S+)[>\"]/\#include "efi\/$1"/ ) {
|
||||
push @dependencies, $1;
|
||||
}
|
||||
# Write out line
|
||||
print $outfh "$_\n";
|
||||
}
|
||||
close $outfh;
|
||||
close $infh;
|
||||
# Recurse to handle any included files that we don't already have
|
||||
foreach my $dependency ( @dependencies ) {
|
||||
if ( ! -e catfile ( $wimbootdir, $dependency ) ) {
|
||||
print "...following dependency on $dependency\n" if $verbosity >= 1;
|
||||
try_import_file ( $wimbootdir, $edktop, $edkdirs, $dependency );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
die "$filename has no equivalent in $edktop\n";
|
||||
}
|
||||
|
||||
# Parse command-line options
|
||||
Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
|
||||
GetOptions (
|
||||
'verbose|v+' => sub { $verbosity++; },
|
||||
'quiet|q+' => sub { $verbosity--; },
|
||||
'help|h' => sub { pod2usage ( 1 ); },
|
||||
) or die "Could not parse command-line options\n";
|
||||
pod2usage ( 1 ) unless @ARGV == 1;
|
||||
my $edktop = shift;
|
||||
|
||||
# Identify edk import directories
|
||||
my $edkdirs = [ "MdePkg/Include", "IntelFrameworkPkg/Include",
|
||||
"MdeModulePkg/Include", "EdkCompatibilityPkg/Foundation" ];
|
||||
foreach my $edkdir ( @$edkdirs ) {
|
||||
die "Directory \"$edktop\" does not appear to contain the EFI EDK2 "
|
||||
."(missing \"$edkdir\")\n" unless -d catdir ( $edktop, $edkdir );
|
||||
}
|
||||
|
||||
# Identify wimboot EFI includes directory
|
||||
my $wimbootdir = $FindBin::Bin;
|
||||
die "Directory \"$wimbootdir\" does not contain the wimboot EFI includes\n"
|
||||
unless -e catfile ( $wimbootdir, "../wimboot.h" );
|
||||
|
||||
if ( $verbosity >= 1 ) {
|
||||
print "Importing EFI headers into $wimbootdir\nfrom ";
|
||||
print join ( "\n and ", map { catdir ( $edktop, $_ ) } @$edkdirs )."\n";
|
||||
}
|
||||
|
||||
# Import headers
|
||||
find ( { wanted => sub {
|
||||
try_import_file ( $wimbootdir, $edktop, $edkdirs,
|
||||
abs2rel ( $_, $wimbootdir ) );
|
||||
}, no_chdir => 1 }, $wimbootdir );
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI block device
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "vdisk.h"
|
||||
#include "efi.h"
|
||||
#include "efipath.h"
|
||||
#include "efiblock.h"
|
||||
|
||||
/** A block I/O device */
|
||||
struct efi_block {
|
||||
/** EFI block I/O protocol */
|
||||
EFI_BLOCK_IO_PROTOCOL block;
|
||||
/** Device path */
|
||||
EFI_DEVICE_PATH_PROTOCOL *path;
|
||||
/** Starting LBA */
|
||||
uint64_t lba;
|
||||
/** Name */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset block I/O protocol
|
||||
*
|
||||
* @v this Block I/O protocol
|
||||
* @v extended Perform extended verification
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_reset_blocks ( EFI_BLOCK_IO_PROTOCOL *this, BOOLEAN extended ) {
|
||||
struct efi_block *block =
|
||||
container_of ( this, struct efi_block, block );
|
||||
void *retaddr = __builtin_return_address ( 0 );
|
||||
|
||||
DBG2 ( "EFI %s %sreset -> %p\n",
|
||||
block->name, ( extended ? "extended " : "" ), retaddr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read blocks
|
||||
*
|
||||
* @v this Block I/O protocol
|
||||
* @v media Media ID
|
||||
* @v lba Starting LBA
|
||||
* @v len Length of data
|
||||
* @v data Data buffer
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this, UINT32 media, EFI_LBA lba,
|
||||
UINTN len, VOID *data ) {
|
||||
struct efi_block *block =
|
||||
container_of ( this, struct efi_block, block );
|
||||
void *retaddr = __builtin_return_address ( 0 );
|
||||
|
||||
DBG2 ( "EFI %s read media %08x LBA %#llx to %p+%zx -> %p\n",
|
||||
block->name, media, lba, data, ( ( size_t ) len ), retaddr );
|
||||
vdisk_read ( ( lba + block->lba ), ( len / VDISK_SECTOR_SIZE ), data );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write blocks
|
||||
*
|
||||
* @v this Block I/O protocol
|
||||
* @v media Media ID
|
||||
* @v lba Starting LBA
|
||||
* @v len Length of data
|
||||
* @v data Data buffer
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
|
||||
UINT32 media __unused, EFI_LBA lba __unused,
|
||||
UINTN len __unused, VOID *data __unused ) {
|
||||
struct efi_block *block =
|
||||
container_of ( this, struct efi_block, block );
|
||||
void *retaddr = __builtin_return_address ( 0 );
|
||||
|
||||
DBG2 ( "EFI %s write media %08x LBA %#llx from %p+%zx -> %p\n",
|
||||
block->name, media, lba, data, ( ( size_t ) len ), retaddr );
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush block operations
|
||||
*
|
||||
* @v this Block I/O protocol
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_flush_blocks ( EFI_BLOCK_IO_PROTOCOL *this ) {
|
||||
struct efi_block *block =
|
||||
container_of ( this, struct efi_block, block );
|
||||
void *retaddr = __builtin_return_address ( 0 );
|
||||
|
||||
DBG2 ( "EFI %s flush -> %p\n", block->name, retaddr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** GUID used in vendor device path */
|
||||
#define EFIBLOCK_GUID { \
|
||||
0x1322d197, 0x15dc, 0x4a45, \
|
||||
{ 0xa6, 0xa4, 0xfa, 0x57, 0x05, 0x4e, 0xa6, 0x14 } \
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise vendor device path
|
||||
*
|
||||
* @v name Variable name
|
||||
*/
|
||||
#define EFIBLOCK_DEVPATH_VENDOR_INIT( name ) { \
|
||||
.Header = EFI_DEVPATH_INIT ( name, HARDWARE_DEVICE_PATH, \
|
||||
HW_VENDOR_DP ), \
|
||||
.Guid = EFIBLOCK_GUID, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise ATA device path
|
||||
*
|
||||
* @v name Variable name
|
||||
*/
|
||||
#define EFIBLOCK_DEVPATH_ATA_INIT( name ) { \
|
||||
.Header = EFI_DEVPATH_INIT ( name, MESSAGING_DEVICE_PATH, \
|
||||
MSG_ATAPI_DP ), \
|
||||
.PrimarySecondary = 0, \
|
||||
.SlaveMaster = 0, \
|
||||
.Lun = 0, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise hard disk device path
|
||||
*
|
||||
* @v name Variable name
|
||||
*/
|
||||
#define EFIBLOCK_DEVPATH_HD_INIT( name ) { \
|
||||
.Header = EFI_DEVPATH_INIT ( name, MEDIA_DEVICE_PATH, \
|
||||
MEDIA_HARDDRIVE_DP ), \
|
||||
.PartitionNumber = 1, \
|
||||
.PartitionStart = VDISK_PARTITION_LBA, \
|
||||
.PartitionSize = VDISK_PARTITION_COUNT, \
|
||||
.Signature[0] = ( ( VDISK_MBR_SIGNATURE >> 0 ) & 0xff ), \
|
||||
.Signature[1] = ( ( VDISK_MBR_SIGNATURE >> 8 ) & 0xff ), \
|
||||
.Signature[2] = ( ( VDISK_MBR_SIGNATURE >> 16 ) & 0xff ), \
|
||||
.Signature[3] = ( ( VDISK_MBR_SIGNATURE >> 24 ) & 0xff ), \
|
||||
.MBRType = MBR_TYPE_PCAT, \
|
||||
.SignatureType = SIGNATURE_TYPE_MBR, \
|
||||
}
|
||||
|
||||
/** Virtual disk media */
|
||||
static EFI_BLOCK_IO_MEDIA efi_vdisk_media = {
|
||||
.MediaId = VDISK_MBR_SIGNATURE,
|
||||
.MediaPresent = TRUE,
|
||||
.LogicalPartition = FALSE,
|
||||
.ReadOnly = TRUE,
|
||||
.BlockSize = VDISK_SECTOR_SIZE,
|
||||
.LastBlock = ( VDISK_COUNT - 1 ),
|
||||
};
|
||||
|
||||
/** Virtual disk device path */
|
||||
static struct {
|
||||
VENDOR_DEVICE_PATH vendor;
|
||||
ATAPI_DEVICE_PATH ata;
|
||||
EFI_DEVICE_PATH_PROTOCOL end;
|
||||
} __attribute__ (( packed )) efi_vdisk_path = {
|
||||
.vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_vdisk_path.vendor ),
|
||||
.ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_vdisk_path.ata ),
|
||||
.end = EFI_DEVPATH_END_INIT ( efi_vdisk_path.end ),
|
||||
};
|
||||
|
||||
/** Virtual disk device */
|
||||
static struct efi_block efi_vdisk = {
|
||||
.block = {
|
||||
.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION,
|
||||
.Media = &efi_vdisk_media,
|
||||
.Reset = efi_reset_blocks,
|
||||
.ReadBlocks = efi_read_blocks,
|
||||
.WriteBlocks = efi_write_blocks,
|
||||
.FlushBlocks = efi_flush_blocks,
|
||||
},
|
||||
.path = &efi_vdisk_path.vendor.Header,
|
||||
.lba = 0,
|
||||
.name = "vdisk",
|
||||
};
|
||||
|
||||
/** Virtual partition media */
|
||||
static EFI_BLOCK_IO_MEDIA efi_vpartition_media = {
|
||||
.MediaId = VDISK_MBR_SIGNATURE,
|
||||
.MediaPresent = TRUE,
|
||||
.LogicalPartition = TRUE,
|
||||
.ReadOnly = TRUE,
|
||||
.BlockSize = VDISK_SECTOR_SIZE,
|
||||
.LastBlock = ( VDISK_PARTITION_COUNT - 1 ),
|
||||
};
|
||||
|
||||
/** Virtual partition device path */
|
||||
static struct {
|
||||
VENDOR_DEVICE_PATH vendor;
|
||||
ATAPI_DEVICE_PATH ata;
|
||||
HARDDRIVE_DEVICE_PATH hd;
|
||||
EFI_DEVICE_PATH_PROTOCOL end;
|
||||
} __attribute__ (( packed )) efi_vpartition_path = {
|
||||
.vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_vpartition_path.vendor ),
|
||||
.ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_vpartition_path.ata ),
|
||||
.hd = EFIBLOCK_DEVPATH_HD_INIT ( efi_vpartition_path.hd ),
|
||||
.end = EFI_DEVPATH_END_INIT ( efi_vpartition_path.end ),
|
||||
};
|
||||
|
||||
/** Virtual partition device */
|
||||
static struct efi_block efi_vpartition = {
|
||||
.block = {
|
||||
.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION,
|
||||
.Media = &efi_vpartition_media,
|
||||
.Reset = efi_reset_blocks,
|
||||
.ReadBlocks = efi_read_blocks,
|
||||
.WriteBlocks = efi_write_blocks,
|
||||
.FlushBlocks = efi_flush_blocks,
|
||||
},
|
||||
.path = &efi_vpartition_path.vendor.Header,
|
||||
.lba = VDISK_PARTITION_LBA,
|
||||
.name = "vpartition",
|
||||
};
|
||||
|
||||
/**
|
||||
* Install block I/O protocols
|
||||
*
|
||||
* @ret vdisk New virtual disk handle
|
||||
* @ret vpartition New virtual partition handle
|
||||
*/
|
||||
void efi_install ( EFI_HANDLE *vdisk, EFI_HANDLE *vpartition ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Install virtual disk */
|
||||
if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
||||
vdisk,
|
||||
&efi_block_io_protocol_guid, &efi_vdisk.block,
|
||||
&efi_device_path_protocol_guid, efi_vdisk.path,
|
||||
NULL ) ) != 0 ) {
|
||||
die ( "Could not install disk block I/O protocols: %#lx\n",
|
||||
( ( unsigned long ) efirc ) );
|
||||
}
|
||||
|
||||
/* Install virtual partition */
|
||||
if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
||||
vpartition,
|
||||
&efi_block_io_protocol_guid, &efi_vpartition.block,
|
||||
&efi_device_path_protocol_guid, efi_vpartition.path,
|
||||
NULL ) ) != 0 ) {
|
||||
die ( "Could not install partition block I/O protocols: %#lx\n",
|
||||
( ( unsigned long ) efirc ) );
|
||||
}
|
||||
}
|
||||
|
||||
/** Boot image path */
|
||||
static struct {
|
||||
VENDOR_DEVICE_PATH vendor;
|
||||
ATAPI_DEVICE_PATH ata;
|
||||
HARDDRIVE_DEVICE_PATH hd;
|
||||
struct {
|
||||
EFI_DEVICE_PATH header;
|
||||
CHAR16 name[ sizeof ( EFI_REMOVABLE_MEDIA_FILE_NAME ) /
|
||||
sizeof ( CHAR16 ) ];
|
||||
} __attribute__ (( packed )) file;
|
||||
EFI_DEVICE_PATH_PROTOCOL end;
|
||||
} __attribute__ (( packed )) efi_bootmgfw_path = {
|
||||
.vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_bootmgfw_path.vendor ),
|
||||
.ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_bootmgfw_path.ata ),
|
||||
.hd = EFIBLOCK_DEVPATH_HD_INIT ( efi_bootmgfw_path.hd ),
|
||||
.file = {
|
||||
.header = EFI_DEVPATH_INIT ( efi_bootmgfw_path.file,
|
||||
MEDIA_DEVICE_PATH,
|
||||
MEDIA_FILEPATH_DP ),
|
||||
.name = EFI_REMOVABLE_MEDIA_FILE_NAME,
|
||||
},
|
||||
.end = EFI_DEVPATH_END_INIT ( efi_bootmgfw_path.end ),
|
||||
};
|
||||
|
||||
/** Boot image path */
|
||||
EFI_DEVICE_PATH_PROTOCOL *bootmgfw_path = &efi_bootmgfw_path.vendor.Header;
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _EFIBLOCK_H
|
||||
#define _EFIBLOCK_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI block device
|
||||
*
|
||||
*/
|
||||
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/BlockIo.h"
|
||||
#include "efi/Protocol/DevicePath.h"
|
||||
|
||||
extern void efi_install ( EFI_HANDLE *vdisk, EFI_HANDLE *vpartition );
|
||||
|
||||
extern EFI_DEVICE_PATH_PROTOCOL *bootmgfw_path;
|
||||
|
||||
#endif /* _EFIBLOCK_H */
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI boot manager invocation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "wimboot.h"
|
||||
#include "cmdline.h"
|
||||
#include "vdisk.h"
|
||||
#include "pause.h"
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/GraphicsOutput.h"
|
||||
#include "efipath.h"
|
||||
#include "efiboot.h"
|
||||
|
||||
/** Original OpenProtocol() method */
|
||||
static EFI_OPEN_PROTOCOL orig_open_protocol;
|
||||
|
||||
/**
|
||||
* Intercept OpenProtocol()
|
||||
*
|
||||
* @v handle EFI handle
|
||||
* @v protocol Protocol GUID
|
||||
* @v interface Opened interface
|
||||
* @v agent_handle Agent handle
|
||||
* @v controller_handle Controller handle
|
||||
* @v attributes Attributes
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_open_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
|
||||
VOID **interface, EFI_HANDLE agent_handle,
|
||||
EFI_HANDLE controller_handle, UINT32 attributes ) {
|
||||
static unsigned int count;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Open the protocol */
|
||||
if ( ( efirc = orig_open_protocol ( handle, protocol, interface,
|
||||
agent_handle, controller_handle,
|
||||
attributes ) ) != 0 ) {
|
||||
return efirc;
|
||||
}
|
||||
|
||||
/* Block first attempt by bootmgfw.efi to open
|
||||
* EFI_GRAPHICS_OUTPUT_PROTOCOL. This forces error messages
|
||||
* to be displayed in text mode (thereby avoiding the totally
|
||||
* blank error screen if the fonts are missing). We must
|
||||
* allow subsequent attempts to succeed, otherwise the OS will
|
||||
* fail to boot.
|
||||
*/
|
||||
if ( ( memcmp ( protocol, &efi_graphics_output_protocol_guid,
|
||||
sizeof ( *protocol ) ) == 0 ) &&
|
||||
( count++ == 0 ) && ( ! cmdline_gui ) ) {
|
||||
DBG ( "Forcing text mode output\n" );
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot from EFI device
|
||||
*
|
||||
* @v file Virtual file
|
||||
* @v path Device path
|
||||
* @v device Device handle
|
||||
*/
|
||||
void efi_boot ( struct vdisk_file *file, EFI_DEVICE_PATH_PROTOCOL *path,
|
||||
EFI_HANDLE device ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
union {
|
||||
EFI_LOADED_IMAGE_PROTOCOL *image;
|
||||
void *intf;
|
||||
} loaded;
|
||||
EFI_PHYSICAL_ADDRESS phys;
|
||||
void *data;
|
||||
unsigned int pages;
|
||||
EFI_HANDLE handle;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Allocate memory */
|
||||
pages = ( ( file->len + PAGE_SIZE - 1 ) / PAGE_SIZE );
|
||||
if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
|
||||
EfiBootServicesData, pages,
|
||||
&phys ) ) != 0 ) {
|
||||
die ( "Could not allocate %d pages: %#lx\n",
|
||||
pages, ( ( unsigned long ) efirc ) );
|
||||
}
|
||||
data = ( ( void * ) ( intptr_t ) phys );
|
||||
|
||||
|
||||
/* Read image */
|
||||
file->read ( file, data, 0, file->len );
|
||||
DBG ( "Read %s\n", file->name );
|
||||
|
||||
/* Load image */
|
||||
if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path, data,
|
||||
file->len, &handle ) ) != 0 ) {
|
||||
die ( "Could not load %s: %#lx\n",
|
||||
file->name, ( ( unsigned long ) efirc ) );
|
||||
}
|
||||
DBG ( "Loaded %s\n", file->name );
|
||||
|
||||
/* Get loaded image protocol */
|
||||
if ( ( efirc = bs->OpenProtocol ( handle,
|
||||
&efi_loaded_image_protocol_guid,
|
||||
&loaded.intf, efi_image_handle, NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
|
||||
die ( "Could not get loaded image protocol for %s: %#lx\n",
|
||||
file->name, ( ( unsigned long ) efirc ) );
|
||||
}
|
||||
|
||||
/* Force correct device handle */
|
||||
if ( loaded.image->DeviceHandle != device ) {
|
||||
DBG ( "Forcing correct DeviceHandle (%p->%p)\n",
|
||||
loaded.image->DeviceHandle, device );
|
||||
loaded.image->DeviceHandle = device;
|
||||
}
|
||||
|
||||
/* Intercept calls to OpenProtocol() */
|
||||
orig_open_protocol =
|
||||
loaded.image->SystemTable->BootServices->OpenProtocol;
|
||||
loaded.image->SystemTable->BootServices->OpenProtocol =
|
||||
efi_open_protocol_wrapper;
|
||||
|
||||
/* Start image */
|
||||
if ( cmdline_pause )
|
||||
pause();
|
||||
if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
|
||||
die ( "Could not start %s: %#lx\n",
|
||||
file->name, ( ( unsigned long ) efirc ) );
|
||||
}
|
||||
|
||||
die ( "%s returned\n", file->name );
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _EFIBOOT_H
|
||||
#define _EFIBOOT_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI boot manager invocation
|
||||
*
|
||||
*/
|
||||
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/DevicePath.h"
|
||||
|
||||
struct vdisk_file;
|
||||
|
||||
extern void efi_boot ( struct vdisk_file *file, EFI_DEVICE_PATH_PROTOCOL *path,
|
||||
EFI_HANDLE device );
|
||||
|
||||
#endif /* _EFIBOOT_H */
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI file system access
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <wchar.h>
|
||||
#include "wimboot.h"
|
||||
#include "vdisk.h"
|
||||
#include "cmdline.h"
|
||||
#include "wimpatch.h"
|
||||
#include "wimfile.h"
|
||||
#include "efi.h"
|
||||
#include "efifile.h"
|
||||
|
||||
/** bootmgfw.efi path within WIM */
|
||||
static const wchar_t bootmgfw_path[] = L"\\Windows\\Boot\\EFI\\bootmgfw.efi";
|
||||
|
||||
/** Other paths within WIM */
|
||||
static const wchar_t *efi_wim_paths[] = {
|
||||
L"\\Windows\\Boot\\DVD\\EFI\\boot.sdi",
|
||||
L"\\Windows\\Boot\\DVD\\EFI\\BCD",
|
||||
L"\\Windows\\Boot\\Fonts\\segmono_boot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\segoen_slboot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\segoe_slboot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\wgl4_boot.ttf",
|
||||
L"\\sms\\boot\\boot.sdi",
|
||||
NULL
|
||||
};
|
||||
|
||||
/** bootmgfw.efi file */
|
||||
struct vdisk_file *bootmgfw;
|
||||
|
||||
/**
|
||||
* Get architecture-specific boot filename
|
||||
*
|
||||
* @ret bootarch Architecture-specific boot filename
|
||||
*/
|
||||
static const CHAR16 * efi_bootarch ( void ) {
|
||||
static const CHAR16 bootarch_full[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
|
||||
const CHAR16 *tmp;
|
||||
const CHAR16 *bootarch = bootarch_full;
|
||||
|
||||
for ( tmp = bootarch_full ; *tmp ; tmp++ ) {
|
||||
if ( *tmp == L'\\' )
|
||||
bootarch = ( tmp + 1 );
|
||||
}
|
||||
return bootarch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from EFI file
|
||||
*
|
||||
* @v vfile Virtual file
|
||||
* @v data Data buffer
|
||||
* @v offset Offset
|
||||
* @v len Length
|
||||
*/
|
||||
static void efi_read_file ( struct vdisk_file *vfile, void *data,
|
||||
size_t offset, size_t len ) {
|
||||
#if 0
|
||||
EFI_FILE_PROTOCOL *file = vfile->opaque;
|
||||
UINTN size = len;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Set file position */
|
||||
if ( ( efirc = file->SetPosition ( file, offset ) ) != 0 ) {
|
||||
die ( "Could not set file position: %#lx\n",
|
||||
( ( unsigned long ) efirc ) );
|
||||
}
|
||||
|
||||
/* Read from file */
|
||||
if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
|
||||
die ( "Could not read from file: %#lx\n",
|
||||
( ( unsigned long ) efirc ) );
|
||||
}
|
||||
#endif /* #if 0 */
|
||||
|
||||
(void)vfile;
|
||||
|
||||
pfventoy_file_read((const char *)vfile->opaque, (int)offset, (int)len, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch BCD file
|
||||
*
|
||||
* @v vfile Virtual file
|
||||
* @v data Data buffer
|
||||
* @v offset Offset
|
||||
* @v len Length
|
||||
*/
|
||||
static void efi_patch_bcd ( struct vdisk_file *vfile __unused, void *data,
|
||||
size_t offset, size_t len ) {
|
||||
static const wchar_t search[] = L".exe";
|
||||
static const wchar_t replace[] = L".efi";
|
||||
size_t i;
|
||||
|
||||
/* Do nothing if BCD patching is disabled */
|
||||
if ( cmdline_rawbcd )
|
||||
return;
|
||||
|
||||
/* Patch any occurrences of ".exe" to ".efi". In the common
|
||||
* simple cases, this allows the same BCD file to be used for
|
||||
* both BIOS and UEFI systems.
|
||||
*/
|
||||
for ( i = 0 ; ( i + sizeof ( search ) ) < len ; i++ ) {
|
||||
if ( wcscasecmp ( ( data + i ), search ) == 0 ) {
|
||||
memcpy ( ( data + i ), replace, sizeof ( replace ) );
|
||||
DBG ( "...patched BCD at %#zx: \"%ls\" to \"%ls\"\n",
|
||||
( offset + i ), search, replace );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract files from EFI file system
|
||||
*
|
||||
* @v handle Device handle
|
||||
*/
|
||||
void efi_extract ( EFI_HANDLE handle ) {
|
||||
struct vdisk_file *wim = NULL;
|
||||
struct vdisk_file *vfile;
|
||||
CHAR16 wname[64];
|
||||
int i, j, k;
|
||||
char *pos;
|
||||
size_t len = 0;
|
||||
|
||||
(void)handle;
|
||||
|
||||
/* Read root directory */
|
||||
for (i = 0; i < cmdline_vf_num; i++) {
|
||||
pos = strchr(cmdline_vf_path[i], ':');
|
||||
|
||||
*pos = 0;
|
||||
k = (int)strlen(cmdline_vf_path[i]);
|
||||
|
||||
memset(wname, 0, sizeof(wname));
|
||||
for (j = 0; j < k; j++)
|
||||
{
|
||||
wname[j] = cmdline_vf_path[i][j];
|
||||
}
|
||||
|
||||
len = pfventoy_file_size(pos + 1);
|
||||
vfile = vdisk_add_file (cmdline_vf_path[i], pos + 1, len, efi_read_file);
|
||||
|
||||
/* Check for special-case files */
|
||||
if ( ( wcscasecmp ( wname, efi_bootarch() ) == 0 ) ||
|
||||
( wcscasecmp ( wname, L"bootmgfw.efi" ) == 0 ) ) {
|
||||
DBG ( "...found bootmgfw.efi file %ls\n", wname );
|
||||
bootmgfw = vfile;
|
||||
} else if ( wcscasecmp ( wname, L"BCD" ) == 0 ) {
|
||||
DBG ( "...found BCD\n" );
|
||||
vdisk_patch_file ( vfile, efi_patch_bcd );
|
||||
} else if ( wcscasecmp ( ( wname + ( wcslen ( wname ) - 4 ) ),
|
||||
L".wim" ) == 0 ) {
|
||||
DBG ( "...found WIM file %ls\n", wname );
|
||||
wim = vfile;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process WIM image */
|
||||
if ( wim ) {
|
||||
vdisk_patch_file ( wim, patch_wim );
|
||||
if ( ( ! bootmgfw ) &&
|
||||
( bootmgfw = wim_add_file ( wim, cmdline_index,
|
||||
bootmgfw_path,
|
||||
efi_bootarch() ) ) ) {
|
||||
DBG ( "...extracted %ls\n", bootmgfw_path );
|
||||
}
|
||||
wim_add_files ( wim, cmdline_index, efi_wim_paths );
|
||||
}
|
||||
|
||||
/* Check that we have a boot file */
|
||||
if ( ! bootmgfw ) {
|
||||
die ( "FATAL: no %ls or bootmgfw.efi found\n",
|
||||
efi_bootarch() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _EFIFILE_H
|
||||
#define _EFIFILE_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI file system access
|
||||
*
|
||||
*/
|
||||
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/SimpleFileSystem.h"
|
||||
#include "efi/Guid/FileInfo.h"
|
||||
|
||||
struct vdisk_file;
|
||||
|
||||
extern struct vdisk_file *bootmgfw;
|
||||
extern void efi_extract ( EFI_HANDLE handle );
|
||||
|
||||
#endif /* _EFIFILE_H */
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI GUIDs
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/BlockIo.h"
|
||||
#include "efi/Protocol/DevicePath.h"
|
||||
#include "efi/Protocol/GraphicsOutput.h"
|
||||
#include "efi/Protocol/LoadedImage.h"
|
||||
#include "efi/Protocol/SimpleFileSystem.h"
|
||||
|
||||
/** Block I/O protocol GUID */
|
||||
EFI_GUID efi_block_io_protocol_guid
|
||||
= EFI_BLOCK_IO_PROTOCOL_GUID;
|
||||
|
||||
/** Device path protocol GUID */
|
||||
EFI_GUID efi_device_path_protocol_guid
|
||||
= EFI_DEVICE_PATH_PROTOCOL_GUID;
|
||||
|
||||
/** Graphics output protocol GUID */
|
||||
EFI_GUID efi_graphics_output_protocol_guid
|
||||
= EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
|
||||
/** Loaded image protocol GUID */
|
||||
EFI_GUID efi_loaded_image_protocol_guid
|
||||
= EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
|
||||
/** Simple file system protocol GUID */
|
||||
EFI_GUID efi_simple_file_system_protocol_guid
|
||||
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI entry point
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "cmdline.h"
|
||||
#include "efi.h"
|
||||
#include "efifile.h"
|
||||
#include "efiblock.h"
|
||||
#include "efiboot.h"
|
||||
|
||||
/**
|
||||
* Process command line
|
||||
*
|
||||
* @v loaded Loaded image protocol
|
||||
*/
|
||||
static void efi_cmdline ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
|
||||
size_t cmdline_len = ( loaded->LoadOptionsSize / sizeof ( wchar_t ) );
|
||||
char cmdline[ cmdline_len + 1 /* NUL */ ];
|
||||
const wchar_t *wcmdline = loaded->LoadOptions;
|
||||
|
||||
/* Convert command line to ASCII */
|
||||
snprintf ( cmdline, sizeof ( cmdline ), "%ls", wcmdline );
|
||||
|
||||
/* Process command line */
|
||||
process_cmdline ( cmdline );
|
||||
}
|
||||
|
||||
/**
|
||||
* EFI entry point
|
||||
*
|
||||
* @v image_handle Image handle
|
||||
* @v systab EFI system table
|
||||
* @ret efirc EFI status code
|
||||
*/
|
||||
EFI_STATUS EFIAPI efi_main ( EFI_HANDLE image_handle,
|
||||
EFI_SYSTEM_TABLE *systab ) {
|
||||
EFI_BOOT_SERVICES *bs;
|
||||
union {
|
||||
EFI_LOADED_IMAGE_PROTOCOL *image;
|
||||
void *interface;
|
||||
} loaded;
|
||||
EFI_HANDLE vdisk = NULL;
|
||||
EFI_HANDLE vpartition = NULL;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Record EFI handle and system table */
|
||||
efi_image_handle = image_handle;
|
||||
efi_systab = systab;
|
||||
bs = systab->BootServices;
|
||||
|
||||
/* Initialise stack cookie */
|
||||
init_cookie();
|
||||
|
||||
/* Print welcome banner */
|
||||
printf ( "\n\nBooting wim file...... (This may take a few minutes, please wait)\n\n");
|
||||
// printf ( "\n\nwimboot " VERSION " -- Windows Imaging Format "
|
||||
// "bootloader -- https://ipxe.org/wimboot\n\n" );
|
||||
|
||||
/* Get loaded image protocol */
|
||||
if ( ( efirc = bs->OpenProtocol ( image_handle,
|
||||
&efi_loaded_image_protocol_guid,
|
||||
&loaded.interface, image_handle, NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
|
||||
die ( "Could not open loaded image protocol: %#lx\n",
|
||||
( ( unsigned long ) efirc ) );
|
||||
}
|
||||
|
||||
/* Process command line */
|
||||
efi_cmdline ( loaded.image );
|
||||
|
||||
/* Extract files from file system */
|
||||
efi_extract ( loaded.image->DeviceHandle );
|
||||
|
||||
/* Install virtual disk */
|
||||
efi_install ( &vdisk, &vpartition );
|
||||
|
||||
/* Invoke boot manager */
|
||||
efi_boot ( bootmgfw, bootmgfw_path, vpartition );
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI device paths
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "efi.h"
|
||||
#include "efipath.h"
|
||||
|
||||
/**
|
||||
* Find end of device path
|
||||
*
|
||||
* @v path Path to device
|
||||
* @ret path_end End of device path
|
||||
*/
|
||||
EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
|
||||
|
||||
while ( path->Type != END_DEVICE_PATH_TYPE ) {
|
||||
path = ( ( ( void * ) path ) +
|
||||
/* There's this amazing new-fangled thing known as
|
||||
* a UINT16, but who wants to use one of those? */
|
||||
( ( path->Length[1] << 8 ) | path->Length[0] ) );
|
||||
}
|
||||
return path;
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef _EFIPATH_H
|
||||
#define _EFIPATH_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI device paths
|
||||
*
|
||||
*/
|
||||
|
||||
#include "efi.h"
|
||||
#include "efi/Protocol/DevicePath.h"
|
||||
|
||||
/**
|
||||
* Initialise device path
|
||||
*
|
||||
* @v name Variable name
|
||||
* @v type Type
|
||||
* @v subtype Subtype
|
||||
*/
|
||||
#define EFI_DEVPATH_INIT( name, type, subtype ) { \
|
||||
.Type = (type), \
|
||||
.SubType = (subtype), \
|
||||
.Length[0] = ( sizeof (name) & 0xff ), \
|
||||
.Length[1] = ( sizeof (name) >> 8 ), \
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise device path
|
||||
*
|
||||
* @v path Device path
|
||||
* @v type Type
|
||||
* @v subtype Subtype
|
||||
* @v len Length
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
efi_devpath_init ( EFI_DEVICE_PATH_PROTOCOL *path, unsigned int type,
|
||||
unsigned int subtype, size_t len ) {
|
||||
|
||||
path->Type = type;
|
||||
path->SubType = subtype;
|
||||
path->Length[0] = ( len & 0xff );
|
||||
path->Length[1] = ( len >> 8 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise device path end
|
||||
*
|
||||
* @v name Variable name
|
||||
*/
|
||||
#define EFI_DEVPATH_END_INIT( name ) \
|
||||
EFI_DEVPATH_INIT ( name, END_DEVICE_PATH_TYPE, \
|
||||
END_ENTIRE_DEVICE_PATH_SUBTYPE )
|
||||
|
||||
/**
|
||||
* Initialise device path end
|
||||
*
|
||||
* @v path Device path
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
efi_devpath_end_init ( EFI_DEVICE_PATH_PROTOCOL *path ) {
|
||||
|
||||
efi_devpath_init ( path, END_DEVICE_PATH_TYPE,
|
||||
END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof ( *path ) );
|
||||
}
|
||||
|
||||
extern EFI_DEVICE_PATH_PROTOCOL *
|
||||
efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
|
||||
|
||||
#endif /* _EFIPATH_H */
|
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* EFI relocations
|
||||
*
|
||||
* Derived from iPXE's elf2efi.c
|
||||
*
|
||||
*/
|
||||
|
||||
#define PACKAGE "wimboot"
|
||||
#define PACKAGE_VERSION VERSION
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <bfd.h>
|
||||
#include "efi.h"
|
||||
#include "efi/IndustryStandard/PeImage.h"
|
||||
#include "wimboot.h"
|
||||
|
||||
#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
|
||||
|
||||
/* Maintain compatibility with binutils 2.34 */
|
||||
#ifndef bfd_get_section_vma
|
||||
#define bfd_get_section_vma(bfd, ptr) bfd_section_vma(ptr)
|
||||
#endif
|
||||
#ifndef bfd_get_section_flags
|
||||
#define bfd_get_section_flags(bfd, ptr) bfd_section_flags(ptr)
|
||||
#endif
|
||||
|
||||
/** PE header maximum length
|
||||
*
|
||||
* This maximum length is guaranteed by the fact that the PE headers
|
||||
* have to fit entirely before the start of the bzImage header.
|
||||
*/
|
||||
#define PE_HEADER_LEN 512
|
||||
|
||||
/** .reloc section index */
|
||||
#define RELOC_SECTION_INDEX 3
|
||||
|
||||
/** PE relocations */
|
||||
struct pe_relocs {
|
||||
struct pe_relocs *next;
|
||||
unsigned long start_rva;
|
||||
unsigned int used_relocs;
|
||||
unsigned int total_relocs;
|
||||
uint16_t *relocs;
|
||||
};
|
||||
|
||||
/** Command-line options */
|
||||
struct options {
|
||||
/** Verbosity */
|
||||
int verbosity;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate memory
|
||||
*
|
||||
* @v len Length of memory to allocate
|
||||
* @ret ptr Pointer to allocated memory
|
||||
*/
|
||||
static void * xmalloc ( size_t len ) {
|
||||
void *ptr;
|
||||
|
||||
ptr = malloc ( len );
|
||||
if ( ! ptr ) {
|
||||
eprintf ( "Could not allocate %zd bytes\n", len );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to file
|
||||
*
|
||||
* @v fd File descriptor
|
||||
* @v data Data
|
||||
* @v len Length of data
|
||||
*/
|
||||
static void xwrite ( int fd, const void *data, size_t len ) {
|
||||
ssize_t written;
|
||||
|
||||
written = write ( fd, data, len );
|
||||
if ( written < 0 ) {
|
||||
eprintf ( "Could not write %zd bytes: %s\n",
|
||||
len, strerror ( errno ) );
|
||||
exit ( 1 );
|
||||
}
|
||||
if ( ( size_t ) written != len ) {
|
||||
eprintf ( "Wrote only %zd of %zd bytes\n", written, len );
|
||||
exit ( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to file position
|
||||
*
|
||||
* @v fd File descriptor
|
||||
* @v offset Offset
|
||||
* @v whence Origin
|
||||
*/
|
||||
static void xlseek ( int fd, off_t offset, int whence ) {
|
||||
off_t pos;
|
||||
|
||||
pos = lseek ( fd, offset, whence );
|
||||
if ( pos < 0 ) {
|
||||
eprintf ( "Could not seek: %s\n", strerror ( errno ) );
|
||||
exit ( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close file
|
||||
*
|
||||
* @v fd File descriptor
|
||||
*/
|
||||
static void xclose ( int fd ) {
|
||||
|
||||
if ( close ( fd ) < 0 ) {
|
||||
eprintf ( "Could not close: %s\n", strerror ( errno ) );
|
||||
exit ( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open input BFD file
|
||||
*
|
||||
* @v filename File name
|
||||
* @ret ibfd BFD file
|
||||
*/
|
||||
static bfd * open_input_bfd ( const char *filename ) {
|
||||
bfd *bfd;
|
||||
|
||||
/* Open the file */
|
||||
bfd = bfd_openr ( filename, NULL );
|
||||
if ( ! bfd ) {
|
||||
eprintf ( "Cannot open %s: ", filename );
|
||||
bfd_perror ( NULL );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* The call to bfd_check_format() must be present, otherwise
|
||||
* we get a segfault from later BFD calls.
|
||||
*/
|
||||
if ( ! bfd_check_format ( bfd, bfd_object ) ) {
|
||||
eprintf ( "%s is not an object file: ", filename );
|
||||
bfd_perror ( NULL );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
return bfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read symbol table
|
||||
*
|
||||
* @v bfd BFD file
|
||||
*/
|
||||
static asymbol ** read_symtab ( bfd *bfd ) {
|
||||
long symtab_size;
|
||||
asymbol **symtab;
|
||||
long symcount;
|
||||
|
||||
/* Get symbol table size */
|
||||
symtab_size = bfd_get_symtab_upper_bound ( bfd );
|
||||
if ( symtab_size < 0 ) {
|
||||
bfd_perror ( "Could not get symbol table upper bound" );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Allocate and read symbol table */
|
||||
symtab = xmalloc ( symtab_size );
|
||||
symcount = bfd_canonicalize_symtab ( bfd, symtab );
|
||||
if ( symcount < 0 ) {
|
||||
bfd_perror ( "Cannot read symbol table" );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
return symtab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read relocation table
|
||||
*
|
||||
* @v bfd BFD file
|
||||
* @v symtab Symbol table
|
||||
* @v section Section
|
||||
* @v symtab Symbol table
|
||||
* @ret reltab Relocation table
|
||||
*/
|
||||
static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
|
||||
asection *section ) {
|
||||
long reltab_size;
|
||||
arelent **reltab;
|
||||
long numrels;
|
||||
|
||||
/* Get relocation table size */
|
||||
reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
|
||||
if ( reltab_size < 0 ) {
|
||||
bfd_perror ( "Could not get relocation table upper bound" );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Allocate and read relocation table */
|
||||
reltab = xmalloc ( reltab_size );
|
||||
numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
|
||||
if ( numrels < 0 ) {
|
||||
bfd_perror ( "Cannot read relocation table" );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
return reltab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate entry in PE relocation table
|
||||
*
|
||||
* @v pe_reltab PE relocation table
|
||||
* @v rva RVA
|
||||
* @v size Size of relocation entry
|
||||
*/
|
||||
static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
|
||||
unsigned long rva, size_t size ) {
|
||||
unsigned long start_rva;
|
||||
uint16_t reloc;
|
||||
struct pe_relocs *pe_rel;
|
||||
uint16_t *relocs;
|
||||
|
||||
/* Construct */
|
||||
start_rva = ( rva & ~0xfff );
|
||||
reloc = ( rva & 0xfff );
|
||||
switch ( size ) {
|
||||
case 8:
|
||||
reloc |= 0xa000;
|
||||
break;
|
||||
case 4:
|
||||
reloc |= 0x3000;
|
||||
break;
|
||||
case 2:
|
||||
reloc |= 0x2000;
|
||||
break;
|
||||
default:
|
||||
eprintf ( "Unsupported relocation size %zd\n", size );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Locate or create PE relocation table */
|
||||
for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
|
||||
if ( pe_rel->start_rva == start_rva )
|
||||
break;
|
||||
}
|
||||
if ( ! pe_rel ) {
|
||||
pe_rel = xmalloc ( sizeof ( *pe_rel ) );
|
||||
memset ( pe_rel, 0, sizeof ( *pe_rel ) );
|
||||
pe_rel->next = *pe_reltab;
|
||||
*pe_reltab = pe_rel;
|
||||
pe_rel->start_rva = start_rva;
|
||||
}
|
||||
|
||||
/* Expand relocation list if necessary */
|
||||
if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
|
||||
relocs = pe_rel->relocs;
|
||||
} else {
|
||||
pe_rel->total_relocs = ( pe_rel->total_relocs ?
|
||||
( pe_rel->total_relocs * 2 ) : 256 );
|
||||
relocs = xmalloc ( pe_rel->total_relocs *
|
||||
sizeof ( pe_rel->relocs[0] ) );
|
||||
memset ( relocs, 0,
|
||||
pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
|
||||
memcpy ( relocs, pe_rel->relocs,
|
||||
pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
|
||||
free ( pe_rel->relocs );
|
||||
pe_rel->relocs = relocs;
|
||||
}
|
||||
|
||||
/* Store relocation */
|
||||
pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process relocation record
|
||||
*
|
||||
* @v bfd BFD file
|
||||
* @v section Section
|
||||
* @v rel Relocation entry
|
||||
* @v pe_reltab PE relocation table to fill in
|
||||
*/
|
||||
static void process_reloc ( bfd *bfd __unused, asection *section, arelent *rel,
|
||||
struct pe_relocs **pe_reltab ) {
|
||||
reloc_howto_type *howto = rel->howto;
|
||||
asymbol *sym = *(rel->sym_ptr_ptr);
|
||||
unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
|
||||
rel->address - BASE_ADDRESS );
|
||||
|
||||
if ( bfd_is_abs_section ( sym->section ) ) {
|
||||
/* Skip absolute symbols; the symbol value won't
|
||||
* change when the object is loaded.
|
||||
*/
|
||||
} else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
|
||||
/* Generate an 8-byte PE relocation */
|
||||
generate_pe_reloc ( pe_reltab, offset, 8 );
|
||||
} else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
|
||||
( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ||
|
||||
( strcmp ( howto->name, "R_X86_64_32S" ) == 0 ) ) {
|
||||
/* Generate a 4-byte PE relocation */
|
||||
generate_pe_reloc ( pe_reltab, offset, 4 );
|
||||
} else if ( ( strcmp ( howto->name, "R_386_16" ) == 0 ) ||
|
||||
( strcmp ( howto->name, "R_X86_64_16" ) == 0 ) ) {
|
||||
/* Generate a 2-byte PE relocation */
|
||||
generate_pe_reloc ( pe_reltab, offset, 2 );
|
||||
} else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
|
||||
( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ||
|
||||
( strcmp ( howto->name, "R_X86_64_PLT32" ) == 0 ) ) {
|
||||
/* Skip PC-relative relocations; all relative offsets
|
||||
* remain unaltered when the object is loaded.
|
||||
*/
|
||||
} else {
|
||||
eprintf ( "Unrecognised relocation type %s\n", howto->name );
|
||||
exit ( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate size of binary PE relocation table
|
||||
*
|
||||
* @v fh File handle
|
||||
* @v pe_reltab PE relocation table
|
||||
* @ret size Size of binary table
|
||||
*/
|
||||
static size_t output_pe_reltab ( int fd, struct pe_relocs *pe_reltab ) {
|
||||
EFI_IMAGE_BASE_RELOCATION header;
|
||||
struct pe_relocs *pe_rel;
|
||||
static uint8_t pad[16];
|
||||
unsigned int num_relocs;
|
||||
size_t size;
|
||||
size_t pad_size;
|
||||
size_t total_size = 0;
|
||||
|
||||
for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
|
||||
num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
|
||||
size = ( sizeof ( header ) +
|
||||
( num_relocs * sizeof ( uint16_t ) ) );
|
||||
pad_size = ( ( -size ) & ( sizeof ( pad ) - 1 ) );
|
||||
size += pad_size;
|
||||
header.VirtualAddress = pe_rel->start_rva;
|
||||
header.SizeOfBlock = size;
|
||||
xwrite ( fd, &header, sizeof ( header ) );
|
||||
xwrite ( fd, pe_rel->relocs,
|
||||
( num_relocs * sizeof ( uint16_t ) ) );
|
||||
xwrite ( fd, pad, pad_size );
|
||||
total_size += size;
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add relocation information
|
||||
*
|
||||
* @v elf_name ELF file name
|
||||
* @v pe_name PE file name
|
||||
*/
|
||||
static void efireloc ( const char *elf_name, const char *pe_name ) {
|
||||
struct pe_relocs *pe_reltab = NULL;
|
||||
int fd;
|
||||
EFI_IMAGE_DOS_HEADER *dos;
|
||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *nt;
|
||||
EFI_IMAGE_DATA_DIRECTORY *data_dir;
|
||||
EFI_IMAGE_SECTION_HEADER *pe_sections;
|
||||
UINT32 *image_size;
|
||||
bfd *bfd;
|
||||
asymbol **symtab;
|
||||
asection *section;
|
||||
arelent **reltab;
|
||||
arelent **rel;
|
||||
size_t reloc_len;
|
||||
|
||||
/* Open the output file */
|
||||
fd = open ( pe_name, O_RDWR );
|
||||
if ( fd < 0 ) {
|
||||
eprintf ( "Could not open %s: %s\n",
|
||||
pe_name, strerror ( errno ) );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Map the output file header */
|
||||
dos = mmap ( NULL, PE_HEADER_LEN, ( PROT_READ | PROT_WRITE ),
|
||||
MAP_SHARED, fd, 0 );
|
||||
if ( ! dos ) {
|
||||
eprintf ( "Could not mmap %s: %s\n",
|
||||
pe_name, strerror ( errno ) );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Locate the modifiable fields within the output file header */
|
||||
nt = ( ( ( void * ) dos ) + dos->e_lfanew );
|
||||
if ( nt->Pe32.FileHeader.Machine == EFI_IMAGE_MACHINE_IA32 ) {
|
||||
image_size = &nt->Pe32.OptionalHeader.SizeOfImage;
|
||||
data_dir = nt->Pe32.OptionalHeader.DataDirectory;
|
||||
pe_sections = ( ( ( void * ) nt ) + sizeof ( nt->Pe32 ) );
|
||||
} else if ( nt->Pe32Plus.FileHeader.Machine == EFI_IMAGE_MACHINE_X64 ) {
|
||||
image_size = &nt->Pe32Plus.OptionalHeader.SizeOfImage;
|
||||
data_dir = nt->Pe32Plus.OptionalHeader.DataDirectory;
|
||||
pe_sections = ( ( ( void * ) nt ) + sizeof ( nt->Pe32Plus ) );
|
||||
} else {
|
||||
eprintf ( "Unrecognised machine type\n" );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
/* Open the input file */
|
||||
bfd = open_input_bfd ( elf_name );
|
||||
symtab = read_symtab ( bfd );
|
||||
|
||||
/* For each input section, create the appropriate relocation records */
|
||||
for ( section = bfd->sections ; section ; section = section->next ) {
|
||||
/* Discard non-allocatable sections */
|
||||
if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
|
||||
continue;
|
||||
/* Add relocations from this section */
|
||||
reltab = read_reltab ( bfd, symtab, section );
|
||||
for ( rel = reltab ; *rel ; rel++ )
|
||||
process_reloc ( bfd, section, *rel, &pe_reltab );
|
||||
free ( reltab );
|
||||
}
|
||||
|
||||
/* Close input file */
|
||||
bfd_close ( bfd );
|
||||
|
||||
/* Generate relocation section */
|
||||
xlseek ( fd, 0, SEEK_END );
|
||||
reloc_len = output_pe_reltab ( fd, pe_reltab );
|
||||
|
||||
/* Modify image header */
|
||||
*image_size += reloc_len;
|
||||
data_dir[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = reloc_len;
|
||||
pe_sections[RELOC_SECTION_INDEX].Misc.VirtualSize = reloc_len;
|
||||
pe_sections[RELOC_SECTION_INDEX].SizeOfRawData = reloc_len;
|
||||
|
||||
/* Unmap output file header */
|
||||
munmap ( dos, PE_HEADER_LEN );
|
||||
|
||||
/* Close output file */
|
||||
xclose ( fd );
|
||||
}
|
||||
|
||||
/**
|
||||
* Print help
|
||||
*
|
||||
* @v program_name Program name
|
||||
*/
|
||||
static void print_help ( const char *program_name ) {
|
||||
eprintf ( "Syntax: %s [-v|-q] infile outfile\n", program_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line options
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @v opts Options structure to populate
|
||||
*/
|
||||
static int parse_options ( const int argc, char **argv,
|
||||
struct options *opts ) {
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
if ( ( c = getopt_long ( argc, argv, "hvq",
|
||||
long_options,
|
||||
&option_index ) ) == -1 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( c ) {
|
||||
case 'v':
|
||||
opts->verbosity++;
|
||||
break;
|
||||
case 'q':
|
||||
if ( opts->verbosity )
|
||||
opts->verbosity--;
|
||||
break;
|
||||
case 'h':
|
||||
print_help ( argv[0] );
|
||||
exit ( 0 );
|
||||
case '?':
|
||||
default:
|
||||
exit ( 2 );
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*
|
||||
* @v argc Number of arguments
|
||||
* @v argv Command-line arguments
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int main ( int argc, char **argv ) {
|
||||
struct options opts = {
|
||||
.verbosity = 0,
|
||||
};
|
||||
int infile_index;
|
||||
const char *infile;
|
||||
const char *outfile;
|
||||
|
||||
/* Initialise libbfd */
|
||||
bfd_init();
|
||||
|
||||
/* Parse command-line arguments */
|
||||
infile_index = parse_options ( argc, argv, &opts );
|
||||
if ( argc != ( infile_index + 2 ) ) {
|
||||
print_help ( argv[0] );
|
||||
exit ( 2 );
|
||||
}
|
||||
infile = argv[infile_index];
|
||||
outfile = argv[infile_index + 1];
|
||||
|
||||
/* Add relocation information */
|
||||
efireloc ( infile, outfile );
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Error numbers
|
||||
*
|
||||
*/
|
||||
|
||||
#endif /* _ERRNO_H */
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Huffman alphabets
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
|
||||
/**
|
||||
* Transcribe binary value (for debugging)
|
||||
*
|
||||
* @v value Value
|
||||
* @v bits Length of value (in bits)
|
||||
* @ret string Transcribed value
|
||||
*/
|
||||
static const char * huffman_bin ( unsigned long value, unsigned int bits ) {
|
||||
static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ];
|
||||
char *out = buf;
|
||||
|
||||
/* Sanity check */
|
||||
assert ( bits < sizeof ( buf ) );
|
||||
|
||||
/* Transcribe value */
|
||||
while ( bits-- )
|
||||
*(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' );
|
||||
*out = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump Huffman alphabet (for debugging)
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
*/
|
||||
static void __attribute__ (( unused ))
|
||||
huffman_dump_alphabet ( struct huffman_alphabet *alphabet ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int bits;
|
||||
unsigned int huf;
|
||||
unsigned int i;
|
||||
|
||||
/* Dump symbol table for each utilised length */
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
if ( sym->freq == 0 )
|
||||
continue;
|
||||
huf = ( sym->start >> sym->shift );
|
||||
DBG ( "Huffman length %d start \"%s\" freq %d:", bits,
|
||||
huffman_bin ( huf, sym->bits ), sym->freq );
|
||||
for ( i = 0 ; i < sym->freq ; i++ ) {
|
||||
DBG ( " %03x", sym->raw[ huf + i ] );
|
||||
}
|
||||
DBG ( "\n" );
|
||||
}
|
||||
|
||||
/* Dump quick lookup table */
|
||||
DBG ( "Huffman quick lookup:" );
|
||||
for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) /
|
||||
sizeof ( alphabet->lookup[0] ) ) ; i++ ) {
|
||||
DBG ( " %d", ( alphabet->lookup[i] + 1 ) );
|
||||
}
|
||||
DBG ( "\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct Huffman alphabet
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
* @v lengths Symbol length table
|
||||
* @v count Number of symbols
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int huffman_alphabet ( struct huffman_alphabet *alphabet,
|
||||
uint8_t *lengths, unsigned int count ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int huf;
|
||||
unsigned int cum_freq;
|
||||
unsigned int bits;
|
||||
unsigned int raw;
|
||||
unsigned int adjustment;
|
||||
unsigned int prefix;
|
||||
int empty;
|
||||
int complete;
|
||||
|
||||
/* Clear symbol table */
|
||||
memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) );
|
||||
|
||||
/* Count number of symbols with each Huffman-coded length */
|
||||
empty = 1;
|
||||
for ( raw = 0 ; raw < count ; raw++ ) {
|
||||
bits = lengths[raw];
|
||||
if ( bits ) {
|
||||
alphabet->huf[ bits - 1 ].freq++;
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* In the degenerate case of having no symbols (i.e. an unused
|
||||
* alphabet), generate a trivial alphabet with exactly two
|
||||
* single-bit codes. This allows callers to avoid having to
|
||||
* check for this special case.
|
||||
*/
|
||||
if ( empty )
|
||||
alphabet->huf[0].freq = 2;
|
||||
|
||||
/* Populate Huffman-coded symbol table */
|
||||
huf = 0;
|
||||
cum_freq = 0;
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
sym->bits = bits;
|
||||
sym->shift = ( HUFFMAN_BITS - bits );
|
||||
sym->start = ( huf << sym->shift );
|
||||
sym->raw = &alphabet->raw[cum_freq];
|
||||
huf += sym->freq;
|
||||
if ( huf > ( 1U << bits ) ) {
|
||||
DBG ( "Huffman alphabet has too many symbols with "
|
||||
"lengths <=%d\n", bits );
|
||||
return -1;
|
||||
}
|
||||
huf <<= 1;
|
||||
cum_freq += sym->freq;
|
||||
}
|
||||
complete = ( huf == ( 1U << bits ) );
|
||||
|
||||
/* Populate raw symbol table */
|
||||
for ( raw = 0 ; raw < count ; raw++ ) {
|
||||
bits = lengths[raw];
|
||||
if ( bits ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
*(sym->raw++) = raw;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust Huffman-coded symbol table raw pointers and populate
|
||||
* quick lookup table.
|
||||
*/
|
||||
for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
|
||||
sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
|
||||
sym = &alphabet->huf[ bits - 1 ];
|
||||
|
||||
/* Adjust raw pointer */
|
||||
sym->raw -= sym->freq; /* Reset to first symbol */
|
||||
adjustment = ( sym->start >> sym->shift );
|
||||
sym->raw -= adjustment; /* Adjust for quick indexing */
|
||||
|
||||
/* Populate quick lookup table */
|
||||
for ( prefix = ( sym->start >> HUFFMAN_QL_SHIFT ) ;
|
||||
prefix < ( 1 << HUFFMAN_QL_BITS ) ; prefix++ ) {
|
||||
alphabet->lookup[prefix] = ( bits - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that there are no invalid codes */
|
||||
if ( ! complete ) {
|
||||
DBG ( "Huffman alphabet is incomplete\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Huffman symbol set
|
||||
*
|
||||
* @v alphabet Huffman alphabet
|
||||
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
|
||||
* @ret sym Huffman symbol set
|
||||
*/
|
||||
struct huffman_symbols * huffman_sym ( struct huffman_alphabet *alphabet,
|
||||
unsigned int huf ) {
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int lookup_index;
|
||||
|
||||
/* Find symbol set for this length */
|
||||
lookup_index = ( huf >> HUFFMAN_QL_SHIFT );
|
||||
sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ];
|
||||
while ( huf < sym->start )
|
||||
sym--;
|
||||
return sym;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef _HUFFMAN_H
|
||||
#define _HUFFMAN_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Huffman alphabets
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Maximum length of a Huffman symbol (in bits) */
|
||||
#define HUFFMAN_BITS 16
|
||||
|
||||
/** Raw huffman symbol */
|
||||
typedef uint16_t huffman_raw_symbol_t;
|
||||
|
||||
/** Quick lookup length for a Huffman symbol (in bits)
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define HUFFMAN_QL_BITS 7
|
||||
|
||||
/** Quick lookup shift */
|
||||
#define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS )
|
||||
|
||||
/** A Huffman-coded set of symbols of a given length */
|
||||
struct huffman_symbols {
|
||||
/** Length of Huffman-coded symbols (in bits) */
|
||||
uint8_t bits;
|
||||
/** Shift to normalise symbols of this length to HUFFMAN_BITS bits */
|
||||
uint8_t shift;
|
||||
/** Number of Huffman-coded symbols having this length */
|
||||
uint16_t freq;
|
||||
/** First symbol of this length (normalised to HUFFMAN_BITS bits)
|
||||
*
|
||||
* Stored as a 32-bit value to allow the value
|
||||
* (1<<HUFFMAN_BITS ) to be used for empty sets of symbols
|
||||
* longer than the maximum utilised length.
|
||||
*/
|
||||
uint32_t start;
|
||||
/** Raw symbols having this length */
|
||||
huffman_raw_symbol_t *raw;
|
||||
};
|
||||
|
||||
/** A Huffman-coded alphabet */
|
||||
struct huffman_alphabet {
|
||||
/** Huffman-coded symbol set for each length */
|
||||
struct huffman_symbols huf[HUFFMAN_BITS];
|
||||
/** Quick lookup table */
|
||||
uint8_t lookup[ 1 << HUFFMAN_QL_BITS ];
|
||||
/** Raw symbols
|
||||
*
|
||||
* Ordered by Huffman-coded symbol length, then by symbol
|
||||
* value. This field has a variable length.
|
||||
*/
|
||||
huffman_raw_symbol_t raw[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Huffman symbol length
|
||||
*
|
||||
* @v sym Huffman symbol set
|
||||
* @ret len Length (in bits)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
huffman_len ( struct huffman_symbols *sym ) {
|
||||
|
||||
return sym->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Huffman symbol value
|
||||
*
|
||||
* @v sym Huffman symbol set
|
||||
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
|
||||
* @ret raw Raw symbol value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) huffman_raw_symbol_t
|
||||
huffman_raw ( struct huffman_symbols *sym, unsigned int huf ) {
|
||||
|
||||
return sym->raw[ huf >> sym->shift ];
|
||||
}
|
||||
|
||||
extern int huffman_alphabet ( struct huffman_alphabet *alphabet,
|
||||
uint8_t *lengths, unsigned int count );
|
||||
extern struct huffman_symbols *
|
||||
huffman_sym ( struct huffman_alphabet *alphabet, unsigned int huf );
|
||||
|
||||
#endif /* _HUFFMAN_H */
|
|
@ -0,0 +1 @@
|
|||
.code32
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* INT 13 emulation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "int13.h"
|
||||
#include "vdisk.h"
|
||||
|
||||
/** Emulated drive number */
|
||||
static int vdisk_drive;
|
||||
|
||||
/**
|
||||
* Initialise emulation
|
||||
*
|
||||
* @ret drive Emulated drive number
|
||||
*/
|
||||
int initialise_int13 ( void ) {
|
||||
|
||||
/* Determine drive number */
|
||||
vdisk_drive = ( 0x80 | INT13_DRIVE_COUNT++ );
|
||||
DBG ( "Emulating drive %#02x\n", vdisk_drive );
|
||||
|
||||
return vdisk_drive;
|
||||
}
|
||||
|
||||
/**
|
||||
* INT 13, 08 - Get drive parameters
|
||||
*
|
||||
* @ret ch Low bits of maximum cylinder number
|
||||
* @ret cl (bits 7:6) High bits of maximum cylinder number
|
||||
* @ret cl (bits 5:0) Maximum sector number
|
||||
* @ret dh Maximum head number
|
||||
* @ret dl Number of drives
|
||||
* @ret ah Status code
|
||||
*/
|
||||
static void int13_get_parameters ( struct bootapp_callback_params *params ) {
|
||||
unsigned int max_cylinder = ( VDISK_CYLINDERS - 1 );
|
||||
unsigned int max_head = ( VDISK_HEADS - 1 );
|
||||
unsigned int max_sector = ( VDISK_SECTORS_PER_TRACK - 0 /* sic */ );
|
||||
unsigned int num_drives;
|
||||
unsigned int min_num_drives;
|
||||
|
||||
/* Calculate number of drives to report */
|
||||
num_drives = INT13_DRIVE_COUNT;
|
||||
min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
|
||||
if ( num_drives < min_num_drives )
|
||||
num_drives = min_num_drives;
|
||||
|
||||
/* Fill in drive parameters */
|
||||
params->ch = ( max_cylinder & 0xff );
|
||||
params->cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
|
||||
params->dh = max_head;
|
||||
params->dl = num_drives;
|
||||
DBG2 ( "Get parameters: C/H/S = %d/%d/%d, drives = %d\n",
|
||||
( max_cylinder + 1 ), ( max_head + 1 ), max_sector, num_drives );
|
||||
|
||||
/* Success */
|
||||
params->ah = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* INT 13, 15 - Get disk type
|
||||
*
|
||||
* @ret cx:dx Sector count
|
||||
* @ret ah Type code
|
||||
*/
|
||||
static void int13_get_disk_type ( struct bootapp_callback_params *params ) {
|
||||
uint32_t sector_count = VDISK_COUNT;
|
||||
uint8_t drive_type = INT13_DISK_TYPE_HDD;
|
||||
|
||||
/* Fill in disk type */
|
||||
params->cx = ( sector_count >> 16 );
|
||||
params->dx = ( sector_count & 0xffff );
|
||||
params->ah = drive_type;
|
||||
DBG2 ( "Get disk type: sectors = %#08x, type = %d\n",
|
||||
sector_count, drive_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* INT 13, 41 - Extensions installation check
|
||||
*
|
||||
* @v bx 0x55aa
|
||||
* @ret bx 0xaa55
|
||||
* @ret cx Extensions API support bitmap
|
||||
* @ret ah API version
|
||||
*/
|
||||
static void int13_extension_check ( struct bootapp_callback_params *params ) {
|
||||
|
||||
/* Fill in extension information */
|
||||
params->bx = 0xaa55;
|
||||
params->cx = INT13_EXTENSION_LINEAR;
|
||||
params->ah = INT13_EXTENSION_VER_1_X;
|
||||
DBG2 ( "Extensions installation check\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* INT 13, 48 - Get extended parameters
|
||||
*
|
||||
* @v ds:si Drive parameter table
|
||||
* @ret ah Status code
|
||||
*/
|
||||
static void
|
||||
int13_get_extended_parameters ( struct bootapp_callback_params *params ) {
|
||||
struct int13_disk_parameters *disk_params;
|
||||
|
||||
/* Fill in extended parameters */
|
||||
disk_params = REAL_PTR ( params->ds, params->si );
|
||||
memset ( disk_params, 0, sizeof ( *disk_params ) );
|
||||
disk_params->bufsize = sizeof ( *disk_params );
|
||||
disk_params->flags = INT13_FL_DMA_TRANSPARENT;
|
||||
disk_params->cylinders = VDISK_CYLINDERS;
|
||||
disk_params->heads = VDISK_HEADS;
|
||||
disk_params->sectors_per_track = VDISK_SECTORS_PER_TRACK;
|
||||
disk_params->sectors = VDISK_COUNT;
|
||||
disk_params->sector_size = VDISK_SECTOR_SIZE;
|
||||
DBG2 ( "Get extended parameters: C/H/S = %d/%d/%d, sectors = %#08llx "
|
||||
"(%d bytes)\n", disk_params->cylinders, disk_params->heads,
|
||||
disk_params->sectors_per_track, disk_params->sectors,
|
||||
disk_params->sector_size );
|
||||
|
||||
/* Success */
|
||||
params->ah = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* INT 13, 42 - Extended read
|
||||
*
|
||||
* @v ds:si Disk address packet
|
||||
* @ret ah Status code
|
||||
*/
|
||||
static void int13_extended_read ( struct bootapp_callback_params *params ) {
|
||||
struct int13_disk_address *disk_address;
|
||||
void *data;
|
||||
|
||||
/* Read from emulated disk */
|
||||
disk_address = REAL_PTR ( params->ds, params->si );
|
||||
data = REAL_PTR ( disk_address->buffer.segment,
|
||||
disk_address->buffer.offset );
|
||||
vdisk_read ( disk_address->lba, disk_address->count, data );
|
||||
|
||||
/* Success */
|
||||
params->ah = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate INT 13 drive
|
||||
*
|
||||
* @v params Parameters
|
||||
*/
|
||||
void emulate_int13 ( struct bootapp_callback_params *params ) {
|
||||
int command = params->ah;
|
||||
int drive = params->dl;
|
||||
int min_num_drives;
|
||||
unsigned long eflags;
|
||||
|
||||
if ( drive == vdisk_drive ) {
|
||||
|
||||
/* Emulated drive - handle internally */
|
||||
|
||||
/* Populate eflags with a sensible starting value */
|
||||
__asm__ ( "pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
: "=r" ( eflags ) );
|
||||
params->eflags = ( eflags & ~CF );
|
||||
|
||||
/* Handle command */
|
||||
switch ( command ) {
|
||||
case INT13_GET_PARAMETERS:
|
||||
int13_get_parameters ( params );
|
||||
break;
|
||||
case INT13_GET_DISK_TYPE:
|
||||
int13_get_disk_type ( params );
|
||||
break;
|
||||
case INT13_EXTENSION_CHECK:
|
||||
int13_extension_check ( params );
|
||||
break;
|
||||
case INT13_GET_EXTENDED_PARAMETERS:
|
||||
int13_get_extended_parameters ( params );
|
||||
break;
|
||||
case INT13_EXTENDED_READ:
|
||||
int13_extended_read ( params );
|
||||
break;
|
||||
default:
|
||||
DBG ( "Unrecognised INT 13,%02x\n", command );
|
||||
params->eflags |= CF;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Pass through command to underlying INT 13 */
|
||||
call_interrupt ( params );
|
||||
|
||||
/* Modify drive count, if applicable */
|
||||
if ( command == INT13_GET_PARAMETERS ) {
|
||||
min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
|
||||
if ( params->dl < min_num_drives )
|
||||
params->dl = min_num_drives;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
#ifndef _INT13_H
|
||||
#define _INT13_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* INT 13 emulation
|
||||
*
|
||||
*/
|
||||
|
||||
/** Construct a pointer from a real-mode segment:offset address */
|
||||
#define REAL_PTR( segment, offset ) \
|
||||
( ( void * ) ( intptr_t ) ( ( (segment) << 4 ) + offset ) )
|
||||
|
||||
/** Get drive parameters */
|
||||
#define INT13_GET_PARAMETERS 0x08
|
||||
/** Get disk type */
|
||||
#define INT13_GET_DISK_TYPE 0x15
|
||||
/** Extensions installation check */
|
||||
#define INT13_EXTENSION_CHECK 0x41
|
||||
/** Extended read */
|
||||
#define INT13_EXTENDED_READ 0x42
|
||||
/** Get extended drive parameters */
|
||||
#define INT13_GET_EXTENDED_PARAMETERS 0x48
|
||||
|
||||
/** Operation completed successfully */
|
||||
#define INT13_STATUS_SUCCESS 0x00
|
||||
/** Invalid function or parameter */
|
||||
#define INT13_STATUS_INVALID 0x01
|
||||
/** Read error */
|
||||
#define INT13_STATUS_READ_ERROR 0x04
|
||||
/** Reset failed */
|
||||
#define INT13_STATUS_RESET_FAILED 0x05
|
||||
/** Write error */
|
||||
#define INT13_STATUS_WRITE_ERROR 0xcc
|
||||
|
||||
/** No such drive */
|
||||
#define INT13_DISK_TYPE_NONE 0x00
|
||||
/** Floppy without change-line support */
|
||||
#define INT13_DISK_TYPE_FDD 0x01
|
||||
/** Floppy with change-line support */
|
||||
#define INT13_DISK_TYPE_FDD_CL 0x02
|
||||
/** Hard disk */
|
||||
#define INT13_DISK_TYPE_HDD 0x03
|
||||
|
||||
/** Extended disk access functions supported */
|
||||
#define INT13_EXTENSION_LINEAR 0x01
|
||||
|
||||
/** INT13 extensions version 1.x */
|
||||
#define INT13_EXTENSION_VER_1_X 0x01
|
||||
|
||||
/** DMA boundary errors handled transparently */
|
||||
#define INT13_FL_DMA_TRANSPARENT 0x01
|
||||
|
||||
/** BIOS drive counter */
|
||||
#define INT13_DRIVE_COUNT ( *( ( ( uint8_t * ) REAL_PTR ( 0x40, 0x75 ) ) ) )
|
||||
|
||||
/** An INT 13 disk address packet */
|
||||
struct int13_disk_address {
|
||||
/** Size of the packet, in bytes */
|
||||
uint8_t bufsize;
|
||||
/** Reserved */
|
||||
uint8_t reserved_a;
|
||||
/** Block count */
|
||||
uint8_t count;
|
||||
/** Reserved */
|
||||
uint8_t reserved_b;
|
||||
/** Data buffer */
|
||||
struct segoff buffer;
|
||||
/** Starting block number */
|
||||
uint64_t lba;
|
||||
/** Data buffer (EDD 3.0+ only) */
|
||||
uint64_t buffer_phys;
|
||||
/** Block count (EDD 4.0+ only) */
|
||||
uint32_t long_count;
|
||||
/** Reserved */
|
||||
uint32_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** INT 13 disk parameters */
|
||||
struct int13_disk_parameters {
|
||||
/** Size of this structure */
|
||||
uint16_t bufsize;
|
||||
/** Flags */
|
||||
uint16_t flags;
|
||||
/** Number of cylinders */
|
||||
uint32_t cylinders;
|
||||
/** Number of heads */
|
||||
uint32_t heads;
|
||||
/** Number of sectors per track */
|
||||
uint32_t sectors_per_track;
|
||||
/** Total number of sectors on drive */
|
||||
uint64_t sectors;
|
||||
/** Bytes per sector */
|
||||
uint16_t sector_size;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
extern int initialise_int13 ( void );
|
||||
extern void emulate_int13 ( struct bootapp_callback_params *params );
|
||||
|
||||
#endif /* _INT13_H */
|
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <wchar.h>
|
||||
#include <ipxe/vsprintf.h>
|
||||
|
||||
/** @file */
|
||||
|
||||
#define CHAR_LEN 0 /**< "hh" length modifier */
|
||||
#define SHORT_LEN 1 /**< "h" length modifier */
|
||||
#define INT_LEN 2 /**< no length modifier */
|
||||
#define LONG_LEN 3 /**< "l" length modifier */
|
||||
#define LONGLONG_LEN 4 /**< "ll" length modifier */
|
||||
#define SIZE_T_LEN 5 /**< "z" length modifier */
|
||||
|
||||
static uint8_t type_sizes[] = {
|
||||
[CHAR_LEN] = sizeof ( char ),
|
||||
[SHORT_LEN] = sizeof ( short ),
|
||||
[INT_LEN] = sizeof ( int ),
|
||||
[LONG_LEN] = sizeof ( long ),
|
||||
[LONGLONG_LEN] = sizeof ( long long ),
|
||||
[SIZE_T_LEN] = sizeof ( size_t ),
|
||||
};
|
||||
|
||||
/**
|
||||
* Use lower-case for hexadecimal digits
|
||||
*
|
||||
* Note that this value is set to 0x20 since that makes for very
|
||||
* efficient calculations. (Bitwise-ORing with @c LCASE converts to a
|
||||
* lower-case character, for example.)
|
||||
*/
|
||||
#define LCASE 0x20
|
||||
|
||||
/**
|
||||
* Use "alternate form"
|
||||
*
|
||||
* For hexadecimal numbers, this means to add a "0x" or "0X" prefix to
|
||||
* the number.
|
||||
*/
|
||||
#define ALT_FORM 0x02
|
||||
|
||||
/**
|
||||
* Use zero padding
|
||||
*
|
||||
* Note that this value is set to 0x10 since that allows the pad
|
||||
* character to be calculated as @c 0x20|(flags&ZPAD)
|
||||
*/
|
||||
#define ZPAD 0x10
|
||||
|
||||
/**
|
||||
* Format a hexadecimal number
|
||||
*
|
||||
* @v end End of buffer to contain number
|
||||
* @v num Number to format
|
||||
* @v width Minimum field width
|
||||
* @v flags Format flags
|
||||
* @ret ptr End of buffer
|
||||
*
|
||||
* Fills a buffer in reverse order with a formatted hexadecimal
|
||||
* number. The number will be zero-padded to the specified width.
|
||||
* Lower-case and "alternate form" (i.e. "0x" prefix) flags may be
|
||||
* set.
|
||||
*
|
||||
* There must be enough space in the buffer to contain the largest
|
||||
* number that this function can format.
|
||||
*/
|
||||
static char * format_hex ( char *end, unsigned long long num, int width,
|
||||
int flags ) {
|
||||
char *ptr = end;
|
||||
int case_mod = ( flags & LCASE );
|
||||
int pad = ( ( flags & ZPAD ) | ' ' );
|
||||
|
||||
/* Generate the number */
|
||||
do {
|
||||
*(--ptr) = "0123456789ABCDEF"[ num & 0xf ] | case_mod;
|
||||
num >>= 4;
|
||||
} while ( num );
|
||||
|
||||
/* Pad to width */
|
||||
while ( ( end - ptr ) < width )
|
||||
*(--ptr) = pad;
|
||||
|
||||
/* Add "0x" or "0X" if alternate form specified */
|
||||
if ( flags & ALT_FORM ) {
|
||||
*(--ptr) = 'X' | case_mod;
|
||||
*(--ptr) = '0';
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a decimal number
|
||||
*
|
||||
* @v end End of buffer to contain number
|
||||
* @v num Number to format
|
||||
* @v width Minimum field width
|
||||
* @v flags Format flags
|
||||
* @ret ptr End of buffer
|
||||
*
|
||||
* Fills a buffer in reverse order with a formatted decimal number.
|
||||
* The number will be space-padded to the specified width.
|
||||
*
|
||||
* There must be enough space in the buffer to contain the largest
|
||||
* number that this function can format.
|
||||
*/
|
||||
static char * format_decimal ( char *end, signed long num, int width,
|
||||
int flags ) {
|
||||
char *ptr = end;
|
||||
int negative = 0;
|
||||
int zpad = ( flags & ZPAD );
|
||||
int pad = ( zpad | ' ' );
|
||||
|
||||
/* Generate the number */
|
||||
if ( num < 0 ) {
|
||||
negative = 1;
|
||||
num = -num;
|
||||
}
|
||||
do {
|
||||
*(--ptr) = '0' + ( num % 10 );
|
||||
num /= 10;
|
||||
} while ( num );
|
||||
|
||||
/* Add "-" if necessary */
|
||||
if ( negative && ( ! zpad ) )
|
||||
*(--ptr) = '-';
|
||||
|
||||
/* Pad to width */
|
||||
while ( ( end - ptr ) < width )
|
||||
*(--ptr) = pad;
|
||||
|
||||
/* Add "-" if necessary */
|
||||
if ( negative && zpad )
|
||||
*ptr = '-';
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print character via a printf context
|
||||
*
|
||||
* @v ctx Context
|
||||
* @v c Character
|
||||
*
|
||||
* Call's the printf_context::handler() method and increments
|
||||
* printf_context::len.
|
||||
*/
|
||||
static inline void cputchar ( struct printf_context *ctx, unsigned int c ) {
|
||||
ctx->handler ( ctx, c );
|
||||
++ctx->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a formatted string to a printf context
|
||||
*
|
||||
* @v ctx Context
|
||||
* @v fmt Format string
|
||||
* @v args Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
||||
int flags;
|
||||
int width;
|
||||
uint8_t *length;
|
||||
char *ptr;
|
||||
char tmp_buf[32]; /* 32 is enough for all numerical formats.
|
||||
* Insane width fields could overflow this buffer. */
|
||||
wchar_t *wptr;
|
||||
|
||||
/* Initialise context */
|
||||
ctx->len = 0;
|
||||
|
||||
for ( ; *fmt ; fmt++ ) {
|
||||
/* Pass through ordinary characters */
|
||||
if ( *fmt != '%' ) {
|
||||
cputchar ( ctx, *fmt );
|
||||
continue;
|
||||
}
|
||||
fmt++;
|
||||
/* Process flag characters */
|
||||
flags = 0;
|
||||
for ( ; ; fmt++ ) {
|
||||
if ( *fmt == '#' ) {
|
||||
flags |= ALT_FORM;
|
||||
} else if ( *fmt == '0' ) {
|
||||
flags |= ZPAD;
|
||||
} else {
|
||||
/* End of flag characters */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Process field width */
|
||||
width = 0;
|
||||
for ( ; ; fmt++ ) {
|
||||
if ( ( ( unsigned ) ( *fmt - '0' ) ) < 10 ) {
|
||||
width = ( width * 10 ) + ( *fmt - '0' );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* We don't do floating point */
|
||||
/* Process length modifier */
|
||||
length = &type_sizes[INT_LEN];
|
||||
for ( ; ; fmt++ ) {
|
||||
if ( *fmt == 'h' ) {
|
||||
length--;
|
||||
} else if ( *fmt == 'l' ) {
|
||||
length++;
|
||||
} else if ( *fmt == 'z' ) {
|
||||
length = &type_sizes[SIZE_T_LEN];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Process conversion specifier */
|
||||
ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
|
||||
*ptr = '\0';
|
||||
wptr = NULL;
|
||||
if ( *fmt == 'c' ) {
|
||||
if ( length < &type_sizes[LONG_LEN] ) {
|
||||
cputchar ( ctx, va_arg ( args, unsigned int ) );
|
||||
} else {
|
||||
wchar_t wc;
|
||||
size_t len;
|
||||
|
||||
wc = va_arg ( args, wint_t );
|
||||
len = wcrtomb ( tmp_buf, wc, NULL );
|
||||
tmp_buf[len] = '\0';
|
||||
ptr = tmp_buf;
|
||||
}
|
||||
} else if ( *fmt == 's' ) {
|
||||
if ( length < &type_sizes[LONG_LEN] ) {
|
||||
ptr = va_arg ( args, char * );
|
||||
} else {
|
||||
wptr = va_arg ( args, wchar_t * );
|
||||
}
|
||||
if ( ( ptr == NULL ) && ( wptr == NULL ) )
|
||||
ptr = "<NULL>";
|
||||
} else if ( *fmt == 'p' ) {
|
||||
intptr_t ptrval;
|
||||
|
||||
ptrval = ( intptr_t ) va_arg ( args, void * );
|
||||
ptr = format_hex ( ptr, ptrval, width,
|
||||
( ALT_FORM | LCASE ) );
|
||||
} else if ( ( *fmt & ~0x20 ) == 'X' ) {
|
||||
unsigned long long hex;
|
||||
|
||||
flags |= ( *fmt & 0x20 ); /* LCASE */
|
||||
if ( *length >= sizeof ( unsigned long long ) ) {
|
||||
hex = va_arg ( args, unsigned long long );
|
||||
} else if ( *length >= sizeof ( unsigned long ) ) {
|
||||
hex = va_arg ( args, unsigned long );
|
||||
} else {
|
||||
hex = va_arg ( args, unsigned int );
|
||||
}
|
||||
ptr = format_hex ( ptr, hex, width, flags );
|
||||
} else if ( ( *fmt == 'd' ) || ( *fmt == 'i' ) ){
|
||||
signed long decimal;
|
||||
|
||||
if ( *length >= sizeof ( signed long ) ) {
|
||||
decimal = va_arg ( args, signed long );
|
||||
} else {
|
||||
decimal = va_arg ( args, signed int );
|
||||
}
|
||||
ptr = format_decimal ( ptr, decimal, width, flags );
|
||||
} else {
|
||||
*(--ptr) = *fmt;
|
||||
}
|
||||
/* Write out conversion result */
|
||||
if ( wptr == NULL ) {
|
||||
for ( ; *ptr ; ptr++ ) {
|
||||
cputchar ( ctx, *ptr );
|
||||
}
|
||||
} else {
|
||||
for ( ; *wptr ; wptr++ ) {
|
||||
size_t len = wcrtomb ( tmp_buf, *wptr, NULL );
|
||||
for ( ptr = tmp_buf ; len-- ; ptr++ ) {
|
||||
cputchar ( ctx, *ptr );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx->len;
|
||||
}
|
||||
|
||||
/** Context used by vsnprintf() and friends */
|
||||
struct sputc_context {
|
||||
struct printf_context ctx;
|
||||
/** Buffer for formatted string (used by printf_sputc()) */
|
||||
char *buf;
|
||||
/** Buffer length (used by printf_sputc()) */
|
||||
size_t max_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write character to buffer
|
||||
*
|
||||
* @v ctx Context
|
||||
* @v c Character
|
||||
*/
|
||||
static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
|
||||
struct sputc_context * sctx =
|
||||
container_of ( ctx, struct sputc_context, ctx );
|
||||
|
||||
if ( ctx->len < sctx->max_len )
|
||||
sctx->buf[ctx->len] = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a formatted string to a buffer
|
||||
*
|
||||
* @v buf Buffer into which to write the string
|
||||
* @v size Size of buffer
|
||||
* @v fmt Format string
|
||||
* @v args Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*
|
||||
* If the buffer is too small to contain the string, the returned
|
||||
* length is the length that would have been written had enough space
|
||||
* been available.
|
||||
*/
|
||||
int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) {
|
||||
struct sputc_context sctx;
|
||||
size_t len;
|
||||
size_t end;
|
||||
|
||||
/* Hand off to vcprintf */
|
||||
sctx.ctx.handler = printf_sputc;
|
||||
sctx.buf = buf;
|
||||
sctx.max_len = size;
|
||||
len = vcprintf ( &sctx.ctx, fmt, args );
|
||||
|
||||
/* Add trailing NUL */
|
||||
if ( size ) {
|
||||
end = size - 1;
|
||||
if ( len < end )
|
||||
end = len;
|
||||
buf[end] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a formatted string to a buffer
|
||||
*
|
||||
* @v buf Buffer into which to write the string
|
||||
* @v size Size of buffer
|
||||
* @v fmt Format string
|
||||
* @v ... Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start ( args, fmt );
|
||||
i = vsnprintf ( buf, size, fmt, args );
|
||||
va_end ( args );
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of vsnprintf() that accepts a signed buffer size
|
||||
*
|
||||
* @v buf Buffer into which to write the string
|
||||
* @v size Size of buffer
|
||||
* @v fmt Format string
|
||||
* @v args Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
int vssnprintf ( char *buf, ssize_t ssize, const char *fmt, va_list args ) {
|
||||
|
||||
/* Treat negative buffer size as zero buffer size */
|
||||
if ( ssize < 0 )
|
||||
ssize = 0;
|
||||
|
||||
/* Hand off to vsnprintf */
|
||||
return vsnprintf ( buf, ssize, fmt, args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of vsnprintf() that accepts a signed buffer size
|
||||
*
|
||||
* @v buf Buffer into which to write the string
|
||||
* @v size Size of buffer
|
||||
* @v fmt Format string
|
||||
* @v ... Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ) {
|
||||
va_list args;
|
||||
int len;
|
||||
|
||||
/* Hand off to vssnprintf */
|
||||
va_start ( args, fmt );
|
||||
len = vssnprintf ( buf, ssize, fmt, args );
|
||||
va_end ( args );
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write character to console
|
||||
*
|
||||
* @v ctx Context
|
||||
* @v c Character
|
||||
*/
|
||||
static void printf_putchar ( struct printf_context *ctx __unused,
|
||||
unsigned int c ) {
|
||||
putchar ( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a formatted string to the console
|
||||
*
|
||||
* @v fmt Format string
|
||||
* @v args Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
int vprintf ( const char *fmt, va_list args ) {
|
||||
struct printf_context ctx;
|
||||
|
||||
/* Hand off to vcprintf */
|
||||
ctx.handler = printf_putchar;
|
||||
return vcprintf ( &ctx, fmt, args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a formatted string to the console.
|
||||
*
|
||||
* @v fmt Format string
|
||||
* @v ... Arguments corresponding to the format string
|
||||
* @ret len Length of formatted string
|
||||
*/
|
||||
int printf ( const char *fmt, ... ) {
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start ( args, fmt );
|
||||
i = vprintf ( fmt, args );
|
||||
va_end ( args );
|
||||
return i;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef _IPXE_VSPRINTF_H
|
||||
#define _IPXE_VSPRINTF_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* printf() and friends
|
||||
*
|
||||
* Etherboot's printf() functions understand the following subset of
|
||||
* the standard C printf()'s format specifiers:
|
||||
*
|
||||
* - Flag characters
|
||||
* - '#' - Alternate form (i.e. "0x" prefix)
|
||||
* - '0' - Zero-pad
|
||||
* - Field widths
|
||||
* - Length modifiers
|
||||
* - 'hh' - Signed / unsigned char
|
||||
* - 'h' - Signed / unsigned short
|
||||
* - 'l' - Signed / unsigned long
|
||||
* - 'll' - Signed / unsigned long long
|
||||
* - 'z' - Signed / unsigned size_t
|
||||
* - Conversion specifiers
|
||||
* - 'd' - Signed decimal
|
||||
* - 'x','X' - Unsigned hexadecimal
|
||||
* - 'c' - Character
|
||||
* - 's' - String
|
||||
* - 'p' - Pointer
|
||||
*
|
||||
* Hexadecimal numbers are always zero-padded to the specified field
|
||||
* width (if any); decimal numbers are always space-padded. Decimal
|
||||
* long longs are not supported.
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* A printf context
|
||||
*
|
||||
* Contexts are used in order to be able to share code between
|
||||
* vprintf() and vsnprintf(), without requiring the allocation of a
|
||||
* buffer for vprintf().
|
||||
*/
|
||||
struct printf_context {
|
||||
/**
|
||||
* Character handler
|
||||
*
|
||||
* @v ctx Context
|
||||
* @v c Character
|
||||
*
|
||||
* This method is called for each character written to the
|
||||
* formatted string.
|
||||
*/
|
||||
void ( * handler ) ( struct printf_context *ctx, unsigned int c );
|
||||
/** Length of formatted string
|
||||
*
|
||||
* When handler() is called, @len will be set to the number of
|
||||
* characters written so far (i.e. zero for the first call to
|
||||
* handler()).
|
||||
*/
|
||||
size_t len;
|
||||
};
|
||||
|
||||
extern size_t vcprintf ( struct printf_context *ctx, const char *fmt,
|
||||
va_list args );
|
||||
extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt,
|
||||
va_list args );
|
||||
extern int __attribute__ (( format ( printf, 3, 4 ) ))
|
||||
ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... );
|
||||
|
||||
#endif /* _IPXE_VSPRINTF_H */
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* LZNT1 decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "lznt1.h"
|
||||
|
||||
/**
|
||||
* Decompress LZNT1-compressed data block
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v limit Length of compressed data up to end of block
|
||||
* @v offset Starting offset within compressed data
|
||||
* @v block Decompression buffer for this block, or NULL
|
||||
* @ret out_len Length of decompressed block, or negative error
|
||||
*/
|
||||
static ssize_t lznt1_block ( const void *data, size_t limit, size_t offset,
|
||||
void *block ) {
|
||||
const uint16_t *tuple;
|
||||
const uint8_t *copy_src;
|
||||
uint8_t *copy_dest = block;
|
||||
size_t copy_len;
|
||||
size_t block_out_len = 0;
|
||||
unsigned int split = 12;
|
||||
unsigned int next_threshold = 16;
|
||||
unsigned int tag_bit = 0;
|
||||
unsigned int tag = 0;
|
||||
|
||||
while ( offset != limit ) {
|
||||
|
||||
/* Extract tag */
|
||||
if ( tag_bit == 0 ) {
|
||||
tag = *( ( uint8_t * ) ( data + offset ) );
|
||||
offset++;
|
||||
if ( offset == limit )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate copy source and length */
|
||||
if ( tag & 1 ) {
|
||||
|
||||
/* Compressed value */
|
||||
if ( offset + sizeof ( *tuple ) > limit ) {
|
||||
DBG ( "LZNT1 compressed value overrun at "
|
||||
"%#zx\n", offset );
|
||||
return -1;
|
||||
}
|
||||
tuple = ( data + offset );
|
||||
offset += sizeof ( *tuple );
|
||||
copy_len = LZNT1_VALUE_LEN ( *tuple, split );
|
||||
block_out_len += copy_len;
|
||||
if ( copy_dest ) {
|
||||
copy_src = ( copy_dest -
|
||||
LZNT1_VALUE_OFFSET ( *tuple,
|
||||
split ) );
|
||||
while ( copy_len-- )
|
||||
*(copy_dest++) = *(copy_src++);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Uncompressed value */
|
||||
copy_src = ( data + offset );
|
||||
if ( copy_dest )
|
||||
*(copy_dest++) = *copy_src;
|
||||
offset++;
|
||||
block_out_len++;
|
||||
}
|
||||
|
||||
/* Update split, if applicable */
|
||||
while ( block_out_len > next_threshold ) {
|
||||
split--;
|
||||
next_threshold <<= 1;
|
||||
}
|
||||
|
||||
/* Move to next value */
|
||||
tag >>= 1;
|
||||
tag_bit = ( ( tag_bit + 1 ) % 8 );
|
||||
}
|
||||
|
||||
return block_out_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress LZNT1-compressed data
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v len Length of compressed data
|
||||
* @v buf Decompression buffer, or NULL
|
||||
* @ret out_len Length of decompressed data, or negative error
|
||||
*/
|
||||
ssize_t lznt1_decompress ( const void *data, size_t len, void *buf ) {
|
||||
const uint16_t *header;
|
||||
const uint8_t *end;
|
||||
size_t offset = 0;
|
||||
ssize_t out_len = 0;
|
||||
size_t block_len;
|
||||
size_t limit;
|
||||
void *block;
|
||||
ssize_t block_out_len;
|
||||
|
||||
while ( offset != len ) {
|
||||
|
||||
/* Check for end marker */
|
||||
if ( ( offset + sizeof ( *end ) ) == len ) {
|
||||
end = ( data + offset );
|
||||
if ( *end == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract block header */
|
||||
if ( ( offset + sizeof ( *header ) ) > len ) {
|
||||
DBG ( "LZNT1 block header overrun at %#zx\n", offset );
|
||||
return -1;
|
||||
}
|
||||
header = ( data + offset );
|
||||
offset += sizeof ( *header );
|
||||
|
||||
/* Process block */
|
||||
block_len = LZNT1_BLOCK_LEN ( *header );
|
||||
if ( LZNT1_BLOCK_COMPRESSED ( *header ) ) {
|
||||
|
||||
/* Compressed block */
|
||||
DBG2 ( "LZNT1 compressed block %#zx+%#zx\n",
|
||||
offset, block_len );
|
||||
limit = ( offset + block_len );
|
||||
block = ( buf ? ( buf + out_len ) : NULL );
|
||||
block_out_len = lznt1_block ( data, limit, offset,
|
||||
block );
|
||||
if ( block_out_len < 0 )
|
||||
return block_out_len;
|
||||
offset += block_len;
|
||||
out_len += block_out_len;
|
||||
|
||||
} else {
|
||||
|
||||
/* Uncompressed block */
|
||||
if ( ( offset + block_len ) > len ) {
|
||||
DBG ( "LZNT1 uncompressed block overrun at "
|
||||
"%#zx+%#zx\n", offset, block_len );
|
||||
return -1;
|
||||
}
|
||||
DBG2 ( "LZNT1 uncompressed block %#zx+%#zx\n",
|
||||
offset, block_len );
|
||||
if ( buf ) {
|
||||
memcpy ( ( buf + out_len ), ( data + offset ),
|
||||
block_len );
|
||||
}
|
||||
offset += block_len;
|
||||
out_len += block_len;
|
||||
}
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef _LZNT1_H
|
||||
#define _LZNT1_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* LZNT1 decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Extract LZNT1 block length */
|
||||
#define LZNT1_BLOCK_LEN( header ) ( ( (header) & 0x0fff ) + 1 )
|
||||
|
||||
/** Determine if LZNT1 block is compressed */
|
||||
#define LZNT1_BLOCK_COMPRESSED( header ) ( (header) & 0x8000 )
|
||||
|
||||
/** Extract LZNT1 compressed value length */
|
||||
#define LZNT1_VALUE_LEN( tuple, split ) \
|
||||
( ( (tuple) & ( ( 1 << (split) ) - 1 ) ) + 3 )
|
||||
|
||||
/** Extract LZNT1 compressed value offset */
|
||||
#define LZNT1_VALUE_OFFSET( tuple, split ) ( ( (tuple) >> split ) + 1 )
|
||||
|
||||
extern ssize_t lznt1_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _LZNT1_H */
|
|
@ -0,0 +1,670 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* LZX decompression
|
||||
*
|
||||
* This algorithm is derived jointly from the document "[MS-PATCH]:
|
||||
* LZX DELTA Compression and Decompression", available from
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/cc483133.aspx
|
||||
*
|
||||
* and from the file lzx-decompress.c in the wimlib source code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
#include "lzx.h"
|
||||
|
||||
/** Base positions, indexed by position slot */
|
||||
static unsigned int lzx_position_base[LZX_POSITION_SLOTS];
|
||||
|
||||
/**
|
||||
* Attempt to accumulate bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to accumulate
|
||||
* @v norm_value Accumulated value (normalised to 16 bits)
|
||||
*
|
||||
* Note that there may not be sufficient accumulated bits in the
|
||||
* bitstream; callers must check that sufficient bits are available
|
||||
* before using the value.
|
||||
*/
|
||||
static int lzx_accumulate ( struct lzx *lzx, unsigned int bits ) {
|
||||
const uint16_t *src16;
|
||||
|
||||
/* Accumulate more bits if required */
|
||||
if ( ( lzx->bits < bits ) &&
|
||||
( lzx->input.offset < lzx->input.len ) ) {
|
||||
src16 = ( ( void * ) lzx->input.data + lzx->input.offset );
|
||||
lzx->input.offset += sizeof ( *src16 );
|
||||
lzx->accumulator |= ( *src16 << ( 16 - lzx->bits ) );
|
||||
lzx->bits += 16;
|
||||
}
|
||||
|
||||
return ( lzx->accumulator >> 16 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume accumulated bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to consume
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_consume ( struct lzx *lzx, unsigned int bits ) {
|
||||
|
||||
/* Fail if insufficient bits are available */
|
||||
if ( lzx->bits < bits ) {
|
||||
DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
|
||||
lzx->input.offset, lzx->input.len, lzx->output.offset );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Consume bits */
|
||||
lzx->accumulator <<= bits;
|
||||
lzx->bits -= bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bits from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Number of bits to fetch
|
||||
* @ret value Value, or negative error
|
||||
*/
|
||||
static int lzx_getbits ( struct lzx *lzx, unsigned int bits ) {
|
||||
int norm_value;
|
||||
int rc;
|
||||
|
||||
/* Accumulate more bits if required */
|
||||
norm_value = lzx_accumulate ( lzx, bits );
|
||||
|
||||
/* Consume bits */
|
||||
if ( ( rc = lzx_consume ( lzx, bits ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return ( norm_value >> ( 16 - bits ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Align LZX bitstream for byte access
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v bits Minimum number of padding bits
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_align ( struct lzx *lzx, unsigned int bits ) {
|
||||
int pad;
|
||||
|
||||
/* Get padding bits */
|
||||
pad = lzx_getbits ( lzx, bits );
|
||||
if ( pad < 0 )
|
||||
return pad;
|
||||
|
||||
/* Consume all accumulated bits */
|
||||
lzx_consume ( lzx, lzx->bits );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bytes from LZX bitstream
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v data Data buffer, or NULL
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_getbytes ( struct lzx *lzx, void *data, size_t len ) {
|
||||
|
||||
/* Sanity check */
|
||||
if ( ( lzx->input.offset + len ) > lzx->input.len ) {
|
||||
DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
|
||||
lzx->input.offset, lzx->input.len, lzx->output.offset );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
if ( data )
|
||||
memcpy ( data, ( lzx->input.data + lzx->input.offset ), len );
|
||||
lzx->input.offset += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode LZX Huffman-coded symbol
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v alphabet Huffman alphabet
|
||||
* @ret raw Raw symbol, or negative error
|
||||
*/
|
||||
static int lzx_decode ( struct lzx *lzx, struct huffman_alphabet *alphabet ) {
|
||||
struct huffman_symbols *sym;
|
||||
int huf;
|
||||
int rc;
|
||||
|
||||
/* Accumulate sufficient bits */
|
||||
huf = lzx_accumulate ( lzx, HUFFMAN_BITS );
|
||||
if ( huf < 0 )
|
||||
return huf;
|
||||
|
||||
/* Decode symbol */
|
||||
sym = huffman_sym ( alphabet, huf );
|
||||
|
||||
/* Consume bits */
|
||||
if ( ( rc = lzx_consume ( lzx, huffman_len ( sym ) ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return huffman_raw ( sym, huf );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Huffman alphabet from raw length table
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v count Number of symbols
|
||||
* @v bits Length of each length (in bits)
|
||||
* @v lengths Lengths table to fill in
|
||||
* @v alphabet Huffman alphabet to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_raw_alphabet ( struct lzx *lzx, unsigned int count,
|
||||
unsigned int bits, uint8_t *lengths,
|
||||
struct huffman_alphabet *alphabet ) {
|
||||
unsigned int i;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
/* Read lengths */
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
len = lzx_getbits ( lzx, bits );
|
||||
if ( len < 0 )
|
||||
return len;
|
||||
lengths[i] = len;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( alphabet, lengths, count ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate pretree
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @v count Number of symbols
|
||||
* @v lengths Lengths table to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_pretree ( struct lzx *lzx, unsigned int count,
|
||||
uint8_t *lengths ) {
|
||||
unsigned int i;
|
||||
unsigned int length;
|
||||
int dup = 0;
|
||||
int code;
|
||||
int rc;
|
||||
|
||||
/* Generate pretree alphabet */
|
||||
if ( ( rc = lzx_raw_alphabet ( lzx, LZX_PRETREE_CODES,
|
||||
LZX_PRETREE_BITS, lzx->pretree_lengths,
|
||||
&lzx->pretree ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Read lengths */
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
|
||||
if ( dup ) {
|
||||
|
||||
/* Duplicate previous length */
|
||||
lengths[i] = lengths[ i - 1 ];
|
||||
dup--;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get next code */
|
||||
code = lzx_decode ( lzx, &lzx->pretree );
|
||||
if ( code < 0 )
|
||||
return code;
|
||||
|
||||
/* Interpret code */
|
||||
if ( code <= 16 ) {
|
||||
length = ( ( lengths[i] - code + 17 ) % 17 );
|
||||
} else if ( code == 17 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 4 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 3;
|
||||
} else if ( code == 18 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 5 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 19;
|
||||
} else if ( code == 19 ) {
|
||||
length = 0;
|
||||
dup = lzx_getbits ( lzx, 1 );
|
||||
if ( dup < 0 )
|
||||
return dup;
|
||||
dup += 3;
|
||||
code = lzx_decode ( lzx, &lzx->pretree );
|
||||
if ( code < 0 )
|
||||
return code;
|
||||
length = ( ( lengths[i] - code + 17 ) % 17 );
|
||||
} else {
|
||||
DBG ( "Unrecognised pretree code %d\n", code );
|
||||
return -1;
|
||||
}
|
||||
lengths[i] = length;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if ( dup ) {
|
||||
DBG ( "Pretree duplicate overrun\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate aligned offset Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_alignoffset_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate aligned offset alphabet */
|
||||
if ( ( rc = lzx_raw_alphabet ( lzx, LZX_ALIGNOFFSET_CODES,
|
||||
LZX_ALIGNOFFSET_BITS,
|
||||
lzx->alignoffset_lengths,
|
||||
&lzx->alignoffset ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate main Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_main_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate literal symbols pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, LZX_MAIN_LIT_CODES,
|
||||
lzx->main_lengths.literals ) ) != 0 ) {
|
||||
DBG ( "Could not construct main literal pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate remaining symbols pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, ( LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ),
|
||||
lzx->main_lengths.remainder ) ) != 0 ) {
|
||||
DBG ( "Could not construct main remainder pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &lzx->main, lzx->main_lengths.literals,
|
||||
LZX_MAIN_CODES ) ) != 0 ) {
|
||||
DBG ( "Could not generate main alphabet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate length Huffman alphabet
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_length_alphabet ( struct lzx *lzx ) {
|
||||
int rc;
|
||||
|
||||
/* Generate pretree */
|
||||
if ( ( rc = lzx_pretree ( lzx, LZX_LENGTH_CODES,
|
||||
lzx->length_lengths ) ) != 0 ) {
|
||||
DBG ( "Could not generate length pretree\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &lzx->length, lzx->length_lengths,
|
||||
LZX_LENGTH_CODES ) ) != 0 ) {
|
||||
DBG ( "Could not generate length alphabet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process LZX block header
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_block_header ( struct lzx *lzx ) {
|
||||
size_t block_len;
|
||||
int block_type;
|
||||
int default_len;
|
||||
int len_high;
|
||||
int len_low;
|
||||
int rc;
|
||||
|
||||
/* Get block type */
|
||||
block_type = lzx_getbits ( lzx, LZX_BLOCK_TYPE_BITS );
|
||||
if ( block_type < 0 )
|
||||
return block_type;
|
||||
lzx->block_type = block_type;
|
||||
|
||||
/* Check block length */
|
||||
default_len = lzx_getbits ( lzx, 1 );
|
||||
if ( default_len < 0 )
|
||||
return default_len;
|
||||
if ( default_len ) {
|
||||
block_len = LZX_DEFAULT_BLOCK_LEN;
|
||||
} else {
|
||||
len_high = lzx_getbits ( lzx, 8 );
|
||||
if ( len_high < 0 )
|
||||
return len_high;
|
||||
len_low = lzx_getbits ( lzx, 8 );
|
||||
if ( len_low < 0 )
|
||||
return len_low;
|
||||
block_len = ( ( len_high << 8 ) | len_low );
|
||||
}
|
||||
lzx->output.threshold = ( lzx->output.offset + block_len );
|
||||
|
||||
/* Handle block type */
|
||||
switch ( block_type ) {
|
||||
case LZX_BLOCK_ALIGNOFFSET :
|
||||
/* Generated aligned offset alphabet */
|
||||
if ( ( rc = lzx_alignoffset_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
/* Fall through */
|
||||
case LZX_BLOCK_VERBATIM :
|
||||
/* Generate main alphabet */
|
||||
if ( ( rc = lzx_main_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
/* Generate lengths alphabet */
|
||||
if ( ( rc = lzx_length_alphabet ( lzx ) ) != 0 )
|
||||
return rc;
|
||||
break;
|
||||
case LZX_BLOCK_UNCOMPRESSED :
|
||||
/* Align input stream */
|
||||
if ( ( rc = lzx_align ( lzx, 1 ) ) != 0 )
|
||||
return rc;
|
||||
/* Read new repeated offsets */
|
||||
if ( ( rc = lzx_getbytes ( lzx, &lzx->repeated_offset,
|
||||
sizeof ( lzx->repeated_offset )))!=0)
|
||||
return rc;
|
||||
break;
|
||||
default:
|
||||
DBG ( "Unrecognised block type %d\n", block_type );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process uncompressed data
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lzx_uncompressed ( struct lzx *lzx ) {
|
||||
void *data;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
/* Copy bytes */
|
||||
data = ( lzx->output.data ?
|
||||
( lzx->output.data + lzx->output.offset ) : NULL );
|
||||
len = ( lzx->output.threshold - lzx->output.offset );
|
||||
if ( ( rc = lzx_getbytes ( lzx, data, len ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Align input stream */
|
||||
if ( len % 2 )
|
||||
lzx->input.offset++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an LZX token
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Variable names are chosen to match the LZX specification
|
||||
* pseudo-code.
|
||||
*/
|
||||
static int lzx_token ( struct lzx *lzx ) {
|
||||
unsigned int length_header;
|
||||
unsigned int position_slot;
|
||||
unsigned int offset_bits;
|
||||
unsigned int i;
|
||||
size_t match_offset;
|
||||
size_t match_length;
|
||||
int verbatim_bits;
|
||||
int aligned_bits;
|
||||
int main;
|
||||
int length;
|
||||
uint8_t *copy;
|
||||
|
||||
/* Get main symelse*/
|
||||
main = lzx_decode ( lzx, &lzx->main );
|
||||
if ( main < 0 )
|
||||
return main;
|
||||
|
||||
/* Check for literals */
|
||||
if ( main < LZX_MAIN_LIT_CODES ) {
|
||||
if ( lzx->output.data )
|
||||
lzx->output.data[lzx->output.offset] = main;
|
||||
lzx->output.offset++;
|
||||
return 0;
|
||||
}
|
||||
main -= LZX_MAIN_LIT_CODES;
|
||||
|
||||
/* Calculate the match length */
|
||||
length_header = ( main & 7 );
|
||||
if ( length_header == 7 ) {
|
||||
length = lzx_decode ( lzx, &lzx->length );
|
||||
if ( length < 0 )
|
||||
return length;
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
match_length = ( length_header + 2 + length );
|
||||
|
||||
/* Calculate the position slot */
|
||||
position_slot = ( main >> 3 );
|
||||
if ( position_slot < LZX_REPEATED_OFFSETS ) {
|
||||
|
||||
/* Repeated offset */
|
||||
match_offset = lzx->repeated_offset[position_slot];
|
||||
lzx->repeated_offset[position_slot] = lzx->repeated_offset[0];
|
||||
lzx->repeated_offset[0] = match_offset;
|
||||
|
||||
} else {
|
||||
|
||||
/* Non-repeated offset */
|
||||
offset_bits = lzx_footer_bits ( position_slot );
|
||||
if ( ( lzx->block_type == LZX_BLOCK_ALIGNOFFSET ) &&
|
||||
( offset_bits >= 3 ) ) {
|
||||
verbatim_bits = lzx_getbits ( lzx, ( offset_bits - 3 ));
|
||||
if ( verbatim_bits < 0 )
|
||||
return verbatim_bits;
|
||||
verbatim_bits <<= 3;
|
||||
aligned_bits = lzx_decode ( lzx, &lzx->alignoffset );
|
||||
if ( aligned_bits < 0 )
|
||||
return aligned_bits;
|
||||
} else {
|
||||
verbatim_bits = lzx_getbits ( lzx, offset_bits );
|
||||
if ( verbatim_bits < 0 )
|
||||
return verbatim_bits;
|
||||
aligned_bits = 0;
|
||||
}
|
||||
match_offset = ( lzx_position_base[position_slot] +
|
||||
verbatim_bits + aligned_bits - 2 );
|
||||
|
||||
/* Update repeated offset list */
|
||||
for ( i = ( LZX_REPEATED_OFFSETS - 1 ) ; i > 0 ; i-- )
|
||||
lzx->repeated_offset[i] = lzx->repeated_offset[ i - 1 ];
|
||||
lzx->repeated_offset[0] = match_offset;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
if ( match_offset > lzx->output.offset ) {
|
||||
DBG ( "LZX match underrun out %#zx offset %#zx len %#zx\n",
|
||||
lzx->output.offset, match_offset, match_length );
|
||||
return -1;
|
||||
}
|
||||
if ( lzx->output.data ) {
|
||||
copy = &lzx->output.data[lzx->output.offset];
|
||||
for ( i = 0 ; i < match_length ; i++ )
|
||||
copy[i] = copy[ i - match_offset ];
|
||||
}
|
||||
lzx->output.offset += match_length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate E8 jump addresses
|
||||
*
|
||||
* @v lzx Decompressor
|
||||
*/
|
||||
static void lzx_translate_jumps ( struct lzx *lzx ) {
|
||||
size_t offset;
|
||||
int32_t *target;
|
||||
|
||||
/* Sanity check */
|
||||
if ( lzx->output.offset < 10 )
|
||||
return;
|
||||
|
||||
/* Scan for jump instructions */
|
||||
for ( offset = 0 ; offset < ( lzx->output.offset - 10 ) ; offset++ ) {
|
||||
|
||||
/* Check for jump instruction */
|
||||
if ( lzx->output.data[offset] != 0xe8 )
|
||||
continue;
|
||||
|
||||
/* Translate jump target */
|
||||
target = ( ( int32_t * ) &lzx->output.data[ offset + 1 ] );
|
||||
if ( *target >= 0 ) {
|
||||
if ( *target < LZX_WIM_MAGIC_FILESIZE )
|
||||
*target -= offset;
|
||||
} else {
|
||||
if ( *target >= -( ( int32_t ) offset ) )
|
||||
*target += LZX_WIM_MAGIC_FILESIZE;
|
||||
}
|
||||
offset += sizeof ( *target );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress LZX-compressed data
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v len Length of compressed data
|
||||
* @v buf Decompression buffer, or NULL
|
||||
* @ret out_len Length of decompressed data, or negative error
|
||||
*/
|
||||
ssize_t lzx_decompress ( const void *data, size_t len, void *buf ) {
|
||||
struct lzx lzx;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
if ( len % 2 ) {
|
||||
DBG ( "LZX cannot handle odd-length input data\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise global state, if required */
|
||||
if ( ! lzx_position_base[ LZX_POSITION_SLOTS - 1 ] ) {
|
||||
for ( i = 1 ; i < LZX_POSITION_SLOTS ; i++ ) {
|
||||
lzx_position_base[i] =
|
||||
( lzx_position_base[i-1] +
|
||||
( 1 << lzx_footer_bits ( i - 1 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise decompressor */
|
||||
memset ( &lzx, 0, sizeof ( lzx ) );
|
||||
lzx.input.data = data;
|
||||
lzx.input.len = len;
|
||||
lzx.output.data = buf;
|
||||
for ( i = 0 ; i < LZX_REPEATED_OFFSETS ; i++ )
|
||||
lzx.repeated_offset[i] = 1;
|
||||
|
||||
/* Process blocks */
|
||||
while ( lzx.input.offset < lzx.input.len ) {
|
||||
|
||||
/* Process block header */
|
||||
if ( ( rc = lzx_block_header ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Process block contents */
|
||||
if ( lzx.block_type == LZX_BLOCK_UNCOMPRESSED ) {
|
||||
|
||||
/* Copy uncompressed data */
|
||||
if ( ( rc = lzx_uncompressed ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
} else {
|
||||
|
||||
/* Process token stream */
|
||||
while ( lzx.output.offset < lzx.output.threshold ) {
|
||||
if ( ( rc = lzx_token ( &lzx ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Postprocess to undo E8 jump compression */
|
||||
if ( lzx.output.data )
|
||||
lzx_translate_jumps ( &lzx );
|
||||
|
||||
return lzx.output.offset;
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
#ifndef _LZX_H
|
||||
#define _LZX_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* LZX decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "huffman.h"
|
||||
|
||||
/** Number of aligned offset codes */
|
||||
#define LZX_ALIGNOFFSET_CODES 8
|
||||
|
||||
/** Aligned offset code length (in bits) */
|
||||
#define LZX_ALIGNOFFSET_BITS 3
|
||||
|
||||
/** Number of pretree codes */
|
||||
#define LZX_PRETREE_CODES 20
|
||||
|
||||
/** Pretree code length (in bits) */
|
||||
#define LZX_PRETREE_BITS 4
|
||||
|
||||
/** Number of literal main codes */
|
||||
#define LZX_MAIN_LIT_CODES 256
|
||||
|
||||
/** Number of position slots */
|
||||
#define LZX_POSITION_SLOTS 30
|
||||
|
||||
/** Number of main codes */
|
||||
#define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) )
|
||||
|
||||
/** Number of length codes */
|
||||
#define LZX_LENGTH_CODES 249
|
||||
|
||||
/** Block type length (in bits) */
|
||||
#define LZX_BLOCK_TYPE_BITS 3
|
||||
|
||||
/** Default block length */
|
||||
#define LZX_DEFAULT_BLOCK_LEN 32768
|
||||
|
||||
/** Number of repeated offsets */
|
||||
#define LZX_REPEATED_OFFSETS 3
|
||||
|
||||
/** Don't ask */
|
||||
#define LZX_WIM_MAGIC_FILESIZE 12000000
|
||||
|
||||
/** Block types */
|
||||
enum lzx_block_type {
|
||||
/** Verbatim block */
|
||||
LZX_BLOCK_VERBATIM = 1,
|
||||
/** Aligned offset block */
|
||||
LZX_BLOCK_ALIGNOFFSET = 2,
|
||||
/** Uncompressed block */
|
||||
LZX_BLOCK_UNCOMPRESSED = 3,
|
||||
};
|
||||
|
||||
/** An LZX input stream */
|
||||
struct lzx_input_stream {
|
||||
/** Data */
|
||||
const uint8_t *data;
|
||||
/** Length */
|
||||
size_t len;
|
||||
/** Offset within stream */
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
/** An LZX output stream */
|
||||
struct lzx_output_stream {
|
||||
/** Data, or NULL */
|
||||
uint8_t *data;
|
||||
/** Offset within stream */
|
||||
size_t offset;
|
||||
/** End of current block within stream */
|
||||
size_t threshold;
|
||||
};
|
||||
|
||||
/** LZX decompressor */
|
||||
struct lzx {
|
||||
/** Input stream */
|
||||
struct lzx_input_stream input;
|
||||
/** Output stream */
|
||||
struct lzx_output_stream output;
|
||||
/** Accumulator */
|
||||
uint32_t accumulator;
|
||||
/** Number of bits in accumulator */
|
||||
unsigned int bits;
|
||||
/** Block type */
|
||||
enum lzx_block_type block_type;
|
||||
/** Repeated offsets */
|
||||
unsigned int repeated_offset[LZX_REPEATED_OFFSETS];
|
||||
|
||||
/** Aligned offset Huffman alphabet */
|
||||
struct huffman_alphabet alignoffset;
|
||||
/** Aligned offset raw symbols
|
||||
*
|
||||
* Must immediately follow the aligned offset Huffman
|
||||
* alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t alignoffset_raw[LZX_ALIGNOFFSET_CODES];
|
||||
/** Aligned offset code lengths */
|
||||
uint8_t alignoffset_lengths[LZX_ALIGNOFFSET_CODES];
|
||||
|
||||
/** Pretree Huffman alphabet */
|
||||
struct huffman_alphabet pretree;
|
||||
/** Pretree raw symbols
|
||||
*
|
||||
* Must immediately follow the pretree Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t pretree_raw[LZX_PRETREE_CODES];
|
||||
/** Preetree code lengths */
|
||||
uint8_t pretree_lengths[LZX_PRETREE_CODES];
|
||||
|
||||
/** Main Huffman alphabet */
|
||||
struct huffman_alphabet main;
|
||||
/** Main raw symbols
|
||||
*
|
||||
* Must immediately follow the main Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t main_raw[LZX_MAIN_CODES];
|
||||
/** Main code lengths */
|
||||
struct {
|
||||
/** Literals */
|
||||
uint8_t literals[LZX_MAIN_LIT_CODES];
|
||||
/** Remaining symbols */
|
||||
uint8_t remainder[ LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ];
|
||||
} __attribute__ (( packed )) main_lengths;
|
||||
|
||||
/** Length Huffman alphabet */
|
||||
struct huffman_alphabet length;
|
||||
/** Length raw symbols
|
||||
*
|
||||
* Must immediately follow the length Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t length_raw[LZX_LENGTH_CODES];
|
||||
/** Length code lengths */
|
||||
uint8_t length_lengths[LZX_LENGTH_CODES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate number of footer bits for a given position slot
|
||||
*
|
||||
* @v position_slot Position slot
|
||||
* @ret footer_bits Number of footer bits
|
||||
*/
|
||||
static inline unsigned int lzx_footer_bits ( unsigned int position_slot ) {
|
||||
|
||||
if ( position_slot < 2 ) {
|
||||
return 0;
|
||||
} else if ( position_slot < 38 ) {
|
||||
return ( ( position_slot / 2 ) - 1 );
|
||||
} else {
|
||||
return 17;
|
||||
}
|
||||
}
|
||||
|
||||
extern ssize_t lzx_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _LZX_H */
|
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Main entry point
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "wimboot.h"
|
||||
#include "peloader.h"
|
||||
#include "int13.h"
|
||||
#include "vdisk.h"
|
||||
#include "cpio.h"
|
||||
#include "lznt1.h"
|
||||
#include "xca.h"
|
||||
#include "cmdline.h"
|
||||
#include "wimpatch.h"
|
||||
#include "wimfile.h"
|
||||
#include "pause.h"
|
||||
#include "paging.h"
|
||||
#include "memmap.h"
|
||||
|
||||
/** Start of our image (defined by linker) */
|
||||
extern char _start[];
|
||||
|
||||
/** End of our image (defined by linker) */
|
||||
extern char _end[];
|
||||
|
||||
/** Command line */
|
||||
char *cmdline;
|
||||
|
||||
/** initrd */
|
||||
void *initrd;
|
||||
|
||||
/** Length of initrd */
|
||||
size_t initrd_len;
|
||||
|
||||
/** bootmgr.exe path within WIM */
|
||||
static const wchar_t bootmgr_path[] = L"\\Windows\\Boot\\PXE\\bootmgr.exe";
|
||||
|
||||
/** Other paths within WIM */
|
||||
static const wchar_t *wim_paths[] = {
|
||||
L"\\Windows\\Boot\\DVD\\PCAT\\boot.sdi",
|
||||
L"\\Windows\\Boot\\DVD\\PCAT\\BCD",
|
||||
L"\\Windows\\Boot\\Fonts\\segmono_boot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\segoen_slboot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\segoe_slboot.ttf",
|
||||
L"\\Windows\\Boot\\Fonts\\wgl4_boot.ttf",
|
||||
L"\\sms\\boot\\boot.sdi",
|
||||
NULL
|
||||
};
|
||||
|
||||
/** bootmgr.exe file */
|
||||
static struct vdisk_file *bootmgr;
|
||||
|
||||
/** WIM image file */
|
||||
static struct vdisk_file *bootwim;
|
||||
|
||||
/** Minimal length of embedded bootmgr.exe */
|
||||
#define BOOTMGR_MIN_LEN 16384
|
||||
|
||||
/** 1MB memory threshold */
|
||||
#define ADDR_1MB 0x00100000
|
||||
|
||||
/** 2GB memory threshold */
|
||||
#define ADDR_2GB 0x80000000
|
||||
|
||||
/** Memory regions */
|
||||
enum {
|
||||
WIMBOOT_REGION = 0,
|
||||
PE_REGION,
|
||||
INITRD_REGION,
|
||||
NUM_REGIONS
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap interrupt callback
|
||||
*
|
||||
* @v params Parameters
|
||||
*/
|
||||
static void call_interrupt_wrapper ( struct bootapp_callback_params *params ) {
|
||||
struct paging_state state;
|
||||
uint16_t *attributes;
|
||||
|
||||
/* Handle/modify/pass-through interrupt as required */
|
||||
if ( params->vector.interrupt == 0x13 ) {
|
||||
|
||||
/* Enable paging */
|
||||
enable_paging ( &state );
|
||||
|
||||
/* Intercept INT 13 calls for the emulated drive */
|
||||
emulate_int13 ( params );
|
||||
|
||||
/* Disable paging */
|
||||
disable_paging ( &state );
|
||||
|
||||
} else if ( ( params->vector.interrupt == 0x10 ) &&
|
||||
( params->ax == 0x4f01 ) &&
|
||||
( ! cmdline_gui ) ) {
|
||||
|
||||
/* Mark all VESA video modes as unsupported */
|
||||
attributes = REAL_PTR ( params->es, params->di );
|
||||
call_interrupt ( params );
|
||||
*attributes &= ~0x0001;
|
||||
|
||||
} else {
|
||||
|
||||
/* Pass through interrupt */
|
||||
call_interrupt ( params );
|
||||
}
|
||||
}
|
||||
|
||||
/** Real-mode callback functions */
|
||||
static struct bootapp_callback_functions callback_fns = {
|
||||
.call_interrupt = call_interrupt_wrapper,
|
||||
.call_real = call_real,
|
||||
};
|
||||
|
||||
/** Real-mode callbacks */
|
||||
static struct bootapp_callback callback = {
|
||||
.fns = &callback_fns,
|
||||
};
|
||||
|
||||
/** Boot application descriptor set */
|
||||
static struct {
|
||||
/** Boot application descriptor */
|
||||
struct bootapp_descriptor bootapp;
|
||||
/** Boot application memory descriptor */
|
||||
struct bootapp_memory_descriptor memory;
|
||||
/** Boot application memory descriptor regions */
|
||||
struct bootapp_memory_region regions[NUM_REGIONS];
|
||||
/** Boot application entry descriptor */
|
||||
struct bootapp_entry_descriptor entry;
|
||||
struct bootapp_entry_wtf1_descriptor wtf1;
|
||||
struct bootapp_entry_wtf2_descriptor wtf2;
|
||||
struct bootapp_entry_wtf3_descriptor wtf3;
|
||||
struct bootapp_entry_wtf3_descriptor wtf3_copy;
|
||||
/** Boot application callback descriptor */
|
||||
struct bootapp_callback_descriptor callback;
|
||||
/** Boot application pointless descriptor */
|
||||
struct bootapp_pointless_descriptor pointless;
|
||||
} __attribute__ (( packed )) bootapps = {
|
||||
.bootapp = {
|
||||
.signature = BOOTAPP_SIGNATURE,
|
||||
.version = BOOTAPP_VERSION,
|
||||
.len = sizeof ( bootapps ),
|
||||
.arch = BOOTAPP_ARCH_I386,
|
||||
.memory = offsetof ( typeof ( bootapps ), memory ),
|
||||
.entry = offsetof ( typeof ( bootapps ), entry ),
|
||||
.xxx = offsetof ( typeof ( bootapps ), wtf3_copy ),
|
||||
.callback = offsetof ( typeof ( bootapps ), callback ),
|
||||
.pointless = offsetof ( typeof ( bootapps ), pointless ),
|
||||
},
|
||||
.memory = {
|
||||
.version = BOOTAPP_MEMORY_VERSION,
|
||||
.len = sizeof ( bootapps.memory ),
|
||||
.num_regions = NUM_REGIONS,
|
||||
.region_len = sizeof ( bootapps.regions[0] ),
|
||||
.reserved_len = sizeof ( bootapps.regions[0].reserved ),
|
||||
},
|
||||
.entry = {
|
||||
.signature = BOOTAPP_ENTRY_SIGNATURE,
|
||||
.flags = BOOTAPP_ENTRY_FLAGS,
|
||||
},
|
||||
.wtf1 = {
|
||||
.flags = 0x11000001,
|
||||
.len = sizeof ( bootapps.wtf1 ),
|
||||
.extra_len = ( sizeof ( bootapps.wtf2 ) +
|
||||
sizeof ( bootapps.wtf3 ) ),
|
||||
},
|
||||
.wtf3 = {
|
||||
.flags = 0x00000006,
|
||||
.len = sizeof ( bootapps.wtf3 ),
|
||||
.boot_partition_offset = ( VDISK_VBR_LBA * VDISK_SECTOR_SIZE ),
|
||||
.xxx = 0x01,
|
||||
.mbr_signature = VDISK_MBR_SIGNATURE,
|
||||
},
|
||||
.wtf3_copy = {
|
||||
.flags = 0x00000006,
|
||||
.len = sizeof ( bootapps.wtf3 ),
|
||||
.boot_partition_offset = ( VDISK_VBR_LBA * VDISK_SECTOR_SIZE ),
|
||||
.xxx = 0x01,
|
||||
.mbr_signature = VDISK_MBR_SIGNATURE,
|
||||
},
|
||||
.callback = {
|
||||
.callback = &callback,
|
||||
},
|
||||
.pointless = {
|
||||
.version = BOOTAPP_POINTLESS_VERSION,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if a paragraph is empty
|
||||
*
|
||||
* @v pgh Paragraph
|
||||
* @ret is_empty Paragraph is empty (all zeroes)
|
||||
*/
|
||||
static int is_empty_pgh ( const void *pgh ) {
|
||||
const uint32_t *dwords = pgh;
|
||||
|
||||
return ( ( dwords[0] | dwords[1] | dwords[2] | dwords[3] ) == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file
|
||||
*
|
||||
* @v file Virtual file
|
||||
* @v data Data buffer
|
||||
* @v offset Offset
|
||||
* @v len Length
|
||||
*/
|
||||
static void read_file ( struct vdisk_file *file, void *data, size_t offset,
|
||||
size_t len ) {
|
||||
|
||||
memcpy ( data, ( file->opaque + offset ), len );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add embedded bootmgr.exe extracted from bootmgr
|
||||
*
|
||||
* @v data File data
|
||||
* @v len Length
|
||||
* @ret file Virtual file, or NULL
|
||||
*
|
||||
* bootmgr.exe is awkward to obtain, since it is not available as a
|
||||
* standalone file on the installation media, or on an installed
|
||||
* system, or in a Windows PE image as created by WAIK or WADK. It
|
||||
* can be extracted from a typical boot.wim image using ImageX, but
|
||||
* this requires installation of the WAIK/WADK/wimlib.
|
||||
*
|
||||
* A compressed version of bootmgr.exe is contained within bootmgr,
|
||||
* which is trivial to obtain.
|
||||
*/
|
||||
static struct vdisk_file * add_bootmgr ( const void *data, size_t len ) {
|
||||
const uint8_t *compressed;
|
||||
size_t offset;
|
||||
size_t compressed_len;
|
||||
ssize_t ( * decompress ) ( const void *data, size_t len, void *buf );
|
||||
ssize_t decompressed_len;
|
||||
size_t padded_len;
|
||||
|
||||
/* Look for an embedded compressed bootmgr.exe on an
|
||||
* eight-byte boundary.
|
||||
*/
|
||||
for ( offset = BOOTMGR_MIN_LEN ; offset < ( len - BOOTMGR_MIN_LEN ) ;
|
||||
offset += 0x08 ) {
|
||||
|
||||
/* Initialise checks */
|
||||
decompress = NULL;
|
||||
compressed = ( data + offset );
|
||||
compressed_len = ( len - offset );
|
||||
|
||||
/* Check for an embedded LZNT1-compressed bootmgr.exe.
|
||||
* Since there is no way for LZNT1 to compress the
|
||||
* initial "MZ" bytes of bootmgr.exe, we look for this
|
||||
* signature starting three bytes after a paragraph
|
||||
* boundary, with a preceding tag byte indicating that
|
||||
* these two bytes would indeed be uncompressed.
|
||||
*/
|
||||
if ( ( ( offset & 0x0f ) == 0x00 ) &&
|
||||
( ( compressed[0x02] & 0x03 ) == 0x00 ) &&
|
||||
( compressed[0x03] == 'M' ) &&
|
||||
( compressed[0x04] == 'Z' ) ) {
|
||||
DBG ( "...checking for LZNT1-compressed bootmgr.exe at "
|
||||
"+%#zx\n", offset );
|
||||
decompress = lznt1_decompress;
|
||||
}
|
||||
|
||||
/* Check for an embedded XCA-compressed bootmgr.exe.
|
||||
* The bytes 0x00, 'M', and 'Z' will always be
|
||||
* present, and so the corresponding symbols must have
|
||||
* a non-zero Huffman length. The embedded image
|
||||
* tends to have a large block of zeroes immediately
|
||||
* beforehand, which we check for. It's implausible
|
||||
* that the compressed data could contain substantial
|
||||
* runs of zeroes, so we check for that too, in order
|
||||
* to eliminate some common false positive matches.
|
||||
*/
|
||||
if ( ( ( compressed[0x00] & 0x0f ) != 0x00 ) &&
|
||||
( ( compressed[0x26] & 0xf0 ) != 0x00 ) &&
|
||||
( ( compressed[0x2d] & 0x0f ) != 0x00 ) &&
|
||||
( is_empty_pgh ( compressed - 0x10 ) ) &&
|
||||
( ! is_empty_pgh ( ( compressed + 0x400 ) ) ) &&
|
||||
( ! is_empty_pgh ( ( compressed + 0x800 ) ) ) &&
|
||||
( ! is_empty_pgh ( ( compressed + 0xc00 ) ) ) ) {
|
||||
DBG ( "...checking for XCA-compressed bootmgr.exe at "
|
||||
"+%#zx\n", offset );
|
||||
decompress = xca_decompress;
|
||||
}
|
||||
|
||||
/* If we have not found a possible bootmgr.exe, skip
|
||||
* to the next offset.
|
||||
*/
|
||||
if ( ! decompress )
|
||||
continue;
|
||||
|
||||
/* Find length of decompressed image */
|
||||
decompressed_len = decompress ( compressed, compressed_len,
|
||||
NULL );
|
||||
if ( decompressed_len < 0 ) {
|
||||
/* May be a false positive signature match */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Prepend decompressed image to initrd */
|
||||
DBG ( "...extracting embedded bootmgr.exe\n" );
|
||||
padded_len = ( ( decompressed_len + PAGE_SIZE - 1 ) &
|
||||
~( PAGE_SIZE - 1 ) );
|
||||
initrd -= padded_len;
|
||||
initrd_len += padded_len;
|
||||
decompress ( compressed, compressed_len, initrd );
|
||||
|
||||
/* Add decompressed image */
|
||||
return vdisk_add_file ( "bootmgr.exe", initrd,
|
||||
decompressed_len, read_file );
|
||||
}
|
||||
|
||||
DBG ( "...no embedded bootmgr.exe found\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* File handler
|
||||
*
|
||||
* @v name File name
|
||||
* @v data File data
|
||||
* @v len Length
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int add_file ( const char *name, void *data, size_t len ) {
|
||||
struct vdisk_file *file;
|
||||
|
||||
/* Store file */
|
||||
file = vdisk_add_file ( name, data, len, read_file );
|
||||
|
||||
/* Check for special-case files */
|
||||
if ( strcasecmp ( name, "bootmgr.exe" ) == 0 ) {
|
||||
DBG ( "...found bootmgr.exe\n" );
|
||||
bootmgr = file;
|
||||
} else if ( strcasecmp ( name, "bootmgr" ) == 0 ) {
|
||||
DBG ( "...found bootmgr\n" );
|
||||
if ( ( ! bootmgr ) &&
|
||||
( bootmgr = add_bootmgr ( data, len ) ) ) {
|
||||
DBG ( "...extracted bootmgr.exe\n" );
|
||||
}
|
||||
} else if ( strcasecmp ( ( name + strlen ( name ) - 4 ),
|
||||
".wim" ) == 0 ) {
|
||||
DBG ( "...found WIM file %s\n", name );
|
||||
bootwim = file;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocate data between 1MB and 2GB if possible
|
||||
*
|
||||
* @v data Start of data
|
||||
* @v len Length of data
|
||||
* @ret start Start address
|
||||
*/
|
||||
static void * relocate_memory_low ( void *data, size_t len ) {
|
||||
struct e820_entry *e820 = NULL;
|
||||
uint64_t end;
|
||||
intptr_t start;
|
||||
|
||||
/* Read system memory map */
|
||||
while ( ( e820 = memmap_next ( e820 ) ) != NULL ) {
|
||||
|
||||
/* Find highest compatible placement within this region */
|
||||
end = ( e820->start + e820->len );
|
||||
start = ( ( end > ADDR_2GB ) ? ADDR_2GB : end );
|
||||
if ( start < len )
|
||||
continue;
|
||||
start -= len;
|
||||
start &= ~( PAGE_SIZE - 1 );
|
||||
if ( start < e820->start )
|
||||
continue;
|
||||
if ( start < ADDR_1MB )
|
||||
continue;
|
||||
|
||||
/* Relocate to this region */
|
||||
memmove ( ( void * ) start, data, len );
|
||||
return ( ( void * ) start );
|
||||
}
|
||||
|
||||
/* Leave at original location */
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point
|
||||
*
|
||||
*/
|
||||
int main ( void ) {
|
||||
size_t padded_len;
|
||||
void *raw_pe;
|
||||
struct loaded_pe pe;
|
||||
struct paging_state state;
|
||||
uint64_t initrd_phys;
|
||||
|
||||
/* Initialise stack cookie */
|
||||
init_cookie();
|
||||
|
||||
/* Print welcome banner */
|
||||
printf ( "\n\nBooting wim file...... (This may take a few minutes, please wait)\n\n");
|
||||
//printf ( "\n\nwimboot " VERSION " -- Windows Imaging Format "
|
||||
// "bootloader -- https://ipxe.org/wimboot\n\n" );
|
||||
|
||||
/* Process command line */
|
||||
process_cmdline ( cmdline );
|
||||
|
||||
/* Initialise paging */
|
||||
init_paging();
|
||||
|
||||
/* Enable paging */
|
||||
enable_paging ( &state );
|
||||
|
||||
/* Relocate initrd below 2GB if possible, to avoid collisions */
|
||||
DBG ( "Found initrd at [%p,%p)\n", initrd, ( initrd + initrd_len ) );
|
||||
initrd = relocate_memory_low ( initrd, initrd_len );
|
||||
DBG ( "Placing initrd at [%p,%p)\n", initrd, ( initrd + initrd_len ) );
|
||||
|
||||
/* Extract files from initrd */
|
||||
if ( cpio_extract ( initrd, initrd_len, add_file ) != 0 )
|
||||
die ( "FATAL: could not extract initrd files\n" );
|
||||
|
||||
/* Process WIM image */
|
||||
if ( bootwim ) {
|
||||
vdisk_patch_file ( bootwim, patch_wim );
|
||||
if ( ( ! bootmgr ) &&
|
||||
( bootmgr = wim_add_file ( bootwim, cmdline_index,
|
||||
bootmgr_path,
|
||||
L"bootmgr.exe" ) ) ) {
|
||||
DBG ( "...extracted bootmgr.exe\n" );
|
||||
}
|
||||
wim_add_files ( bootwim, cmdline_index, wim_paths );
|
||||
}
|
||||
|
||||
/* Add INT 13 drive */
|
||||
callback.drive = initialise_int13();
|
||||
|
||||
/* Read bootmgr.exe into memory */
|
||||
if ( ! bootmgr )
|
||||
die ( "FATAL: no bootmgr.exe\n" );
|
||||
if ( bootmgr->read == read_file ) {
|
||||
raw_pe = bootmgr->opaque;
|
||||
} else {
|
||||
padded_len = ( ( bootmgr->len + PAGE_SIZE - 1 ) &
|
||||
~( PAGE_SIZE -1 ) );
|
||||
raw_pe = ( initrd - padded_len );
|
||||
bootmgr->read ( bootmgr, raw_pe, 0, bootmgr->len );
|
||||
}
|
||||
|
||||
/* Load bootmgr.exe into memory */
|
||||
if ( load_pe ( raw_pe, bootmgr->len, &pe ) != 0 )
|
||||
die ( "FATAL: Could not load bootmgr.exe\n" );
|
||||
|
||||
/* Relocate initrd above 4GB if possible, to free up 32-bit memory */
|
||||
initrd_phys = relocate_memory_high ( initrd, initrd_len );
|
||||
DBG ( "Placing initrd at physical [%#llx,%#llx)\n",
|
||||
initrd_phys, ( initrd_phys + initrd_len ) );
|
||||
|
||||
/* Complete boot application descriptor set */
|
||||
bootapps.bootapp.pe_base = pe.base;
|
||||
bootapps.bootapp.pe_len = pe.len;
|
||||
bootapps.regions[WIMBOOT_REGION].start_page = page_start ( _start );
|
||||
bootapps.regions[WIMBOOT_REGION].num_pages = page_len ( _start, _end );
|
||||
bootapps.regions[PE_REGION].start_page = page_start ( pe.base );
|
||||
bootapps.regions[PE_REGION].num_pages =
|
||||
page_len ( pe.base, ( pe.base + pe.len ) );
|
||||
bootapps.regions[INITRD_REGION].start_page =
|
||||
( initrd_phys / PAGE_SIZE );
|
||||
bootapps.regions[INITRD_REGION].num_pages =
|
||||
page_len ( initrd, initrd + initrd_len );
|
||||
|
||||
/* Omit initrd region descriptor if located above 4GB */
|
||||
if ( initrd_phys >= ADDR_4GB )
|
||||
bootapps.memory.num_regions--;
|
||||
|
||||
/* Disable paging */
|
||||
disable_paging ( &state );
|
||||
|
||||
/* Jump to PE image */
|
||||
DBG ( "Entering bootmgr.exe with parameters at %p\n", &bootapps );
|
||||
if ( cmdline_pause )
|
||||
pause();
|
||||
pe.entry ( &bootapps.bootapp );
|
||||
die ( "FATAL: bootmgr.exe returned\n" );
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Memory map
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "wimboot.h"
|
||||
#include "memmap.h"
|
||||
|
||||
/** Buffer for INT 15,e820 calls */
|
||||
static struct e820_entry e820_buf __attribute__ (( section ( ".bss16" ) ));
|
||||
|
||||
/** Continuation value for next INT 15,e820 call */
|
||||
static uint32_t e820_ebx;
|
||||
|
||||
/**
|
||||
* Get system memory map entry
|
||||
*
|
||||
* @v prev Previous system memory map entry, or NULL at start
|
||||
* @v next Next system memory map entry, or NULL at end
|
||||
*/
|
||||
struct e820_entry * memmap_next ( struct e820_entry *prev ) {
|
||||
struct bootapp_callback_params params;
|
||||
|
||||
/* Reset buffer and continuation value if restarting */
|
||||
if ( ! prev ) {
|
||||
memset ( &e820_buf, 0, sizeof ( e820_buf ) );
|
||||
e820_ebx = 0;
|
||||
} else if ( e820_ebx == 0 ) {
|
||||
/* Reach the end */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read system memory map */
|
||||
memset ( ¶ms, 0, sizeof ( params ) );
|
||||
do {
|
||||
|
||||
/* Call INT 15,e820 */
|
||||
params.vector.interrupt = 0x15;
|
||||
params.eax = 0xe820;
|
||||
params.ebx = e820_ebx;
|
||||
params.ecx = sizeof ( e820_buf );
|
||||
params.edx = E820_SMAP;
|
||||
params.es = BASE_SEG;
|
||||
params.edi = ( ( ( void * ) &e820_buf ) -
|
||||
( ( void * ) BASE_ADDRESS ) );
|
||||
call_interrupt ( ¶ms );
|
||||
|
||||
/* Record continuation value */
|
||||
e820_ebx = params.ebx;
|
||||
|
||||
/* Check result */
|
||||
if ( params.eflags & CF ) {
|
||||
DBG ( "INT 15,e820 failed: error %02x\n", params.ah );
|
||||
break;
|
||||
}
|
||||
if ( params.eax != E820_SMAP ) {
|
||||
DBG ( "INT 15,e820 invalid SMAP signature %08x\n",
|
||||
params.eax );
|
||||
break;
|
||||
}
|
||||
DBG2 ( "INT 15,e820 region [%llx,%llx) type %d\n",
|
||||
e820_buf.start, ( e820_buf.start + e820_buf.len ),
|
||||
e820_buf.type );
|
||||
|
||||
/* Skip non-RAM regions */
|
||||
if ( e820_buf.type != E820_TYPE_RAM )
|
||||
continue;
|
||||
if ( params.ecx > offsetof ( typeof ( e820_buf ), attrs ) ) {
|
||||
if ( ! ( e820_buf.attrs & E820_ATTR_ENABLED ) )
|
||||
continue;
|
||||
if ( e820_buf.attrs & E820_ATTR_NONVOLATILE )
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Return this region */
|
||||
return &e820_buf;
|
||||
|
||||
} while ( e820_ebx != 0 );
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef _MEMMAP_H
|
||||
#define _MEMMAP_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Memory map
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Magic value for INT 15,e820 calls */
|
||||
#define E820_SMAP 0x534d4150
|
||||
|
||||
/** An INT 15,e820 memory map entry */
|
||||
struct e820_entry {
|
||||
/** Start of region */
|
||||
uint64_t start;
|
||||
/** Length of region */
|
||||
uint64_t len;
|
||||
/** Type of region */
|
||||
uint32_t type;
|
||||
/** Extended attributes (optional) */
|
||||
uint32_t attrs;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Normal RAM */
|
||||
#define E820_TYPE_RAM 1
|
||||
|
||||
/** Region is enabled (if extended attributes are present) */
|
||||
#define E820_ATTR_ENABLED 0x00000001UL
|
||||
|
||||
/** Region is non-volatile memory (if extended attributes are present) */
|
||||
#define E820_ATTR_NONVOLATILE 0x00000002UL
|
||||
|
||||
extern struct e820_entry * memmap_next ( struct e820_entry *prev );
|
||||
|
||||
#endif /* _MEMMAP_H */
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Paging
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "wimboot.h"
|
||||
#include "memmap.h"
|
||||
#include "paging.h"
|
||||
|
||||
/** Virtual address used as a 2MB window during relocation */
|
||||
#define COPY_WINDOW 0x200000
|
||||
|
||||
/** Paging is available */
|
||||
int paging;
|
||||
|
||||
/** Page directory pointer table */
|
||||
static uint64_t pdpt[4] __attribute__ (( aligned ( PAGE_SIZE ) ));
|
||||
|
||||
/** Page directories */
|
||||
static uint64_t pd[2048] __attribute__ (( aligned ( PAGE_SIZE ) ));
|
||||
|
||||
/**
|
||||
* Check that paging can be supported
|
||||
*
|
||||
* @ret supported Paging can be supported on this CPU
|
||||
*/
|
||||
static int paging_supported ( void ) {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
|
||||
/* Get CPU features */
|
||||
__asm__ ( "cpuid"
|
||||
: "=a" ( eax ), "=b" ( ebx ), "=c" ( ecx ), "=d" ( edx )
|
||||
: "0" ( CPUID_FEATURES ) );
|
||||
|
||||
return ( edx & CPUID_FEATURE_EDX_PAE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Map 2MB page directory entry containing address
|
||||
*
|
||||
* @v vaddr Virtual address
|
||||
* @v paddr Physical address
|
||||
*/
|
||||
static void map_page ( uint32_t vaddr, uint64_t paddr ) {
|
||||
char *byte = ( ( char * ) ( intptr_t ) vaddr );
|
||||
unsigned int index;
|
||||
|
||||
/* Sanity checks */
|
||||
assert ( ( vaddr & ( PAGE_SIZE_2MB - 1 ) ) == 0 );
|
||||
assert ( ( paddr & ( PAGE_SIZE_2MB - 1 ) ) == 0 );
|
||||
|
||||
/* Populate page directory entry */
|
||||
index = ( vaddr / PAGE_SIZE_2MB );
|
||||
pd[index] = ( paddr | PG_P | PG_RW | PG_US | PG_PS );
|
||||
|
||||
/* Invalidate TLB */
|
||||
__asm__ __volatile__ ( "invlpg %0" : : "m" ( *byte ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise paging
|
||||
*
|
||||
*/
|
||||
void init_paging ( void ) {
|
||||
uint32_t addr;
|
||||
unsigned int i;
|
||||
|
||||
/* Do nothing if paging is disabled */
|
||||
if ( cmdline_linear ) {
|
||||
DBG ( "Paging disabled\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for PAE */
|
||||
if ( ! paging_supported() ) {
|
||||
DBG ( "Paging not possible on this CPU\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialise page directory entries */
|
||||
addr = 0;
|
||||
do {
|
||||
map_page ( addr, addr );
|
||||
addr += PAGE_SIZE_2MB;
|
||||
} while ( addr );
|
||||
|
||||
/* Initialise page directory pointer table */
|
||||
for ( i = 0 ; i < ( sizeof ( pdpt ) / sizeof ( pdpt[0] ) ) ; i++ ) {
|
||||
addr = ( ( intptr_t ) &pd[ i * PAGE_SIZE / sizeof ( pd[0] ) ] );
|
||||
pdpt[i] = ( addr | PG_P );
|
||||
}
|
||||
|
||||
/* Mark paging as available */
|
||||
paging = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable paging
|
||||
*
|
||||
* @v state Saved paging state to fill in
|
||||
*/
|
||||
void enable_paging ( struct paging_state *state ) {
|
||||
unsigned long cr0;
|
||||
unsigned long cr3;
|
||||
unsigned long cr4;
|
||||
|
||||
/* Do nothing if paging is unavailable */
|
||||
if ( ! paging )
|
||||
return;
|
||||
|
||||
/* Save paging state */
|
||||
__asm__ __volatile__ ( "mov %%cr0, %0\n\t"
|
||||
"mov %%cr3, %1\n\t"
|
||||
"mov %%cr4, %2\n\t"
|
||||
: "=r" ( cr0 ), "=r" ( cr3 ), "=r" ( cr4 ) );
|
||||
state->cr0 = cr0;
|
||||
state->cr3 = cr3;
|
||||
state->cr4 = cr4;
|
||||
|
||||
/* Disable any existing paging */
|
||||
__asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 & ~CR0_PG ) );
|
||||
|
||||
/* Enable PAE */
|
||||
__asm__ __volatile__ ( "mov %0, %%cr4" : : "r" ( cr4 | CR4_PAE ) );
|
||||
|
||||
/* Load page directory pointer table */
|
||||
__asm__ __volatile__ ( "mov %0, %%cr3" : : "r" ( pdpt ) );
|
||||
|
||||
/* Enable paging */
|
||||
__asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 | CR0_PG ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable paging
|
||||
*
|
||||
* @v state Previously saved paging state
|
||||
*/
|
||||
void disable_paging ( struct paging_state *state ) {
|
||||
unsigned long cr0 = state->cr0;
|
||||
unsigned long cr3 = state->cr3;
|
||||
unsigned long cr4 = state->cr4;
|
||||
|
||||
/* Do nothing if paging is unavailable */
|
||||
if ( ! paging )
|
||||
return;
|
||||
|
||||
/* Disable paging */
|
||||
__asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 & ~CR0_PG ) );
|
||||
|
||||
/* Restore saved paging state */
|
||||
__asm__ __volatile__ ( "mov %2, %%cr4\n\t"
|
||||
"mov %1, %%cr3\n\t"
|
||||
"mov %0, %%cr0\n\t"
|
||||
: : "r" ( cr0 ), "r" ( cr3 ), "r" ( cr4 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocate data out of 32-bit address space, if possible
|
||||
*
|
||||
* @v data Start of data
|
||||
* @v len Length of data
|
||||
* @ret start Physical start address
|
||||
*/
|
||||
uint64_t relocate_memory_high ( void *data, size_t len ) {
|
||||
intptr_t end = ( ( ( intptr_t ) data ) + len );
|
||||
struct e820_entry *e820 = NULL;
|
||||
uint64_t start;
|
||||
uint64_t dest;
|
||||
size_t offset;
|
||||
size_t frag_len;
|
||||
|
||||
/* Do nothing if paging is unavailable */
|
||||
if ( ! paging )
|
||||
return ( ( intptr_t ) data );
|
||||
|
||||
/* Read system memory map */
|
||||
while ( ( e820 = memmap_next ( e820 ) ) != NULL ) {
|
||||
|
||||
/* Find highest compatible placement within this region */
|
||||
start = ( e820->start + e820->len );
|
||||
if ( start < ADDR_4GB )
|
||||
continue;
|
||||
start = ( ( ( start - end ) & ~( PAGE_SIZE_2MB - 1 ) ) + end );
|
||||
start -= len;
|
||||
if ( start < e820->start )
|
||||
continue;
|
||||
if ( start < ADDR_4GB )
|
||||
continue;
|
||||
|
||||
/* Relocate to this region */
|
||||
dest = start;
|
||||
while ( len ) {
|
||||
|
||||
/* Calculate length within this 2MB page */
|
||||
offset = ( ( ( intptr_t ) data ) &
|
||||
( PAGE_SIZE_2MB - 1 ) );
|
||||
frag_len = ( PAGE_SIZE_2MB - offset );
|
||||
if ( frag_len > len )
|
||||
frag_len = len;
|
||||
|
||||
/* Map copy window to destination */
|
||||
map_page ( COPY_WINDOW,
|
||||
( dest & ~( PAGE_SIZE_2MB - 1 ) ) );
|
||||
|
||||
/* Copy data through copy window */
|
||||
memcpy ( ( ( ( void * ) COPY_WINDOW ) + offset ),
|
||||
data, frag_len );
|
||||
|
||||
/* Map original page to destination */
|
||||
map_page ( ( ( ( intptr_t ) data ) - offset ),
|
||||
( dest & ~( PAGE_SIZE_2MB - 1 ) ) );
|
||||
|
||||
/* Move to next 2MB page */
|
||||
data += frag_len;
|
||||
dest += frag_len;
|
||||
len -= frag_len;
|
||||
}
|
||||
|
||||
/* Remap copy window */
|
||||
map_page ( COPY_WINDOW, COPY_WINDOW );
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Leave at original location */
|
||||
return ( ( intptr_t ) data );
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef _PAGING_H
|
||||
#define _PAGING_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Paging
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/** Get CPU features */
|
||||
#define CPUID_FEATURES 0x00000001
|
||||
|
||||
/** CPU supports PAE */
|
||||
#define CPUID_FEATURE_EDX_PAE 0x00000040
|
||||
|
||||
/* CR0: paging */
|
||||
#define CR0_PG 0x80000000
|
||||
|
||||
/* CR4: physical address extensions */
|
||||
#define CR4_PAE 0x00000020
|
||||
|
||||
/* Page: present */
|
||||
#define PG_P 0x01
|
||||
|
||||
/* Page: read/write */
|
||||
#define PG_RW 0x02
|
||||
|
||||
/* Page: user/supervisor */
|
||||
#define PG_US 0x04
|
||||
|
||||
/* Page: page size */
|
||||
#define PG_PS 0x80
|
||||
|
||||
/** 2MB page size */
|
||||
#define PAGE_SIZE_2MB 0x200000
|
||||
|
||||
/** 32-bit address space size */
|
||||
#define ADDR_4GB 0x100000000ULL
|
||||
|
||||
/** Saved paging state */
|
||||
struct paging_state {
|
||||
/** Control register 0 */
|
||||
unsigned long cr0;
|
||||
/** Control register 3 */
|
||||
unsigned long cr3;
|
||||
/** Control register 4 */
|
||||
unsigned long cr4;
|
||||
};
|
||||
|
||||
extern int paging;
|
||||
|
||||
extern void init_paging ( void );
|
||||
extern void enable_paging ( struct paging_state *state );
|
||||
extern void disable_paging ( struct paging_state *state );
|
||||
extern uint64_t relocate_memory_high ( void *start, size_t len );
|
||||
|
||||
#endif /* _PAGING_H */
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Diagnostic pause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "wimboot.h"
|
||||
#include "cmdline.h"
|
||||
#include "pause.h"
|
||||
|
||||
/**
|
||||
* Pause before booting
|
||||
*
|
||||
*/
|
||||
void pause ( void ) {
|
||||
|
||||
/* Wait for keypress, prompting unless inhibited */
|
||||
if ( cmdline_pause_quiet ) {
|
||||
getchar();
|
||||
} else {
|
||||
printf ( "Press any key to continue booting..." );
|
||||
getchar();
|
||||
printf ( "\n" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _PAUSE_H
|
||||
#define _PAUSE_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Diagnostic pause
|
||||
*
|
||||
*/
|
||||
|
||||
extern void pause ( void );
|
||||
|
||||
#endif /* _PAUSE_H */
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* PE image loader
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "wimboot.h"
|
||||
#include "peloader.h"
|
||||
|
||||
/**
|
||||
* Load PE image into memory
|
||||
*
|
||||
* @v data PE image
|
||||
* @v len Length of PE image
|
||||
* @v pe Loaded PE structure to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int load_pe ( const void *data, size_t len, struct loaded_pe *pe ) {
|
||||
const struct mz_header *mzhdr;
|
||||
size_t pehdr_offset;
|
||||
const struct pe_header *pehdr;
|
||||
size_t opthdr_offset;
|
||||
const struct pe_optional_header *opthdr;
|
||||
size_t section_offset;
|
||||
const struct coff_section *section;
|
||||
char name[ sizeof ( section->name ) + 1 /* NUL */ ];
|
||||
unsigned int i;
|
||||
void *section_base;
|
||||
size_t filesz;
|
||||
size_t memsz;
|
||||
void *end;
|
||||
void *raw_base;
|
||||
|
||||
DBG2 ( "Loading PE executable...\n" );
|
||||
|
||||
/* Parse PE header */
|
||||
mzhdr = data;
|
||||
if ( mzhdr->magic != MZ_HEADER_MAGIC ) {
|
||||
DBG ( "Bad MZ magic %04x\n", mzhdr->magic );
|
||||
return -1;
|
||||
}
|
||||
pehdr_offset = mzhdr->lfanew;
|
||||
if ( pehdr_offset > len ) {
|
||||
DBG ( "PE header outside file\n" );
|
||||
return -1;
|
||||
}
|
||||
pehdr = ( data + pehdr_offset );
|
||||
if ( pehdr->magic != PE_HEADER_MAGIC ) {
|
||||
DBG ( "Bad PE magic %08x\n", pehdr->magic );
|
||||
return -1;
|
||||
}
|
||||
opthdr_offset = ( pehdr_offset + sizeof ( *pehdr ) );
|
||||
opthdr = ( data + opthdr_offset );
|
||||
pe->base = ( ( void * ) ( intptr_t ) ( opthdr->base ) );
|
||||
section_offset = ( opthdr_offset + pehdr->coff.opthdr_len );
|
||||
section = ( data + section_offset );
|
||||
|
||||
/* Load header into memory */
|
||||
DBG2 ( "...headers to %p+%#x\n", pe->base, opthdr->header_len );
|
||||
memcpy ( pe->base, data, opthdr->header_len );
|
||||
end = ( pe->base + opthdr->header_len );
|
||||
|
||||
/* Load each section into memory */
|
||||
for ( i = 0 ; i < pehdr->coff.num_sections ; i++, section++ ) {
|
||||
memset ( name, 0, sizeof ( name ) );
|
||||
memcpy ( name, section->name, sizeof ( section->name ) );
|
||||
section_base = ( pe->base + section->virtual );
|
||||
filesz = section->raw_len;
|
||||
memsz = section->misc.virtual_len;
|
||||
DBG2 ( "...from %#05x to %p+%#zx/%#zx (%s)\n",
|
||||
section->raw, section_base, filesz, memsz, name );
|
||||
memset ( section_base, 0, memsz );
|
||||
memcpy ( section_base, ( data + section->raw ), filesz );
|
||||
if ( end < ( section_base + memsz ) )
|
||||
end = ( section_base + memsz );
|
||||
}
|
||||
pe->len = ( ( ( end - pe->base ) + opthdr->section_align - 1 )
|
||||
& ~( opthdr->section_align - 1 ) );
|
||||
|
||||
/* Load copy of raw image into memory immediately after loaded
|
||||
* sections. This seems to be used for verification of X.509
|
||||
* signatures.
|
||||
*/
|
||||
raw_base = ( pe->base + pe->len );
|
||||
memcpy ( raw_base, data, len );
|
||||
pe->len += len;
|
||||
DBG2 ( "...raw copy to %p+%#zx\n", raw_base, len );
|
||||
|
||||
/* Extract entry point */
|
||||
pe->entry = ( pe->base + opthdr->entry );
|
||||
DBG2 ( "...entry point %p\n", pe->entry );
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
#ifndef _PELOADER_H
|
||||
#define _PELOADER_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* PE image loader
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "wimboot.h"
|
||||
|
||||
/** DOS MZ header */
|
||||
struct mz_header {
|
||||
/** Magic number */
|
||||
uint16_t magic;
|
||||
/** Bytes on last page of file */
|
||||
uint16_t cblp;
|
||||
/** Pages in file */
|
||||
uint16_t cp;
|
||||
/** Relocations */
|
||||
uint16_t crlc;
|
||||
/** Size of header in paragraphs */
|
||||
uint16_t cparhdr;
|
||||
/** Minimum extra paragraphs needed */
|
||||
uint16_t minalloc;
|
||||
/** Maximum extra paragraphs needed */
|
||||
uint16_t maxalloc;
|
||||
/** Initial (relative) SS value */
|
||||
uint16_t ss;
|
||||
/** Initial SP value */
|
||||
uint16_t sp;
|
||||
/** Checksum */
|
||||
uint16_t csum;
|
||||
/** Initial IP value */
|
||||
uint16_t ip;
|
||||
/** Initial (relative) CS value */
|
||||
uint16_t cs;
|
||||
/** File address of relocation table */
|
||||
uint16_t lfarlc;
|
||||
/** Overlay number */
|
||||
uint16_t ovno;
|
||||
/** Reserved words */
|
||||
uint16_t res[4];
|
||||
/** OEM identifier (for oeminfo) */
|
||||
uint16_t oemid;
|
||||
/** OEM information; oemid specific */
|
||||
uint16_t oeminfo;
|
||||
/** Reserved words */
|
||||
uint16_t res2[10];
|
||||
/** File address of new exe header */
|
||||
uint32_t lfanew;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** MZ header magic */
|
||||
#define MZ_HEADER_MAGIC 0x5a4d
|
||||
|
||||
/** COFF file header */
|
||||
struct coff_header {
|
||||
/** Magic number */
|
||||
uint16_t magic;
|
||||
/** Number of sections */
|
||||
uint16_t num_sections;
|
||||
/** Timestamp (seconds since the Epoch) */
|
||||
uint32_t timestamp;
|
||||
/** Offset to symbol table */
|
||||
uint32_t symtab;
|
||||
/** Number of symbol table entries */
|
||||
uint32_t num_syms;
|
||||
/** Length of optional header */
|
||||
uint16_t opthdr_len;
|
||||
/** Flags */
|
||||
uint16_t flags;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** COFF section */
|
||||
struct coff_section {
|
||||
/** Section name */
|
||||
char name[8];
|
||||
/** Physical address or virtual length */
|
||||
union {
|
||||
/** Physical address */
|
||||
uint32_t physical;
|
||||
/** Virtual length */
|
||||
uint32_t virtual_len;
|
||||
} misc;
|
||||
/** Virtual address */
|
||||
uint32_t virtual;
|
||||
/** Length of raw data */
|
||||
uint32_t raw_len;
|
||||
/** Offset to raw data */
|
||||
uint32_t raw;
|
||||
/** Offset to relocations */
|
||||
uint32_t relocations;
|
||||
/** Offset to line numbers */
|
||||
uint32_t line_numbers;
|
||||
/** Number of relocations */
|
||||
uint16_t num_relocations;
|
||||
/** Number of line numbers */
|
||||
uint16_t num_line_numbers;
|
||||
/** Flags */
|
||||
uint32_t flags;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** PE file header */
|
||||
struct pe_header {
|
||||
/** Magic number */
|
||||
uint32_t magic;
|
||||
/** COFF header */
|
||||
struct coff_header coff;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** PE header magic */
|
||||
#define PE_HEADER_MAGIC 0x00004550
|
||||
|
||||
/** PE optional header */
|
||||
struct pe_optional_header {
|
||||
/** Magic number */
|
||||
uint16_t magic;
|
||||
/** Major linker version */
|
||||
uint8_t linker_major;
|
||||
/** Minor linker version */
|
||||
uint8_t linker_minor;
|
||||
/** Length of code */
|
||||
uint32_t text_len;
|
||||
/** Length of initialised data */
|
||||
uint32_t data_len;
|
||||
/** Length of uninitialised data */
|
||||
uint32_t bss_len;
|
||||
/** Entry point */
|
||||
uint32_t entry;
|
||||
/** Base of code */
|
||||
uint32_t text;
|
||||
/** Base of data */
|
||||
uint32_t data;
|
||||
/** Image base address */
|
||||
uint32_t base;
|
||||
/** Section alignment */
|
||||
uint32_t section_align;
|
||||
/** File alignment */
|
||||
uint32_t file_align;
|
||||
/** Major operating system version */
|
||||
uint16_t os_major;
|
||||
/** Minor operating system version */
|
||||
uint16_t os_minor;
|
||||
/** Major image version */
|
||||
uint16_t image_major;
|
||||
/** Minor image version */
|
||||
uint16_t image_minor;
|
||||
/** Major subsystem version */
|
||||
uint16_t subsystem_major;
|
||||
/** Minor subsystem version */
|
||||
uint16_t subsystem_minor;
|
||||
/** Win32 version */
|
||||
uint32_t win32_version;
|
||||
/** Size of image */
|
||||
uint32_t len;
|
||||
/** Size of headers */
|
||||
uint32_t header_len;
|
||||
/* Plus extra fields that we don't care about */
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A loaded PE image */
|
||||
struct loaded_pe {
|
||||
/** Base address */
|
||||
void *base;
|
||||
/** Length */
|
||||
size_t len;
|
||||
/** Entry point */
|
||||
void ( * entry ) ( struct bootapp_descriptor *bootapp );
|
||||
};
|
||||
|
||||
extern int load_pe ( const void *data, size_t len, struct loaded_pe *pe );
|
||||
|
||||
#endif /* _PELOADER_H */
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef _ROTATE_H
|
||||
#define _ROTATE_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Bit operations
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint8_t
|
||||
rol8 ( uint8_t data, unsigned int rotation ) {
|
||||
return ( ( data << rotation ) | ( data >> ( 8 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint8_t
|
||||
ror8 ( uint8_t data, unsigned int rotation ) {
|
||||
return ( ( data >> rotation ) | ( data << ( 8 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint16_t
|
||||
rol16 ( uint16_t data, unsigned int rotation ) {
|
||||
return ( ( data << rotation ) | ( data >> ( 16 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint16_t
|
||||
ror16 ( uint16_t data, unsigned int rotation ) {
|
||||
return ( ( data >> rotation ) | ( data << ( 16 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint32_t
|
||||
rol32 ( uint32_t data, unsigned int rotation ) {
|
||||
return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint32_t
|
||||
ror32 ( uint32_t data, unsigned int rotation ) {
|
||||
return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint64_t
|
||||
rol64 ( uint64_t data, unsigned int rotation ) {
|
||||
return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint64_t
|
||||
ror64 ( uint64_t data, unsigned int rotation ) {
|
||||
return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) );
|
||||
}
|
||||
|
||||
#endif /* _ROTATE_H */
|
|
@ -0,0 +1,116 @@
|
|||
SECTIONS {
|
||||
|
||||
/* Align sections to keep PE tools happy */
|
||||
alignment = 16;
|
||||
|
||||
/* Virtual addresses start at 0x20000 */
|
||||
. = 0x20000;
|
||||
_start = .;
|
||||
|
||||
/* bzImage prefix */
|
||||
_prefix_pos = 0;
|
||||
.prefix : AT ( _prefix_pos ) {
|
||||
_prefix = .;
|
||||
*(.prefix)
|
||||
*(.prefix.*)
|
||||
. = ALIGN ( alignment );
|
||||
_eprefix = .;
|
||||
}
|
||||
_prefix_len = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix );
|
||||
|
||||
/* Real-mode uninitialised data section */
|
||||
.bss16 ( NOLOAD ) : {
|
||||
_bss16 = .;
|
||||
*(.stack16)
|
||||
*(.stack16.*)
|
||||
*(.bss16)
|
||||
*(.bss16.*)
|
||||
. = ALIGN ( alignment );
|
||||
_ebss16 = .;
|
||||
}
|
||||
_bss16_len = ABSOLUTE ( _ebss16 ) - ABSOLUTE ( _bss16 );
|
||||
|
||||
/* Payload section */
|
||||
_payload_pos = ( _prefix_pos + _prefix_len );
|
||||
.payload : AT ( _payload_pos ) {
|
||||
_payload = .;
|
||||
/* Portions that must be accessible in 16-bit modes */
|
||||
_text16 = .;
|
||||
*(.text16)
|
||||
*(.text16.*)
|
||||
_etext16 = .;
|
||||
_data16 = .;
|
||||
*(.rodata16)
|
||||
*(.rodata16.*)
|
||||
*(.data16)
|
||||
*(.data16.*)
|
||||
_edata16 = .;
|
||||
/* Portions that need not be accessible in 16-bit modes */
|
||||
_text = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
_etext = .;
|
||||
_data = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
. = ALIGN ( alignment );
|
||||
_edata = .;
|
||||
_epayload = .;
|
||||
}
|
||||
_text16_len = ABSOLUTE ( _etext16 ) - ABSOLUTE ( _text16 );
|
||||
_data16_len = ABSOLUTE ( _edata16 ) - ABSOLUTE ( _data16 );
|
||||
_text_len = ABSOLUTE ( _etext ) - ABSOLUTE ( _text );
|
||||
_data_len = ABSOLUTE ( _edata ) - ABSOLUTE ( _data );
|
||||
_payload_len = ABSOLUTE ( _epayload ) - ABSOLUTE ( _payload );
|
||||
|
||||
/* bootmgr.exe hardcodes the address 0x30000 for use as a
|
||||
* buffer accessible by real-mode code. We can't fit our
|
||||
* .text, .data, and .bss below this region, so explicitly
|
||||
* place the .bss higher in memory.
|
||||
*/
|
||||
_forbidden_start = 0x30000;
|
||||
_forbidden_end = 0x40000;
|
||||
|
||||
/* Uninitialised data section */
|
||||
.bss ( NOLOAD ) : {
|
||||
_bss = .;
|
||||
ASSERT ( ABSOLUTE ( . ) <= ABSOLUTE ( _forbidden_start ),
|
||||
"Binary is too large" );
|
||||
. = ABSOLUTE ( _forbidden_end );
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
*(.stack)
|
||||
*(.stack.*)
|
||||
. = ALIGN ( alignment );
|
||||
_ebss = .;
|
||||
}
|
||||
_bss_len = ABSOLUTE ( _ebss ) - ABSOLUTE ( _bss );
|
||||
|
||||
/* Relocations section */
|
||||
_reloc_pos = ( _payload_pos + _payload_len );
|
||||
_reloc = .;
|
||||
|
||||
_end = .;
|
||||
|
||||
_text_total_len = ( _text_len + _text16_len );
|
||||
_data_total_len = ( _data_len + _data16_len );
|
||||
_bss_total_len = ( _bss_len + _bss16_len );
|
||||
|
||||
/* Symbols required by i386.x86_64 objects */
|
||||
__i386__start = _start;
|
||||
__i386__end = _end;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.comment)
|
||||
*(.comment.*)
|
||||
*(.note)
|
||||
*(.note.*)
|
||||
*(.eh_frame)
|
||||
*(.eh_frame.*)
|
||||
*(.rel)
|
||||
*(.rel.*)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* SHA-1 algorithm
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <byteswap.h>
|
||||
#include <assert.h>
|
||||
#include "rotate.h"
|
||||
#include "sha1.h"
|
||||
|
||||
/** SHA-1 variables */
|
||||
struct sha1_variables {
|
||||
/* This layout matches that of struct sha1_digest_data,
|
||||
* allowing for efficient endianness-conversion,
|
||||
*/
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
uint32_t e;
|
||||
uint32_t w[80];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* f(a,b,c,d) for steps 0 to 19
|
||||
*
|
||||
* @v v SHA-1 variables
|
||||
* @ret f f(a,b,c,d)
|
||||
*/
|
||||
static uint32_t sha1_f_0_19 ( struct sha1_variables *v ) {
|
||||
return ( ( v->b & v->c ) | ( (~v->b) & v->d ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* f(a,b,c,d) for steps 20 to 39 and 60 to 79
|
||||
*
|
||||
* @v v SHA-1 variables
|
||||
* @ret f f(a,b,c,d)
|
||||
*/
|
||||
static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables *v ) {
|
||||
return ( v->b ^ v->c ^ v->d );
|
||||
}
|
||||
|
||||
/**
|
||||
* f(a,b,c,d) for steps 40 to 59
|
||||
*
|
||||
* @v v SHA-1 variables
|
||||
* @ret f f(a,b,c,d)
|
||||
*/
|
||||
static uint32_t sha1_f_40_59 ( struct sha1_variables *v ) {
|
||||
return ( ( v->b & v->c ) | ( v->b & v->d ) | ( v->c & v->d ) );
|
||||
}
|
||||
|
||||
/** An SHA-1 step function */
|
||||
struct sha1_step {
|
||||
/**
|
||||
* Calculate f(a,b,c,d)
|
||||
*
|
||||
* @v v SHA-1 variables
|
||||
* @ret f f(a,b,c,d)
|
||||
*/
|
||||
uint32_t ( * f ) ( struct sha1_variables *v );
|
||||
/** Constant k */
|
||||
uint32_t k;
|
||||
};
|
||||
|
||||
/** SHA-1 steps */
|
||||
static struct sha1_step sha1_steps[4] = {
|
||||
/** 0 to 19 */
|
||||
{ .f = sha1_f_0_19, .k = 0x5a827999 },
|
||||
/** 20 to 39 */
|
||||
{ .f = sha1_f_20_39_60_79, .k = 0x6ed9eba1 },
|
||||
/** 40 to 59 */
|
||||
{ .f = sha1_f_40_59, .k = 0x8f1bbcdc },
|
||||
/** 60 to 79 */
|
||||
{ .f = sha1_f_20_39_60_79, .k = 0xca62c1d6 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise SHA-1 algorithm
|
||||
*
|
||||
* @v ctx SHA-1 context
|
||||
*/
|
||||
void sha1_init ( void *ctx ) {
|
||||
struct sha1_context *context = ctx;
|
||||
|
||||
context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x67452301 );
|
||||
context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xefcdab89 );
|
||||
context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x98badcfe );
|
||||
context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0x10325476 );
|
||||
context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0xc3d2e1f0 );
|
||||
context->len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate SHA-1 digest of accumulated data
|
||||
*
|
||||
* @v context SHA-1 context
|
||||
*/
|
||||
static void sha1_digest ( struct sha1_context *context ) {
|
||||
union {
|
||||
union sha1_digest_data_dwords ddd;
|
||||
struct sha1_variables v;
|
||||
} u;
|
||||
uint32_t *a = &u.v.a;
|
||||
uint32_t *b = &u.v.b;
|
||||
uint32_t *c = &u.v.c;
|
||||
uint32_t *d = &u.v.d;
|
||||
uint32_t *e = &u.v.e;
|
||||
uint32_t *w = u.v.w;
|
||||
uint32_t f;
|
||||
uint32_t k;
|
||||
uint32_t temp;
|
||||
struct sha1_step *step;
|
||||
unsigned int i;
|
||||
|
||||
/* Convert h[0..4] to host-endian, and initialise a, b, c, d,
|
||||
* e, and w[0..15]
|
||||
*/
|
||||
for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
|
||||
sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
|
||||
be32_to_cpus ( &context->ddd.dword[i] );
|
||||
u.ddd.dword[i] = context->ddd.dword[i];
|
||||
}
|
||||
|
||||
/* Initialise w[16..79] */
|
||||
for ( i = 16 ; i < 80 ; i++ )
|
||||
w[i] = rol32 ( ( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16] ), 1 );
|
||||
|
||||
/* Main loop */
|
||||
for ( i = 0 ; i < 80 ; i++ ) {
|
||||
step = &sha1_steps[ i / 20 ];
|
||||
f = step->f ( &u.v );
|
||||
k = step->k;
|
||||
temp = ( rol32 ( *a, 5 ) + f + *e + k + w[i] );
|
||||
*e = *d;
|
||||
*d = *c;
|
||||
*c = rol32 ( *b, 30 );
|
||||
*b = *a;
|
||||
*a = temp;
|
||||
}
|
||||
|
||||
/* Add chunk to hash and convert back to big-endian */
|
||||
for ( i = 0 ; i < 5 ; i++ ) {
|
||||
context->ddd.dd.digest.h[i] =
|
||||
cpu_to_be32 ( context->ddd.dd.digest.h[i] +
|
||||
u.ddd.dd.digest.h[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate data with SHA-1 algorithm
|
||||
*
|
||||
* @v ctx SHA-1 context
|
||||
* @v data Data
|
||||
* @v len Length of data
|
||||
*/
|
||||
void sha1_update ( void *ctx, const void *data, size_t len ) {
|
||||
struct sha1_context *context = ctx;
|
||||
const uint8_t *byte = data;
|
||||
size_t offset;
|
||||
|
||||
/* Accumulate data a byte at a time, performing the digest
|
||||
* whenever we fill the data buffer
|
||||
*/
|
||||
while ( len-- ) {
|
||||
offset = ( context->len % sizeof ( context->ddd.dd.data ) );
|
||||
context->ddd.dd.data.byte[offset] = *(byte++);
|
||||
context->len++;
|
||||
if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
|
||||
sha1_digest ( context );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SHA-1 digest
|
||||
*
|
||||
* @v ctx SHA-1 context
|
||||
* @v out Output buffer
|
||||
*/
|
||||
void sha1_final ( void *ctx, void *out ) {
|
||||
struct sha1_context *context = ctx;
|
||||
uint64_t len_bits;
|
||||
uint8_t pad;
|
||||
|
||||
/* Record length before pre-processing */
|
||||
len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
|
||||
|
||||
/* Pad with a single "1" bit followed by as many "0" bits as required */
|
||||
pad = 0x80;
|
||||
do {
|
||||
sha1_update ( ctx, &pad, sizeof ( pad ) );
|
||||
pad = 0x00;
|
||||
} while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
|
||||
offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
|
||||
|
||||
/* Append length (in bits) */
|
||||
sha1_update ( ctx, &len_bits, sizeof ( len_bits ) );
|
||||
assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
|
||||
|
||||
/* Copy out final digest */
|
||||
memcpy ( out, &context->ddd.dd.digest,
|
||||
sizeof ( context->ddd.dd.digest ) );
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _SHA1_H
|
||||
#define _SHA1_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* SHA-1 algorithm
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** An SHA-1 digest */
|
||||
struct sha1_digest {
|
||||
/** Hash output */
|
||||
uint32_t h[5];
|
||||
};
|
||||
|
||||
/** An SHA-1 data block */
|
||||
union sha1_block {
|
||||
/** Raw bytes */
|
||||
uint8_t byte[64];
|
||||
/** Raw dwords */
|
||||
uint32_t dword[16];
|
||||
/** Final block structure */
|
||||
struct {
|
||||
/** Padding */
|
||||
uint8_t pad[56];
|
||||
/** Length in bits */
|
||||
uint64_t len;
|
||||
} final;
|
||||
};
|
||||
|
||||
/** SHA-1 digest and data block
|
||||
*
|
||||
* The order of fields within this structure is designed to minimise
|
||||
* code size.
|
||||
*/
|
||||
struct sha1_digest_data {
|
||||
/** Digest of data already processed */
|
||||
struct sha1_digest digest;
|
||||
/** Accumulated data */
|
||||
union sha1_block data;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** SHA-1 digest and data block */
|
||||
union sha1_digest_data_dwords {
|
||||
/** Digest and data block */
|
||||
struct sha1_digest_data dd;
|
||||
/** Raw dwords */
|
||||
uint32_t dword[ sizeof ( struct sha1_digest_data ) /
|
||||
sizeof ( uint32_t ) ];
|
||||
};
|
||||
|
||||
/** An SHA-1 context */
|
||||
struct sha1_context {
|
||||
/** Amount of accumulated data */
|
||||
size_t len;
|
||||
/** Digest and accumulated data */
|
||||
union sha1_digest_data_dwords ddd;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** SHA-1 context size */
|
||||
#define SHA1_CTX_SIZE sizeof ( struct sha1_context )
|
||||
|
||||
/** SHA-1 digest size */
|
||||
#define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest )
|
||||
|
||||
extern void sha1_init ( void *ctx );
|
||||
extern void sha1_update ( void *ctx, const void *data, size_t len );
|
||||
extern void sha1_final ( void *ctx, void *out );
|
||||
|
||||
#endif /* _SHA1_H */
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Standard arguments
|
||||
*
|
||||
*/
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
#define va_start( ap, last ) __builtin_va_start ( ap, last )
|
||||
#define va_arg( ap, type ) __builtin_va_arg ( ap, type )
|
||||
#define va_end( ap ) __builtin_va_end ( ap )
|
||||
#define va_copy( dest, src ) __builtin_va_copy ( dest, src )
|
||||
|
||||
#endif /* _STDARG_H */
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Standard definitions
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NULL ( ( void * ) 0 )
|
||||
|
||||
#define offsetof( type, member ) ( ( size_t ) &( ( type * ) NULL )->member )
|
||||
|
||||
#define container_of( ptr, type, member ) ( { \
|
||||
const typeof ( ( ( type * ) NULL )->member ) *__mptr = (ptr); \
|
||||
( type * ) ( ( void * ) __mptr - offsetof ( type, member ) ); } )
|
||||
|
||||
#endif /* _STDDEF_H */
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Standard integer types
|
||||
*
|
||||
*/
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
typedef unsigned long intptr_t;
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef signed long ssize_t;
|
||||
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
|
||||
#endif /* _STDINT_H */
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Standard Input/Output
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "bootapp.h"
|
||||
#include "wimboot.h"
|
||||
#include "efi.h"
|
||||
|
||||
/**
|
||||
* Print character to console
|
||||
*
|
||||
* @v character Character to print
|
||||
*/
|
||||
int putchar ( int character ) {
|
||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout;
|
||||
struct bootapp_callback_params params;
|
||||
wchar_t wbuf[2];
|
||||
|
||||
/* Convert LF to CR,LF */
|
||||
if ( character == '\n' )
|
||||
putchar ( '\r' );
|
||||
|
||||
/* Print character to bochs debug port */
|
||||
__asm__ __volatile__ ( "outb %b0, $0xe9"
|
||||
: : "a" ( character ) );
|
||||
|
||||
/* Print character to EFI/BIOS console as applicable */
|
||||
if ( efi_systab ) {
|
||||
conout = efi_systab->ConOut;
|
||||
wbuf[0] = character;
|
||||
wbuf[1] = 0;
|
||||
conout->OutputString ( conout, wbuf );
|
||||
} else {
|
||||
memset ( ¶ms, 0, sizeof ( params ) );
|
||||
params.vector.interrupt = 0x10;
|
||||
params.eax = ( 0x0e00 | character );
|
||||
params.ebx = 0x0007;
|
||||
call_interrupt ( ¶ms );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get character from console
|
||||
*
|
||||
* @ret character Character
|
||||
*/
|
||||
int getchar ( void ) {
|
||||
EFI_BOOT_SERVICES *bs;
|
||||
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin;
|
||||
EFI_INPUT_KEY key;
|
||||
UINTN index;
|
||||
struct bootapp_callback_params params;
|
||||
int character;
|
||||
|
||||
/* Get character */
|
||||
if ( efi_systab ) {
|
||||
bs = efi_systab->BootServices;
|
||||
conin = efi_systab->ConIn;
|
||||
bs->WaitForEvent ( 1, &conin->WaitForKey, &index );
|
||||
conin->ReadKeyStroke ( conin, &key );
|
||||
character = key.UnicodeChar;
|
||||
} else {
|
||||
memset ( ¶ms, 0, sizeof ( params ) );
|
||||
params.vector.interrupt = 0x16;
|
||||
call_interrupt ( ¶ms );
|
||||
character = params.al;
|
||||
}
|
||||
|
||||
return character;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue