diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/efi.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/efi.c index dc811577..a93da199 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/efi.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/efi.c @@ -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; +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index 3a9b7718..e4dce219 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -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; } diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h index 3aff72b2..f7b4f9de 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h @@ -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) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c index d21533a5..ba738693 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c @@ -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; +} + diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/efi/efi.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/efi/efi.h index 263359db..4abd5db6 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/efi/efi.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/efi/efi.h @@ -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, diff --git a/INSTALL/grub/arm64-efi/moddep.lst b/INSTALL/grub/arm64-efi/moddep.lst index 3342bd68..2c8eba24 100644 --- a/INSTALL/grub/arm64-efi/moddep.lst +++ b/INSTALL/grub/arm64-efi/moddep.lst @@ -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 diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index f57a20c9..d62b71df 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -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 + + if [ -n "${vtdebug_flag}" ]; then + echo vtoy_wimboot_prefix=$vtoy_wimboot_prefix vtoy_wimboot_bit=$vtoy_wimboot_bit + fi - vt_windows_wimboot_data + for wmfile in sources/boot.wim boot/bcd boot/boot.sdi; do + if [ ! -f $vtoy_wimboot_prefix/$wmfile ]; then + return + fi + done - linux16 $vtoy_efi_part/ventoy/wimboot quiet - ventoy_debug_pause + 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 diff --git a/INSTALL/grub/i386-efi/moddep.lst b/INSTALL/grub/i386-efi/moddep.lst index 3ab0a92b..f101a8fe 100644 --- a/INSTALL/grub/i386-efi/moddep.lst +++ b/INSTALL/grub/i386-efi/moddep.lst @@ -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 diff --git a/INSTALL/grub/i386-pc/moddep.lst b/INSTALL/grub/i386-pc/moddep.lst index 4f8b330d..08cc536a 100644 --- a/INSTALL/grub/i386-pc/moddep.lst +++ b/INSTALL/grub/i386-pc/moddep.lst @@ -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 diff --git a/INSTALL/grub/mips64el-efi/moddep.lst b/INSTALL/grub/mips64el-efi/moddep.lst index 5b71692e..3164b81b 100644 Binary files a/INSTALL/grub/mips64el-efi/moddep.lst and b/INSTALL/grub/mips64el-efi/moddep.lst differ diff --git a/INSTALL/grub/x86_64-efi/moddep.lst b/INSTALL/grub/x86_64-efi/moddep.lst index f706b828..60211723 100644 --- a/INSTALL/grub/x86_64-efi/moddep.lst +++ b/INSTALL/grub/x86_64-efi/moddep.lst @@ -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 diff --git a/INSTALL/ventoy/vtoyjump32.exe b/INSTALL/ventoy/vtoyjump32.exe index 6019aa44..1c7bea1f 100644 Binary files a/INSTALL/ventoy/vtoyjump32.exe and b/INSTALL/ventoy/vtoyjump32.exe differ diff --git a/INSTALL/ventoy/vtoyjump64.exe b/INSTALL/ventoy/vtoyjump64.exe index c2e80a77..a0d60562 100644 Binary files a/INSTALL/ventoy/vtoyjump64.exe and b/INSTALL/ventoy/vtoyjump64.exe differ diff --git a/INSTALL/ventoy/wimboot b/INSTALL/ventoy/wimboot deleted file mode 100644 index e02ed655..00000000 Binary files a/INSTALL/ventoy/wimboot and /dev/null differ diff --git a/INSTALL/ventoy/wimboot.i386.efi.xz b/INSTALL/ventoy/wimboot.i386.efi.xz new file mode 100644 index 00000000..42abe44d Binary files /dev/null and b/INSTALL/ventoy/wimboot.i386.efi.xz differ diff --git a/INSTALL/ventoy/wimboot.x86_64.xz b/INSTALL/ventoy/wimboot.x86_64.xz new file mode 100644 index 00000000..3f628676 Binary files /dev/null and b/INSTALL/ventoy/wimboot.x86_64.xz differ diff --git a/INSTALL/ventoy/winpeshl.ini b/INSTALL/ventoy/winpeshl.ini deleted file mode 100644 index 2302fea9..00000000 --- a/INSTALL/ventoy/winpeshl.ini +++ /dev/null @@ -1,2 +0,0 @@ -[LaunchApps] -vtoyjump.exe \ No newline at end of file diff --git a/vtoyjump/vtoyjump/vtoyjump.c b/vtoyjump/vtoyjump/vtoyjump.c index e8f9f5a8..9b10d1af 100644 --- a/vtoyjump/vtoyjump/vtoyjump.c +++ b/vtoyjump/vtoyjump/vtoyjump.c @@ -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")) { diff --git a/wimboot/build.sh b/wimboot/build.sh new file mode 100644 index 00000000..72536004 --- /dev/null +++ b/wimboot/build.sh @@ -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 ../../ diff --git a/wimboot/wimboot-2.7.3/src/.gitignore b/wimboot/wimboot-2.7.3/src/.gitignore new file mode 100644 index 00000000..80c3366c --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/.gitignore @@ -0,0 +1,10 @@ +wimboot +*.s +*.o +*.a +*.elf +*.map +*.unsigned +*.efi +*.cab +efireloc diff --git a/wimboot/wimboot-2.7.3/src/Makefile b/wimboot/wimboot-2.7.3/src/Makefile new file mode 100644 index 00000000..bb4716b1 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/Makefile @@ -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 diff --git a/wimboot/wimboot-2.7.3/src/assert.h b/wimboot/wimboot-2.7.3/src/assert.h new file mode 100644 index 00000000..bbfcde9e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/assert.h @@ -0,0 +1,39 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/bootapp.h b/wimboot/wimboot-2.7.3/src/bootapp.h new file mode 100644 index 00000000..16b3c1f0 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/bootapp.h @@ -0,0 +1,318 @@ +#ifndef _BOOTAPP_H +#define _BOOTAPP_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/byteswap.h b/wimboot/wimboot-2.7.3/src/byteswap.h new file mode 100644 index 00000000..34a6066e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/byteswap.h @@ -0,0 +1,183 @@ +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H + +/** @file + * + * Byte-order swapping functions + * + */ + +#include + +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 */ diff --git a/wimboot/wimboot-2.7.3/src/cmdline.c b/wimboot/wimboot-2.7.3/src/cmdline.c new file mode 100644 index 00000000..e070ccbc --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/cmdline.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#include +#include +#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); +} diff --git a/wimboot/wimboot-2.7.3/src/cmdline.h b/wimboot/wimboot-2.7.3/src/cmdline.h new file mode 100644 index 00000000..73520c18 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/cmdline.h @@ -0,0 +1,48 @@ +#ifndef _CMDLINE_H +#define _CMDLINE_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/compiler.h b/wimboot/wimboot-2.7.3/src/compiler.h new file mode 100644 index 00000000..d5eb0346 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/compiler.h @@ -0,0 +1,43 @@ +#ifndef _COMPILER_H +#define _COMPILER_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/cookie.c b/wimboot/wimboot-2.7.3/src/cookie.c new file mode 100644 index 00000000..c1cfa65c --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/cookie.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * 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" ); +} diff --git a/wimboot/wimboot-2.7.3/src/coverity-model.c b/wimboot/wimboot-2.7.3/src/coverity-model.c new file mode 100644 index 00000000..e85c85a4 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/coverity-model.c @@ -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 ) { +} diff --git a/wimboot/wimboot-2.7.3/src/cpio.c b/wimboot/wimboot-2.7.3/src/cpio.c new file mode 100644 index 00000000..affb1d88 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/cpio.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#include +#include +#include +#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; + } +} diff --git a/wimboot/wimboot-2.7.3/src/cpio.h b/wimboot/wimboot-2.7.3/src/cpio.h new file mode 100644 index 00000000..b689b066 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/cpio.h @@ -0,0 +1,78 @@ +#ifndef _CPIO_H +#define _CPIO_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/ctype.h b/wimboot/wimboot-2.7.3/src/ctype.h new file mode 100644 index 00000000..6138158e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/ctype.h @@ -0,0 +1,47 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/die.c b/wimboot/wimboot-2.7.3/src/die.c new file mode 100644 index 00000000..54e287ef --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/die.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#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(); +} diff --git a/wimboot/wimboot-2.7.3/src/efi.c b/wimboot/wimboot-2.7.3/src/efi.c new file mode 100644 index 00000000..1be33e99 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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; diff --git a/wimboot/wimboot-2.7.3/src/efi.h b/wimboot/wimboot-2.7.3/src/efi.h new file mode 100644 index 00000000..afc7c421 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi.h @@ -0,0 +1,52 @@ +#ifndef _EFI_H +#define _EFI_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/efi/Base.h b/wimboot/wimboot-2.7.3/src/efi/Base.h new file mode 100644 index 00000000..488f0ef6 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Base.h @@ -0,0 +1,1021 @@ +/** @file + Root include file for Mde Package Base type modules + + This is the include file for any module of type base. Base modules only use + types defined via this include file and can be ported easily to any + environment. There are a set of base libraries in the Mde Package that can + be used to implement base modules. + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+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 __BASE_H__ +#define __BASE_H__ + +// +// Include processor specific binding +// +#include "efi/ProcessorBind.h" + + +/** + Verifies the storage size of a given data type. + + This macro generates a divide by zero error or a zero size array declaration in + the preprocessor if the size is incorrect. These are declared as "extern" so + the space for these arrays will not be in the modules. + + @param TYPE The date type to determine the size of. + @param Size The expected size for the TYPE. + +**/ +#define VERIFY_SIZE_OF(TYPE, Size) extern UINT8 _VerifySizeof##TYPE[(sizeof(TYPE) == (Size)) / (sizeof(TYPE) == (Size))] + +// +// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with +// Section 2.3.1 of the UEFI 2.3 Specification. +// +VERIFY_SIZE_OF (BOOLEAN, 1); +VERIFY_SIZE_OF (INT8, 1); +VERIFY_SIZE_OF (UINT8, 1); +VERIFY_SIZE_OF (INT16, 2); +VERIFY_SIZE_OF (UINT16, 2); +VERIFY_SIZE_OF (INT32, 4); +VERIFY_SIZE_OF (UINT32, 4); +VERIFY_SIZE_OF (INT64, 8); +VERIFY_SIZE_OF (UINT64, 8); +VERIFY_SIZE_OF (CHAR8, 1); +VERIFY_SIZE_OF (CHAR16, 2); + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if defined(_MSC_EXTENSIONS) && !defined (MDE_CPU_EBC) + /// + /// Remove global variable from the linked image if there are no references to + /// it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + /// + /// Remove the global variable from the linked image if there are no references + /// to it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +// +// For symbol name in GNU assembly code, an extra "_" is necessary +// +#if defined(__GNUC__) + /// + /// Private worker functions for ASM_PFX() + /// + #define _CONCATENATE(a, b) __CONCATENATE(a, b) + #define __CONCATENATE(a, b) a ## b + + /// + /// The __USER_LABEL_PREFIX__ macro predefined by GNUC represents the prefix + /// on symbols in assembly language. + /// + #define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name) +#endif + +#if __APPLE__ + // + // Apple extension that is used by the linker to optimize code size + // with assembly functions. Put at the end of your .S files + // + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED .subsections_via_symbols +#else + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED +#endif + +#ifdef __CC_ARM + // + // Older RVCT ARM compilers don't fully support #pragma pack and require __packed + // as a prefix for the structure. + // + #define PACKED __packed +#else + #define PACKED +#endif + +/// +/// 128 bit buffer containing a unique identifier value. +/// Unless otherwise specified, aligned on a 64 bit boundary. +/// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; + +// +// 8-bytes unsigned value that represents a physical system address. +// +typedef UINT64 PHYSICAL_ADDRESS; + +/// +/// LIST_ENTRY structure definition. +/// +typedef struct _LIST_ENTRY LIST_ENTRY; + +/// +/// _LIST_ENTRY structure definition. +/// +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; + +// +// Modifiers to abstract standard types to aid in debug of problems +// + +/// +/// Datum is read-only. +/// +#define CONST const + +/// +/// Datum is scoped to the current file or function. +/// +#define STATIC static + +/// +/// Undeclared type. +/// +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// + +/// +/// Datum is passed to the function. +/// +#define IN + +/// +/// Datum is returned from the function. +/// +#define OUT + +/// +/// Passing the datum to the function is optional, and a NULL +/// is passed if the value is not supplied. +/// +#define OPTIONAL + +// +// UEFI specification claims 1 and 0. We are concerned about the +// complier portability so we did it this way. +// + +/// +/// Boolean true value. UEFI Specification defines this value to be 1, +/// but this form is more portable. +/// +#define TRUE ((BOOLEAN)(1==1)) + +/// +/// Boolean false value. UEFI Specification defines this value to be 0, +/// but this form is more portable. +/// +#define FALSE ((BOOLEAN)(0==1)) + +/// +/// NULL pointer (VOID *) +/// +#define NULL ((VOID *) 0) + +/// +/// Maximum values for common UEFI Data Types +/// +#define MAX_INT8 ((INT8)0x7F) +#define MAX_UINT8 ((UINT8)0xFF) +#define MAX_INT16 ((INT16)0x7FFF) +#define MAX_UINT16 ((UINT16)0xFFFF) +#define MAX_INT32 ((INT32)0x7FFFFFFF) +#define MAX_UINT32 ((UINT32)0xFFFFFFFF) +#define MAX_INT64 ((INT64)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL) + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#define BIT32 0x0000000100000000ULL +#define BIT33 0x0000000200000000ULL +#define BIT34 0x0000000400000000ULL +#define BIT35 0x0000000800000000ULL +#define BIT36 0x0000001000000000ULL +#define BIT37 0x0000002000000000ULL +#define BIT38 0x0000004000000000ULL +#define BIT39 0x0000008000000000ULL +#define BIT40 0x0000010000000000ULL +#define BIT41 0x0000020000000000ULL +#define BIT42 0x0000040000000000ULL +#define BIT43 0x0000080000000000ULL +#define BIT44 0x0000100000000000ULL +#define BIT45 0x0000200000000000ULL +#define BIT46 0x0000400000000000ULL +#define BIT47 0x0000800000000000ULL +#define BIT48 0x0001000000000000ULL +#define BIT49 0x0002000000000000ULL +#define BIT50 0x0004000000000000ULL +#define BIT51 0x0008000000000000ULL +#define BIT52 0x0010000000000000ULL +#define BIT53 0x0020000000000000ULL +#define BIT54 0x0040000000000000ULL +#define BIT55 0x0080000000000000ULL +#define BIT56 0x0100000000000000ULL +#define BIT57 0x0200000000000000ULL +#define BIT58 0x0400000000000000ULL +#define BIT59 0x0800000000000000ULL +#define BIT60 0x1000000000000000ULL +#define BIT61 0x2000000000000000ULL +#define BIT62 0x4000000000000000ULL +#define BIT63 0x8000000000000000ULL + +#define SIZE_1KB 0x00000400 +#define SIZE_2KB 0x00000800 +#define SIZE_4KB 0x00001000 +#define SIZE_8KB 0x00002000 +#define SIZE_16KB 0x00004000 +#define SIZE_32KB 0x00008000 +#define SIZE_64KB 0x00010000 +#define SIZE_128KB 0x00020000 +#define SIZE_256KB 0x00040000 +#define SIZE_512KB 0x00080000 +#define SIZE_1MB 0x00100000 +#define SIZE_2MB 0x00200000 +#define SIZE_4MB 0x00400000 +#define SIZE_8MB 0x00800000 +#define SIZE_16MB 0x01000000 +#define SIZE_32MB 0x02000000 +#define SIZE_64MB 0x04000000 +#define SIZE_128MB 0x08000000 +#define SIZE_256MB 0x10000000 +#define SIZE_512MB 0x20000000 +#define SIZE_1GB 0x40000000 +#define SIZE_2GB 0x80000000 +#define SIZE_4GB 0x0000000100000000ULL +#define SIZE_8GB 0x0000000200000000ULL +#define SIZE_16GB 0x0000000400000000ULL +#define SIZE_32GB 0x0000000800000000ULL +#define SIZE_64GB 0x0000001000000000ULL +#define SIZE_128GB 0x0000002000000000ULL +#define SIZE_256GB 0x0000004000000000ULL +#define SIZE_512GB 0x0000008000000000ULL +#define SIZE_1TB 0x0000010000000000ULL +#define SIZE_2TB 0x0000020000000000ULL +#define SIZE_4TB 0x0000040000000000ULL +#define SIZE_8TB 0x0000080000000000ULL +#define SIZE_16TB 0x0000100000000000ULL +#define SIZE_32TB 0x0000200000000000ULL +#define SIZE_64TB 0x0000400000000000ULL +#define SIZE_128TB 0x0000800000000000ULL +#define SIZE_256TB 0x0001000000000000ULL +#define SIZE_512TB 0x0002000000000000ULL +#define SIZE_1PB 0x0004000000000000ULL +#define SIZE_2PB 0x0008000000000000ULL +#define SIZE_4PB 0x0010000000000000ULL +#define SIZE_8PB 0x0020000000000000ULL +#define SIZE_16PB 0x0040000000000000ULL +#define SIZE_32PB 0x0080000000000000ULL +#define SIZE_64PB 0x0100000000000000ULL +#define SIZE_128PB 0x0200000000000000ULL +#define SIZE_256PB 0x0400000000000000ULL +#define SIZE_512PB 0x0800000000000000ULL +#define SIZE_1EB 0x1000000000000000ULL +#define SIZE_2EB 0x2000000000000000ULL +#define SIZE_4EB 0x4000000000000000ULL +#define SIZE_8EB 0x8000000000000000ULL + +#define BASE_1KB 0x00000400 +#define BASE_2KB 0x00000800 +#define BASE_4KB 0x00001000 +#define BASE_8KB 0x00002000 +#define BASE_16KB 0x00004000 +#define BASE_32KB 0x00008000 +#define BASE_64KB 0x00010000 +#define BASE_128KB 0x00020000 +#define BASE_256KB 0x00040000 +#define BASE_512KB 0x00080000 +#define BASE_1MB 0x00100000 +#define BASE_2MB 0x00200000 +#define BASE_4MB 0x00400000 +#define BASE_8MB 0x00800000 +#define BASE_16MB 0x01000000 +#define BASE_32MB 0x02000000 +#define BASE_64MB 0x04000000 +#define BASE_128MB 0x08000000 +#define BASE_256MB 0x10000000 +#define BASE_512MB 0x20000000 +#define BASE_1GB 0x40000000 +#define BASE_2GB 0x80000000 +#define BASE_4GB 0x0000000100000000ULL +#define BASE_8GB 0x0000000200000000ULL +#define BASE_16GB 0x0000000400000000ULL +#define BASE_32GB 0x0000000800000000ULL +#define BASE_64GB 0x0000001000000000ULL +#define BASE_128GB 0x0000002000000000ULL +#define BASE_256GB 0x0000004000000000ULL +#define BASE_512GB 0x0000008000000000ULL +#define BASE_1TB 0x0000010000000000ULL +#define BASE_2TB 0x0000020000000000ULL +#define BASE_4TB 0x0000040000000000ULL +#define BASE_8TB 0x0000080000000000ULL +#define BASE_16TB 0x0000100000000000ULL +#define BASE_32TB 0x0000200000000000ULL +#define BASE_64TB 0x0000400000000000ULL +#define BASE_128TB 0x0000800000000000ULL +#define BASE_256TB 0x0001000000000000ULL +#define BASE_512TB 0x0002000000000000ULL +#define BASE_1PB 0x0004000000000000ULL +#define BASE_2PB 0x0008000000000000ULL +#define BASE_4PB 0x0010000000000000ULL +#define BASE_8PB 0x0020000000000000ULL +#define BASE_16PB 0x0040000000000000ULL +#define BASE_32PB 0x0080000000000000ULL +#define BASE_64PB 0x0100000000000000ULL +#define BASE_128PB 0x0200000000000000ULL +#define BASE_256PB 0x0400000000000000ULL +#define BASE_512PB 0x0800000000000000ULL +#define BASE_1EB 0x1000000000000000ULL +#define BASE_2EB 0x2000000000000000ULL +#define BASE_4EB 0x4000000000000000ULL +#define BASE_8EB 0x8000000000000000ULL + +// +// Support for variable length argument lists using the ANSI standard. +// +// Since we are using the ANSI standard we used the standard naming and +// did not follow the coding convention +// +// VA_LIST - typedef for argument list. +// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. +// VA_END (VA_LIST Marker) - Clear Marker +// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from +// the ... list. You must know the size and pass it in this macro. +// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start. +// +// example: +// +// UINTN +// ExampleVarArg ( +// IN UINTN NumberOfArgs, +// ... +// ) +// { +// VA_LIST Marker; +// UINTN Index; +// UINTN Result; +// +// // +// // Initialize the Marker +// // +// VA_START (Marker, NumberOfArgs); +// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { +// // +// // The ... list is a series of UINTN values, so average them up. +// // +// Result += VA_ARG (Marker, UINTN); +// } +// +// VA_END (Marker); +// return Result +// } +// + +/** + Return the size of argument that has been aligned to sizeof (UINTN). + + @param n The parameter size to be aligned. + + @return The aligned size. +**/ +#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) + +#if defined(__CC_ARM) +// +// RVCT ARM variable argument list support. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +#ifdef __APCS_ADSABI + typedef int *va_list[1]; + #define VA_LIST va_list +#else + typedef struct __va_list { void *__ap; } va_list; + #define VA_LIST va_list +#endif + +#define VA_START(Marker, Parameter) __va_start(Marker, Parameter) + +#define VA_ARG(Marker, TYPE) __va_arg(Marker, TYPE) + +#define VA_END(Marker) ((void)0) + +// For some ARM RVCT compilers, __va_copy is not defined +#ifndef __va_copy + #define __va_copy(dest, src) ((void)((dest) = (src))) +#endif + +#define VA_COPY(Dest, Start) __va_copy (Dest, Start) + +#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS) +// +// Use GCC built-in macros for variable argument lists. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef __builtin_va_list VA_LIST; + +#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter) + +#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) + +#define VA_END(Marker) __builtin_va_end (Marker) + +#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) + +#else +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef CHAR8 *VA_LIST; + +/** + Retrieves a pointer to the beginning of a variable argument list, based on + the name of the parameter that immediately precedes the variable argument list. + + This function initializes Marker to point to the beginning of the variable + argument list that immediately follows Parameter. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the + EFIAPI ABI. + + @param Marker The VA_LIST used to traverse the list of arguments. + @param Parameter The name of the parameter that immediately precedes + the variable argument list. + + @return A pointer to the beginning of a variable argument list. + +**/ +#define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter))) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI. + + @param Marker VA_LIST used to traverse the list of arguments. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE))) + +/** + Terminates the use of a variable argument list. + + This function initializes Marker so it can no longer be used with VA_ARG(). + After this macro is used, the only way to access the variable argument list is + by using VA_START() again. + + @param Marker VA_LIST used to traverse the list of arguments. + +**/ +#define VA_END(Marker) (Marker = (VA_LIST) 0) + +/** + Initializes a VA_LIST as a copy of an existing VA_LIST. + + This macro initializes Dest as a copy of Start, as if the VA_START macro had been applied to Dest + followed by the same sequence of uses of the VA_ARG macro as had previously been used to reach + the present state of Start. + + @param Dest VA_LIST used to traverse the list of arguments. + @param Start VA_LIST used to traverse the list of arguments. + +**/ +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + +#endif + +/// +/// Pointer to the start of a variable argument list stored in a memory buffer. Same as UINT8 *. +/// +typedef UINTN *BASE_LIST; + +/** + Returns the size of a data type in sizeof(UINTN) units rounded up to the nearest UINTN boundary. + + @param TYPE The date type to determine the size of. + + @return The size of TYPE in sizeof (UINTN) units rounded up to the nearest UINTN boundary. +**/ +#define _BASE_INT_SIZE_OF(TYPE) ((sizeof (TYPE) + sizeof (UINTN) - 1) / sizeof (UINTN)) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU specific following the EFIAPI ABI. + + @param Marker The pointer to the beginning of a variable argument list. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define BASE_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _BASE_INT_SIZE_OF (TYPE)) - _BASE_INT_SIZE_OF (TYPE))) + +/** + The macro that returns the byte offset of a field in a data structure. + + This function returns the offset, in bytes, of field specified by Field from the + beginning of the data structure specified by TYPE. If TYPE does not contain Field, + the module will not compile. + + @param TYPE The name of the data structure that contains the field specified by Field. + @param Field The name of the field in the data structure. + + @return Offset, in bytes, of field. + +**/ +#ifdef __GNUC__ +#if __GNUC__ >= 4 +#define OFFSET_OF(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field)) +#endif +#endif + +#ifndef OFFSET_OF +#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) +#endif + +/** + Macro that returns a pointer to the data structure that contains a specified field of + that data structure. This is a lightweight method to hide information by placing a + public data structure inside a larger private data structure and using a pointer to + the public data structure to retrieve a pointer to the private data structure. + + This function computes the offset, in bytes, of field specified by Field from the beginning + of the data structure specified by TYPE. This offset is subtracted from Record, and is + used to return a pointer to a data structure of the type specified by TYPE. If the data type + specified by TYPE does not contain the field specified by Field, then the module will not compile. + + @param Record Pointer to the field specified by Field within a data structure of type TYPE. + @param TYPE The name of the data structure type to return. This data structure must + contain the field specified by Field. + @param Field The name of the field in the data structure specified by TYPE to which Record points. + + @return A pointer to the structure from one of it's elements. + +**/ +#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +/** + Rounds a value up to the next boundary using a specified alignment. + + This function rounds Value up to the next boundary using the specified Alignment. + This aligned value is returned. + + @param Value The value to round up. + @param Alignment The alignment boundary used to return the aligned value. + + @return A value up to the next boundary. + +**/ +#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1))) + +/** + Adjust a pointer by adding the minimum offset required for it to be aligned on + a specified alignment boundary. + + This function rounds the pointer specified by Pointer to the next alignment boundary + specified by Alignment. The pointer to the aligned address is returned. + + @param Pointer The pointer to round up. + @param Alignment The alignment boundary to use to return an aligned pointer. + + @return Pointer to the aligned address. + +**/ +#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment)))) + +/** + Rounds a value up to the next natural boundary for the current CPU. + This is 4-bytes for 32-bit CPUs and 8-bytes for 64-bit CPUs. + + This function rounds the value specified by Value up to the next natural boundary for the + current CPU. This rounded value is returned. + + @param Value The value to round up. + + @return Rounded value specified by Value. + +**/ +#define ALIGN_VARIABLE(Value) ALIGN_VALUE ((Value), sizeof (UINTN)) + + +/** + Return the maximum of two operands. + + This macro returns the maximum of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. Can be any numerical type as long as is + the same type as a. + + @return Maximum of two operands. + +**/ +#define MAX(a, b) \ + (((a) > (b)) ? (a) : (b)) + +/** + Return the minimum of two operands. + + This macro returns the minimal of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. It should be the same any numerical type with a. + + @return Minimum of two operands. + +**/ +#define MIN(a, b) \ + (((a) < (b)) ? (a) : (b)) + +/** + Return the absolute value of a signed operand. + + This macro returns the absolute value of the signed operand specified by a. + + @param a The signed operand. + + @return The absolute value of the signed operand. + +**/ +#define ABS(a) \ + (((a) < 0) ? (-(a)) : (a)) + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +/// +/// The operation is not supported. +/// +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) + +/// +/// The buffer was not the proper size for the request. +/// +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) + +/// +/// The buffer was not large enough to hold the requested data. +/// The required buffer size is returned in the appropriate +/// parameter when this error occurs. +/// +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) + +/// +/// There is no data pending upon return. +/// +#define RETURN_NOT_READY ENCODE_ERROR (6) + +/// +/// The physical device reported an error while attempting the +/// operation. +/// +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) + +/// +/// The device can not be written to. +/// +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) + +/// +/// The resource has run out. +/// +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/// +/// An inconsistency was detected on the file system causing the +/// operation to fail. +/// +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) + +/// +/// There is no more space on the file system. +/// +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) + +/// +/// The device does not contain any medium to perform the +/// operation. +/// +#define RETURN_NO_MEDIA ENCODE_ERROR (12) + +/// +/// The medium in the device has changed since the last +/// access. +/// +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) + +/// +/// The item was not found. +/// +#define RETURN_NOT_FOUND ENCODE_ERROR (14) + +/// +/// Access was denied. +/// +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) + +/// +/// The server was not found or did not respond to the request. +/// +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) + +/// +/// A mapping to the device does not exist. +/// +#define RETURN_NO_MAPPING ENCODE_ERROR (17) + +/// +/// A timeout time expired. +/// +#define RETURN_TIMEOUT ENCODE_ERROR (18) + +/// +/// The protocol has not been started. +/// +#define RETURN_NOT_STARTED ENCODE_ERROR (19) + +/// +/// The protocol has already been started. +/// +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) + +/// +/// The operation was aborted. +/// +#define RETURN_ABORTED ENCODE_ERROR (21) + +/// +/// An ICMP error occurred during the network operation. +/// +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) + +/// +/// A TFTP error occurred during the network operation. +/// +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) + +/// +/// A protocol error occurred during the network operation. +/// +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) + +/// +/// A function encountered an internal version that was +/// incompatible with a version requested by the caller. +/// +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) + +/// +/// The function was not performed due to a security violation. +/// +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) + +/// +/// A CRC error was detected. +/// +#define RETURN_CRC_ERROR ENCODE_ERROR (27) + +/// +/// The beginning or end of media was reached. +/// +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) + +/// +/// The end of the file was reached. +/// +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +/// +/// The language specified was invalid. +/// +#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) + +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) + +/// +/// The string contained one or more characters that +/// the device could not render and were skipped. +/// +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) + +/// +/// The handle was closed, but the file was not deleted. +/// +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) + +/// +/// The handle was closed, but the data to the file was not +/// flushed properly. +/// +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) + +/// +/// The resulting buffer was too small, and the data was +/// truncated to the buffer size. +/// +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + +/** + Returns a 16-bit signature built from 2 ASCII characters. + + This macro returns a 16-bit value built from the two ASCII characters specified + by A and B. + + @param A The first ASCII character. + @param B The second ASCII character. + + @return A 16-bit value built from the two ASCII characters specified by A and B. + +**/ +#define SIGNATURE_16(A, B) ((A) | (B << 8)) + +/** + Returns a 32-bit signature built from 4 ASCII characters. + + This macro returns a 32-bit value built from the four ASCII characters specified + by A, B, C, and D. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + + @return A 32-bit value built from the two ASCII characters specified by A, B, + C and D. + +**/ +#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) + +/** + Returns a 64-bit signature built from 8 ASCII characters. + + This macro returns a 64-bit value built from the eight ASCII characters specified + by A, B, C, D, E, F, G,and H. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + @param E The fifth ASCII character. + @param F The sixth ASCII character. + @param G The seventh ASCII character. + @param H The eighth ASCII character. + + @return A 64-bit value built from the two ASCII characters specified by A, B, + C, D, E, F, G and H. + +**/ +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) + +#endif + diff --git a/wimboot/wimboot-2.7.3/src/efi/Guid/FileInfo.h b/wimboot/wimboot-2.7.3/src/efi/Guid/FileInfo.h new file mode 100644 index 00000000..14572753 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Guid/FileInfo.h @@ -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.
+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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Guid/HiiFormMapMethodGuid.h b/wimboot/wimboot-2.7.3/src/efi/Guid/HiiFormMapMethodGuid.h new file mode 100644 index 00000000..ab508fd3 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Guid/HiiFormMapMethodGuid.h @@ -0,0 +1,25 @@ +/** @file + Guid used to identify HII FormMap configuration method. + + Copyright (c) 2009, Intel Corporation. All rights reserved.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Guid/PcAnsi.h b/wimboot/wimboot-2.7.3/src/efi/Guid/PcAnsi.h new file mode 100644 index 00000000..8f312542 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Guid/PcAnsi.h @@ -0,0 +1,58 @@ +/** @file + Terminal Device Path Vendor Guid. + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Guid/WinCertificate.h b/wimboot/wimboot-2.7.3/src/efi/Guid/WinCertificate.h new file mode 100644 index 00000000..6dea446b --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Guid/WinCertificate.h @@ -0,0 +1,128 @@ +/** @file + GUID for UEFI WIN_CERTIFICATE structure. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Ia32/ProcessorBind.h b/wimboot/wimboot-2.7.3/src/efi/Ia32/ProcessorBind.h new file mode 100644 index 00000000..bdcd7d4f --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Ia32/ProcessorBind.h @@ -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.
+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 + diff --git a/wimboot/wimboot-2.7.3/src/efi/IndustryStandard/PeImage.h b/wimboot/wimboot-2.7.3/src/efi/IndustryStandard/PeImage.h new file mode 100644 index 00000000..254e5d2e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/IndustryStandard/PeImage.h @@ -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.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+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 "!\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 diff --git a/wimboot/wimboot-2.7.3/src/efi/ProcessorBind.h b/wimboot/wimboot-2.7.3/src/efi/ProcessorBind.h new file mode 100644 index 00000000..0f31cc36 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/ProcessorBind.h @@ -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 +#endif + +#if __x86_64__ +#include +#endif + +#endif /* _WIMBOOT_EFI_PROCESSOR_BIND_H */ diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/BlockIo.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/BlockIo.h new file mode 100644 index 00000000..33c69915 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/BlockIo.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.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/DevicePath.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/DevicePath.h new file mode 100644 index 00000000..e466e878 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/DevicePath.h @@ -0,0 +1,1169 @@ +/** @file + The device path protocol as defined in UEFI 2.0. + + The device path represents a programmatic path to a device, + from a software point of view. The path must persist from boot to boot, so + it can not contain things like PCI bus numbers that change from boot to boot. + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+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 __EFI_DEVICE_PATH_PROTOCOL_H__ +#define __EFI_DEVICE_PATH_PROTOCOL_H__ + +#include "efi/Guid/PcAnsi.h" + +/// +/// Device Path protocol. +/// +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// Device Path guid definition for backward-compatible with EFI1.1. +/// +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + +#pragma pack(1) + +/** + This protocol can be used on any device handle to obtain generic path/location + information concerning the physical device or logical device. If the handle does + not logically map to a physical device, the handle may not necessarily support + the device path protocol. The device path describes the location of the device + the handle is for. The size of the Device Path can be determined from the structures + that make up the Device Path. +**/ +typedef struct { + UINT8 Type; ///< 0x01 Hardware Device Path. + ///< 0x02 ACPI Device Path. + ///< 0x03 Messaging Device Path. + ///< 0x04 Media Device Path. + ///< 0x05 BIOS Boot Specification Device Path. + ///< 0x7F End of Hardware Device Path. + + UINT8 SubType; ///< Varies by Type + ///< 0xFF End Entire Device Path, or + ///< 0x01 End This Instance of a Device Path and start a new + ///< Device Path. + + UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define + ///< type of data. Size of data is included in Length. + +} EFI_DEVICE_PATH_PROTOCOL; + +/// +/// Device Path protocol definition for backward-compatible with EFI1.1. +/// +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +/// +/// Hardware Device Paths. +/// +#define HARDWARE_DEVICE_PATH 0x01 + +/// +/// PCI Device Path SubType. +/// +#define HW_PCI_DP 0x01 + +/// +/// PCI Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// PCI Function Number. + /// + UINT8 Function; + /// + /// PCI Device Number. + /// + UINT8 Device; +} PCI_DEVICE_PATH; + +/// +/// PCCARD Device Path SubType. +/// +#define HW_PCCARD_DP 0x02 + +/// +/// PCCARD Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Function Number (0 = First Function). + /// + UINT8 FunctionNumber; +} PCCARD_DEVICE_PATH; + +/// +/// Memory Mapped Device Path SubType. +/// +#define HW_MEMMAP_DP 0x03 + +/// +/// Memory Mapped Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// EFI_MEMORY_TYPE + /// + UINT32 MemoryType; + /// + /// Starting Memory Address. + /// + EFI_PHYSICAL_ADDRESS StartingAddress; + /// + /// Ending Memory Address. + /// + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +/// +/// Hardware Vendor Device Path SubType. +/// +#define HW_VENDOR_DP 0x04 + +/// +/// The Vendor Device Path allows the creation of vendor-defined Device Paths. A vendor must +/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be used to define the +/// contents on the n bytes that follow in the Vendor Device Path node. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor-assigned GUID that defines the data that follows. + /// + EFI_GUID Guid; + /// + /// Vendor-defined variable size data. + /// +} VENDOR_DEVICE_PATH; + +/// +/// Controller Device Path SubType. +/// +#define HW_CONTROLLER_DP 0x05 + +/// +/// Controller Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Controller number. + /// + UINT32 ControllerNumber; +} CONTROLLER_DEVICE_PATH; + +/// +/// ACPI Device Paths. +/// +#define ACPI_DEVICE_PATH 0x02 + +/// +/// ACPI Device Path SubType. +/// +#define ACPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. Only the 32-bit + /// numeric value type of _UID is supported. Thus, strings must + /// not be used for the _UID in the ACPI name space. + /// + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +/// +/// Expanded ACPI Device Path SubType. +/// +#define ACPI_EXTENDED_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. + /// + UINT32 UID; + /// + /// Device's compatible PnP hardware ID stored in a numeric + /// 32-bit compressed EISA-type ID. This value must match at + /// least one of the compatible device IDs returned by the + /// corresponding _CID in the ACPI name space. + /// + UINT32 CID; + /// + /// Optional variable length _HIDSTR. + /// Optional variable length _UIDSTR. + /// Optional variable length _CIDSTR. + /// +} ACPI_EXTENDED_HID_DEVICE_PATH; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32)((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) +#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + +/// +/// ACPI _ADR Device Path SubType. +/// +#define ACPI_ADR_DP 0x03 + +/// +/// The _ADR device path is used to contain video output device attributes to support the Graphics +/// Output Protocol. The device path can contain multiple _ADR entries if multiple video output +/// devices are displaying the same output. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// _ADR value. For video output devices the value of this + /// field comes from Table B-2 of the ACPI 3.0 specification. At + /// least one _ADR value is required. + /// + UINT32 ADR; + // + // This device path may optionally contain more than one _ADR entry. + // +} ACPI_ADR_DEVICE_PATH; + +#define ACPI_ADR_DISPLAY_TYPE_OTHER 0 +#define ACPI_ADR_DISPLAY_TYPE_VGA 1 +#define ACPI_ADR_DISPLAY_TYPE_TV 2 +#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL 3 +#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL 4 + +#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \ + ((UINT32)( (((_DeviceIdScheme) & 0x1) << 31) | \ + (((_HeadId) & 0x7) << 18) | \ + (((_NonVgaOutput) & 0x1) << 17) | \ + (((_BiosCanDetect) & 0x1) << 16) | \ + (((_VendorInfo) & 0xf) << 12) | \ + (((_Type) & 0xf) << 8) | \ + (((_Port) & 0xf) << 4) | \ + ((_Index) & 0xf) )) + +/// +/// Messaging Device Paths. +/// This Device Path is used to describe the connection of devices outside the resource domain of the +/// system. This Device Path can describe physical messaging information like SCSI ID, or abstract +/// information like networking protocol IP addresses. +/// +#define MESSAGING_DEVICE_PATH 0x03 + +/// +/// ATAPI Device Path SubType +/// +#define MSG_ATAPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Set to zero for primary, or one for secondary. + /// + UINT8 PrimarySecondary; + /// + /// Set to zero for master, or one for slave mode. + /// + UINT8 SlaveMaster; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +/// +/// SCSI Device Path SubType. +/// +#define MSG_SCSI_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID on the SCSI bus (PUN). + /// + UINT16 Pun; + /// + /// Logical Unit Number (LUN). + /// + UINT16 Lun; +} SCSI_DEVICE_PATH; + +/// +/// Fibre Channel SubType. +/// +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// Fibre Channel World Wide Number. + /// + UINT64 WWN; + /// + /// Fibre Channel Logical Unit Number. + /// + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +/// +/// Fibre Channel Ex SubType. +/// +#define MSG_FIBRECHANNELEX_DP 0x15 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 8 byte array containing Fibre Channel End Device Port Name. + /// + UINT8 WWN[8]; + /// + /// 8 byte array containing Fibre Channel Logical Unit Number. + /// + UINT8 Lun[8]; +} FIBRECHANNELEX_DEVICE_PATH; + +/// +/// 1394 Device Path SubType +/// +#define MSG_1394_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 1394 Global Unique ID (GUID). + /// + UINT64 Guid; +} F1394_DEVICE_PATH; + +/// +/// USB Device Path SubType. +/// +#define MSG_USB_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB Parent Port Number. + /// + UINT8 ParentPortNumber; + /// + /// USB Interface Number. + /// + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; + +/// +/// USB Class Device Path SubType. +/// +#define MSG_USB_CLASS_DP 0x0f +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor ID assigned by USB-IF. A value of 0xFFFF will + /// match any Vendor ID. + /// + UINT16 VendorId; + /// + /// Product ID assigned by USB-IF. A value of 0xFFFF will + /// match any Product ID. + /// + UINT16 ProductId; + /// + /// The class code assigned by the USB-IF. A value of 0xFF + /// will match any class code. + /// + UINT8 DeviceClass; + /// + /// The subclass code assigned by the USB-IF. A value of + /// 0xFF will match any subclass code. + /// + UINT8 DeviceSubClass; + /// + /// The protocol code assigned by the USB-IF. A value of + /// 0xFF will match any protocol code. + /// + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +/// +/// USB WWID Device Path SubType. +/// +#define MSG_USB_WWID_DP 0x10 + +/// +/// This device path describes a USB device using its serial number. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB interface number. + /// + UINT16 InterfaceNumber; + /// + /// USB vendor id of the device. + /// + UINT16 VendorId; + /// + /// USB product id of the device. + /// + UINT16 ProductId; + /// + /// Last 64-or-fewer UTF-16 characters of the USB + /// serial number. The length of the string is + /// determined by the Length field less the offset of the + /// Serial Number field (10) + /// + /// CHAR16 SerialNumber[...]; +} USB_WWID_DEVICE_PATH; + +/// +/// Device Logical Unit SubType. +/// +#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Logical Unit Number for the interface. + /// + UINT8 Lun; +} DEVICE_LOGICAL_UNIT_DEVICE_PATH; + +/// +/// SATA Device Path SubType. +/// +#define MSG_SATA_DP 0x12 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The HBA port number that facilitates the connection to the + /// device or a port multiplier. The value 0xFFFF is reserved. + /// + UINT16 HBAPortNumber; + /// + /// The Port multiplier port number that facilitates the connection + /// to the device. Bit 15 should be set if the device is directly + /// connected to the HBA. + /// + UINT16 PortMultiplierPortNumber; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} SATA_DEVICE_PATH; + +/// +/// Flag for if the device is directly connected to the HBA. +/// +#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000 + +/// +/// I2O Device Path SubType. +/// +#define MSG_I2O_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID (TID) for a device. + /// + UINT32 Tid; +} I2O_DEVICE_PATH; + +/// +/// MAC Address Device Path SubType. +/// +#define MSG_MAC_ADDR_DP 0x0b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The MAC address for a network interface padded with 0s. + /// + EFI_MAC_ADDRESS MacAddress; + /// + /// Network interface type(i.e. 802.3, FDDI). + /// + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +/// +/// IPv4 Device Path SubType +/// +#define MSG_IPv4_DP 0x0c +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv4 address. + /// + EFI_IPv4_ADDRESS LocalIpAddress; + /// + /// The remote IPv4 address. + /// + EFI_IPv4_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Source IP Address was assigned though DHCP. + /// 0x01 - The Source IP Address is statically bound. + /// + BOOLEAN StaticIpAddress; + /// + /// The gateway IP address + /// + EFI_IPv4_ADDRESS GatewayIpAddress; + /// + /// The subnet mask + /// + EFI_IPv4_ADDRESS SubnetMask; +} IPv4_DEVICE_PATH; + +/// +/// IPv6 Device Path SubType. +/// +#define MSG_IPv6_DP 0x0d +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv6 address. + /// + EFI_IPv6_ADDRESS LocalIpAddress; + /// + /// The remote IPv6 address. + /// + EFI_IPv6_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Local IP Address was manually configured. + /// 0x01 - The Local IP Address is assigned through IPv6 + /// stateless auto-configuration. + /// 0x02 - The Local IP Address is assigned through IPv6 + /// stateful configuration. + /// + UINT8 IpAddressOrigin; + /// + /// The prefix length + /// + UINT8 PrefixLength; + /// + /// The gateway IP address + /// + EFI_IPv6_ADDRESS GatewayIpAddress; +} IPv6_DEVICE_PATH; + +/// +/// InfiniBand Device Path SubType. +/// +#define MSG_INFINIBAND_DP 0x09 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Flags to help identify/manage InfiniBand device path elements: + /// Bit 0 - IOC/Service (0b = IOC, 1b = Service). + /// Bit 1 - Extend Boot Environment. + /// Bit 2 - Console Protocol. + /// Bit 3 - Storage Protocol. + /// Bit 4 - Network Protocol. + /// All other bits are reserved. + /// + UINT32 ResourceFlags; + /// + /// 128-bit Global Identifier for remote fabric port. + /// + UINT8 PortGid[16]; + /// + /// 64-bit unique identifier to remote IOC or server process. + /// Interpretation of field specified by Resource Flags (bit 0). + /// + UINT64 ServiceId; + /// + /// 64-bit persistent ID of remote IOC port. + /// + UINT64 TargetPortId; + /// + /// 64-bit persistent ID of remote device. + /// + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01 +#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02 +#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04 +#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08 +#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10 + +/// +/// UART Device Path SubType. +/// +#define MSG_UART_DP 0x0e +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved. + /// + UINT32 Reserved; + /// + /// The baud rate setting for the UART style device. A value of 0 + /// means that the device's default baud rate will be used. + /// + UINT64 BaudRate; + /// + /// The number of data bits for the UART style device. A value + /// of 0 means that the device's default number of data bits will be used. + /// + UINT8 DataBits; + /// + /// The parity setting for the UART style device. + /// Parity 0x00 - Default Parity. + /// Parity 0x01 - No Parity. + /// Parity 0x02 - Even Parity. + /// Parity 0x03 - Odd Parity. + /// Parity 0x04 - Mark Parity. + /// Parity 0x05 - Space Parity. + /// + UINT8 Parity; + /// + /// The number of stop bits for the UART style device. + /// Stop Bits 0x00 - Default Stop Bits. + /// Stop Bits 0x01 - 1 Stop Bit. + /// Stop Bits 0x02 - 1.5 Stop Bits. + /// Stop Bits 0x03 - 2 Stop Bits. + /// + UINT8 StopBits; +} UART_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MSG_VENDOR_DP 0x0a +typedef VENDOR_DEVICE_PATH VENDOR_DEFINED_DEVICE_PATH; + +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + +/// +/// A new device path node is defined to declare flow control characteristics. +/// UART Flow Control Messaging Device Path +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID. + /// + EFI_GUID Guid; + /// + /// Bitmap of supported flow control types. + /// Bit 0 set indicates hardware flow control. + /// Bit 1 set indicates Xon/Xoff flow control. + /// All other bits are reserved and are clear. + /// + UINT32 FlowControlMap; +} UART_FLOW_CONTROL_DEVICE_PATH; + +#define UART_FLOW_CONTROL_HARDWARE 0x00000001 +#define UART_FLOW_CONTROL_XON_XOFF 0x00000010 + +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +/// +/// Serial Attached SCSI (SAS) Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_SAS GUID. + /// + EFI_GUID Guid; + /// + /// Reserved for future use. + /// + UINT32 Reserved; + /// + /// SAS Address for Serial Attached SCSI Target. + /// + UINT64 SasAddress; + /// + /// SAS Logical Unit Number. + /// + UINT64 Lun; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SAS_DEVICE_PATH; + +/// +/// Serial Attached SCSI (SAS) Ex Device Path SubType +/// +#define MSG_SASEX_DP 0x16 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port. + /// + UINT8 SasAddress[8]; + /// + /// 8-byte array of the SAS Logical Unit Number. + /// + UINT8 Lun[8]; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SASEX_DEVICE_PATH; + +/// +/// NvmExpress Namespace Device Path SubType. +/// +#define MSG_NVME_NAMESPACE_DP 0x17 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 NamespaceId; + UINT64 NamespaceUuid; +} NVME_NAMESPACE_DEVICE_PATH; + +/// +/// iSCSI Device Path SubType +/// +#define MSG_ISCSI_DP 0x13 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Network Protocol (0 = TCP, 1+ = reserved). + /// + UINT16 NetworkProtocol; + /// + /// iSCSI Login Options. + /// + UINT16 LoginOption; + /// + /// iSCSI Logical Unit Number. + /// + UINT64 Lun; + /// + /// iSCSI Target Portal group tag the initiator intends + /// to establish a session with. + /// + UINT16 TargetPortalGroupTag; + /// + /// iSCSI NodeTarget Name. The length of the name + /// is determined by subtracting the offset of this field from Length. + /// + /// CHAR8 iSCSI Target Name. +} ISCSI_DEVICE_PATH; + +#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002 +#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000 +#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 +#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 + +/// +/// VLAN Device Path SubType. +/// +#define MSG_VLAN_DP 0x14 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// VLAN identifier (0-4094). + /// + UINT16 VlanId; +} VLAN_DEVICE_PATH; + +// +// Media Device Path +// +#define MEDIA_DEVICE_PATH 0x04 + +/// +/// Hard Drive Media Device Path SubType. +/// +#define MEDIA_HARDDRIVE_DP 0x01 + +/// +/// The Hard Drive Media Device Path is used to represent a partition on a hard drive. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Describes the entry in a partition table, starting with entry 1. + /// Partition number zero represents the entire device. Valid + /// partition numbers for a MBR partition are [1, 4]. Valid + /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries]. + /// + UINT32 PartitionNumber; + /// + /// Starting LBA of the partition on the hard drive. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Logical Blocks. + /// + UINT64 PartitionSize; + /// + /// Signature unique to this partition: + /// If SignatureType is 0, this field has to be initialized with 16 zeros. + /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of this field. + /// The other 12 bytes are initialized with zeros. + /// If SignatureType is 2, this field contains a 16 byte signature. + /// + UINT8 Signature[16]; + /// + /// Partition Format: (Unused values reserved). + /// 0x01 - PC-AT compatible legacy MBR. + /// 0x02 - GUID Partition Table. + /// + UINT8 MBRType; + /// + /// Type of Disk Signature: (Unused values reserved). + /// 0x00 - No Disk Signature. + /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR. + /// 0x02 - GUID signature. + /// + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define NO_DISK_SIGNATURE 0x00 +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +/// +/// CD-ROM Media Device Path SubType. +/// +#define MEDIA_CDROM_DP 0x02 + +/// +/// The CD-ROM Media Device Path is used to define a system partition that exists on a CD-ROM. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Boot Entry number from the Boot Catalog. The Initial/Default entry is defined as zero. + /// + UINT32 BootEntry; + /// + /// Starting RBA of the partition on the medium. CD-ROMs use Relative logical Block Addressing. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Blocks, also called Sectors. + /// + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MEDIA_VENDOR_DP 0x03 ///< Media vendor device path subtype. + +/// +/// File Path Media Device Path SubType +/// +#define MEDIA_FILEPATH_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// A NULL-terminated Path string including directory and file names. + /// + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH OFFSET_OF(FILEPATH_DEVICE_PATH,PathName) + +/// +/// Media Protocol Device Path SubType. +/// +#define MEDIA_PROTOCOL_DP 0x05 + +/// +/// The Media Protocol Device Path is used to denote the protocol that is being +/// used in a device path at the location of the path specified. +/// Many protocols are inherent to the style of device path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The ID of the protocol. + /// + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +/// +/// PIWG Firmware File SubType. +/// +#define MEDIA_PIWG_FW_FILE_DP 0x06 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware file. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware file name + /// + EFI_GUID FvFileName; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +/// +/// PIWG Firmware Volume Device Path SubType. +/// +#define MEDIA_PIWG_FW_VOL_DP 0x07 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware volume. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware volume name. + /// + EFI_GUID FvName; +} MEDIA_FW_VOL_DEVICE_PATH; + +/// +/// Media relative offset range device path. +/// +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08 + +/// +/// Used to describe the offset range of media relative. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 StartingOffset; + UINT64 EndingOffset; +} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH; + +/// +/// BIOS Boot Specification Device Path. +/// +#define BBS_DEVICE_PATH 0x05 + +/// +/// BIOS Boot Specification Device Path SubType. +/// +#define BBS_BBS_DP 0x01 + +/// +/// This Device Path is used to describe the booting of non-EFI-aware operating systems. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device Type as defined by the BIOS Boot Specification. + /// + UINT16 DeviceType; + /// + /// Status Flags as defined by the BIOS Boot Specification. + /// + UINT16 StatusFlag; + /// + /// Null-terminated ASCII string that describes the boot device to a user. + /// + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +// +// DeviceType definitions - from BBS specification +// +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_BEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + + +/// +/// Union of all possible Device Paths and pointers to Device Paths. +/// +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH ExtendedAcpi; + ACPI_ADR_DEVICE_PATH AcpiAdr; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + FIBRECHANNELEX_DEVICE_PATH FibreChannelEx; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + USB_WWID_DEVICE_PATH UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicUnit; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + VLAN_DEVICE_PATH Vlan; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + UART_FLOW_CONTROL_DEVICE_PATH UartFlowControl; + SAS_DEVICE_PATH Sas; + SASEX_DEVICE_PATH SasEx; + NVME_NAMESPACE_DEVICE_PATH NvmeNamespace; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset; + + BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + + + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + + CONTROLLER_DEVICE_PATH *Controller; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + ISCSI_DEVICE_PATH *Iscsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + FIBRECHANNELEX_DEVICE_PATH *FibreChannelEx; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + USB_WWID_DEVICE_PATH *UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicUnit; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + VLAN_DEVICE_PATH *Vlan; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + SAS_DEVICE_PATH *Sas; + SASEX_DEVICE_PATH *SasEx; + NVME_NAMESPACE_DEVICE_PATH *NvmeNamespace; + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH *FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; +} EFI_DEV_PATH_PTR; + +#pragma pack() + +#define END_DEVICE_PATH_TYPE 0x7f +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xFF +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 + +extern EFI_GUID gEfiDevicePathProtocolGuid; + +#endif diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/GraphicsOutput.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/GraphicsOutput.h new file mode 100644 index 00000000..0621b577 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/GraphicsOutput.h @@ -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.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/LoadedImage.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/LoadedImage.h new file mode 100644 index 00000000..12e5e2d7 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/LoadedImage.h @@ -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.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleFileSystem.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleFileSystem.h new file mode 100644 index 00000000..37888d51 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleFileSystem.h @@ -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.
+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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextIn.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextIn.h new file mode 100644 index 00000000..a3335f05 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextIn.h @@ -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.
+ 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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextInEx.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextInEx.h new file mode 100644 index 00000000..0950c321 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextInEx.h @@ -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.
+ 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 + diff --git a/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextOut.h b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextOut.h new file mode 100644 index 00000000..7e1c70c6 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Protocol/SimpleTextOut.h @@ -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.
+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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi.h b/wimboot/wimboot-2.7.3/src/efi/Uefi.h new file mode 100644 index 00000000..326b4ac0 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi.h @@ -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.
+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 + diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiBaseType.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiBaseType.h new file mode 100644 index 00000000..fabf72e2 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiBaseType.h @@ -0,0 +1,301 @@ +/** @file + Defines data types and constants introduced in UEFI. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+ +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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiGpt.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiGpt.h new file mode 100644 index 00000000..5aa2ee2f --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiGpt.h @@ -0,0 +1,141 @@ +/** @file + EFI Guid Partition Table Format Definition. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+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 + + diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiInternalFormRepresentation.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiInternalFormRepresentation.h new file mode 100644 index 00000000..790555e7 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiInternalFormRepresentation.h @@ -0,0 +1,2106 @@ +/** @file + This file defines the encoding for the VFR (Visual Form Representation) language. + IFR is primarily consumed by the EFI presentation engine, and produced by EFI + internal application and drivers as well as all add-in card option-ROM drivers + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+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. + + @par Revision Reference: + These definitions are from UEFI 2.1 and 2.2. + +**/ + +#ifndef __UEFI_INTERNAL_FORMREPRESENTATION_H__ +#define __UEFI_INTERNAL_FORMREPRESENTATION_H__ + +#include "efi/Guid/HiiFormMapMethodGuid.h" + +/// +/// The following types are currently defined: +/// +typedef VOID* EFI_HII_HANDLE; +typedef CHAR16* EFI_STRING; +typedef UINT16 EFI_IMAGE_ID; +typedef UINT16 EFI_QUESTION_ID; +typedef UINT16 EFI_STRING_ID; +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_VARSTORE_ID; +typedef UINT16 EFI_ANIMATION_ID; + +typedef UINT16 EFI_DEFAULT_ID; + +typedef UINT32 EFI_HII_FONT_STYLE; + + + +#pragma pack(1) + +// +// Definitions for Package Lists and Package Headers +// Section 27.3.1 +// + +/// +/// The header found at the start of each package list. +/// +typedef struct { + EFI_GUID PackageListGuid; + UINT32 PackageLength; +} EFI_HII_PACKAGE_LIST_HEADER; + +/// +/// The header found at the start of each package. +/// +typedef struct { + UINT32 Length:24; + UINT32 Type:8; + // UINT8 Data[...]; +} EFI_HII_PACKAGE_HEADER; + +// +// Value of HII package type +// +#define EFI_HII_PACKAGE_TYPE_ALL 0x00 +#define EFI_HII_PACKAGE_TYPE_GUID 0x01 +#define EFI_HII_PACKAGE_FORMS 0x02 +#define EFI_HII_PACKAGE_STRINGS 0x04 +#define EFI_HII_PACKAGE_FONTS 0x05 +#define EFI_HII_PACKAGE_IMAGES 0x06 +#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 +#define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09 +#define EFI_HII_PACKAGE_ANIMATIONS 0x0A +#define EFI_HII_PACKAGE_END 0xDF +#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 +#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF + +// +// Definitions for Simplified Font Package +// + +/// +/// Contents of EFI_NARROW_GLYPH.Attributes. +///@{ +#define EFI_GLYPH_NON_SPACING 0x01 +#define EFI_GLYPH_WIDE 0x02 +#define EFI_GLYPH_HEIGHT 19 +#define EFI_GLYPH_WIDTH 8 +///@} + +/// +/// The EFI_NARROW_GLYPH has a preferred dimension (w x h) of 8 x 19 pixels. +/// +typedef struct { + /// + /// The Unicode representation of the glyph. The term weight is the + /// technical term for a character code. + /// + CHAR16 UnicodeWeight; + /// + /// The data element containing the glyph definitions. + /// + UINT8 Attributes; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +/// +/// The EFI_WIDE_GLYPH has a preferred dimension (w x h) of 16 x 19 pixels, which is large enough +/// to accommodate logographic characters. +/// +typedef struct { + /// + /// The Unicode representation of the glyph. The term weight is the + /// technical term for a character code. + /// + CHAR16 UnicodeWeight; + /// + /// The data element containing the glyph definitions. + /// + UINT8 Attributes; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol2[EFI_GLYPH_HEIGHT]; + /// + /// Ensures that sizeof (EFI_WIDE_GLYPH) is twice the + /// sizeof (EFI_NARROW_GLYPH). The contents of Pad must + /// be zero. + /// + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + +/// +/// A simplified font package consists of a font header +/// followed by a series of glyph structures. +/// +typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + // EFI_NARROW_GLYPH NarrowGlyphs[]; + // EFI_WIDE_GLYPH WideGlyphs[]; +} EFI_HII_SIMPLE_FONT_PACKAGE_HDR; + +// +// Definitions for Font Package +// Section 27.3.3 +// + +// +// Value for font style +// +#define EFI_HII_FONT_STYLE_NORMAL 0x00000000 +#define EFI_HII_FONT_STYLE_BOLD 0x00000001 +#define EFI_HII_FONT_STYLE_ITALIC 0x00000002 +#define EFI_HII_FONT_STYLE_EMBOSS 0x00010000 +#define EFI_HII_FONT_STYLE_OUTLINE 0x00020000 +#define EFI_HII_FONT_STYLE_SHADOW 0x00040000 +#define EFI_HII_FONT_STYLE_UNDERLINE 0x00080000 +#define EFI_HII_FONT_STYLE_DBL_UNDER 0x00100000 + +typedef struct _EFI_HII_GLYPH_INFO { + UINT16 Width; + UINT16 Height; + INT16 OffsetX; + INT16 OffsetY; + INT16 AdvanceX; +} EFI_HII_GLYPH_INFO; + +/// +/// The fixed header consists of a standard record header, +/// then the character values in this section, the flags +/// (including the encoding method) and the offsets of the glyph +/// information, the glyph bitmaps and the character map. +/// +typedef struct _EFI_HII_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 GlyphBlockOffset; + EFI_HII_GLYPH_INFO Cell; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontFamily[1]; +} EFI_HII_FONT_PACKAGE_HDR; + +// +// Value of different glyph info block types +// +#define EFI_HII_GIBT_END 0x00 +#define EFI_HII_GIBT_GLYPH 0x10 +#define EFI_HII_GIBT_GLYPHS 0x11 +#define EFI_HII_GIBT_GLYPH_DEFAULT 0x12 +#define EFI_HII_GIBT_GLYPHS_DEFAULT 0x13 +#define EFI_HII_GIBT_DUPLICATE 0x20 +#define EFI_HII_GIBT_SKIP2 0x21 +#define EFI_HII_GIBT_SKIP1 0x22 +#define EFI_HII_GIBT_DEFAULTS 0x23 +#define EFI_HII_GIBT_EXT1 0x30 +#define EFI_HII_GIBT_EXT2 0x31 +#define EFI_HII_GIBT_EXT4 0x32 + +typedef struct _EFI_HII_GLYPH_BLOCK { + UINT8 BlockType; +} EFI_HII_GLYPH_BLOCK; + +// +// Definition of different glyph info block types +// + +typedef struct _EFI_HII_GIBT_DEFAULTS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; +} EFI_HII_GIBT_DEFAULTS_BLOCK; + +typedef struct _EFI_HII_GIBT_DUPLICATE_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + CHAR16 CharValue; +} EFI_HII_GIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_GLYPH_GIBT_END_BLOCK { + EFI_HII_GLYPH_BLOCK Header; +} EFI_GLYPH_GIBT_END_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_GIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_GIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT4_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_GIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT16 Count; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPHS_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 Count; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_GIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_GIBT_SKIP2_BLOCK; + +// +// Definitions for Device Path Package +// Section 27.3.4 +// + +/// +/// The device path package is used to carry a device path +/// associated with the package list. +/// +typedef struct _EFI_HII_DEVICE_PATH_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + // EFI_DEVICE_PATH_PROTOCOL DevicePath[]; +} EFI_HII_DEVICE_PATH_PACKAGE_HDR; + +// +// Definitions for GUID Package +// Section 27.3.5 +// + +/// +/// The GUID package is used to carry data where the format is defined by a GUID. +/// +typedef struct _EFI_HII_GUID_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + EFI_GUID Guid; + // Data per GUID definition may follow +} EFI_HII_GUID_PACKAGE_HDR; + +// +// Definitions for String Package +// Section 27.3.6 +// + +#define UEFI_CONFIG_LANG "x-UEFI" +#define UEFI_CONFIG_LANG_2 "x-i-UEFI" + +/// +/// The fixed header consists of a standard record header and then the string identifiers +/// contained in this section and the offsets of the string and language information. +/// +typedef struct _EFI_HII_STRING_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 StringInfoOffset; + CHAR16 LanguageWindow[16]; + EFI_STRING_ID LanguageName; + CHAR8 Language[1]; +} EFI_HII_STRING_PACKAGE_HDR; + +typedef struct { + UINT8 BlockType; +} EFI_HII_STRING_BLOCK; + +// +// Value of different string information block types +// +#define EFI_HII_SIBT_END 0x00 +#define EFI_HII_SIBT_STRING_SCSU 0x10 +#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11 +#define EFI_HII_SIBT_STRINGS_SCSU 0x12 +#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13 +#define EFI_HII_SIBT_STRING_UCS2 0x14 +#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15 +#define EFI_HII_SIBT_STRINGS_UCS2 0x16 +#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17 +#define EFI_HII_SIBT_DUPLICATE 0x20 +#define EFI_HII_SIBT_SKIP2 0x21 +#define EFI_HII_SIBT_SKIP1 0x22 +#define EFI_HII_SIBT_EXT1 0x30 +#define EFI_HII_SIBT_EXT2 0x31 +#define EFI_HII_SIBT_EXT4 0x32 +#define EFI_HII_SIBT_FONT 0x40 + +// +// Definition of different string information block types +// + +typedef struct _EFI_HII_SIBT_DUPLICATE_BLOCK { + EFI_HII_STRING_BLOCK Header; + EFI_STRING_ID StringId; +} EFI_HII_SIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_SIBT_END_BLOCK { + EFI_HII_STRING_BLOCK Header; +} EFI_HII_SIBT_END_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_SIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_SIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT4_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_SIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_SIBT_FONT_BLOCK { + EFI_HII_SIBT_EXT2_BLOCK Header; + UINT8 FontId; + UINT16 FontSize; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontName[1]; +} EFI_HII_SIBT_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_SIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_SIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK; + +// +// Definitions for Image Package +// Section 27.3.7 +// + +typedef struct _EFI_HII_IMAGE_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 ImageInfoOffset; + UINT32 PaletteInfoOffset; +} EFI_HII_IMAGE_PACKAGE_HDR; + +typedef struct _EFI_HII_IMAGE_BLOCK { + UINT8 BlockType; +} EFI_HII_IMAGE_BLOCK; + +// +// Value of different image information block types +// +#define EFI_HII_IIBT_END 0x00 +#define EFI_HII_IIBT_IMAGE_1BIT 0x10 +#define EFI_HII_IIBT_IMAGE_1BIT_TRANS 0x11 +#define EFI_HII_IIBT_IMAGE_4BIT 0x12 +#define EFI_HII_IIBT_IMAGE_4BIT_TRANS 0x13 +#define EFI_HII_IIBT_IMAGE_8BIT 0x14 +#define EFI_HII_IIBT_IMAGE_8BIT_TRANS 0x15 +#define EFI_HII_IIBT_IMAGE_24BIT 0x16 +#define EFI_HII_IIBT_IMAGE_24BIT_TRANS 0x17 +#define EFI_HII_IIBT_IMAGE_JPEG 0x18 +#define EFI_HII_IIBT_DUPLICATE 0x20 +#define EFI_HII_IIBT_SKIP2 0x21 +#define EFI_HII_IIBT_SKIP1 0x22 +#define EFI_HII_IIBT_EXT1 0x30 +#define EFI_HII_IIBT_EXT2 0x31 +#define EFI_HII_IIBT_EXT4 0x32 + +// +// Definition of different image information block types +// + +typedef struct _EFI_HII_IIBT_END_BLOCK { + EFI_HII_IMAGE_BLOCK Header; +} EFI_HII_IIBT_END_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_IIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_IIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT4_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_IIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_1BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_RGB_PIXEL { + UINT8 b; + UINT8 g; + UINT8 r; +} EFI_HII_RGB_PIXEL; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BASE { + UINT16 Width; + UINT16 Height; + EFI_HII_RGB_PIXEL Bitmap[1]; +} EFI_HII_IIBT_IMAGE_24BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_4BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_8BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_PALETTE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_TRAN_BLOCK; + +typedef struct _EFI_HII_IIBT_DUPLICATE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_IMAGE_ID ImageId; +} EFI_HII_IIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_IIBT_JPEG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_JPEG_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_IIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_IIBT_SKIP2_BLOCK; + +// +// Definitions for Palette Information +// + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO_HEADER { + UINT16 PaletteCount; +} EFI_HII_IMAGE_PALETTE_INFO_HEADER; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO { + UINT16 PaletteSize; + EFI_HII_RGB_PIXEL PaletteValue[1]; +} EFI_HII_IMAGE_PALETTE_INFO; + +// +// Definitions for Forms Package +// Section 27.3.8 +// + +/// +/// The Form package is used to carry form-based encoding data. +/// +typedef struct _EFI_HII_FORM_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + // EFI_IFR_OP_HEADER OpCodeHeader; + // More op-codes follow +} EFI_HII_FORM_PACKAGE_HDR; + +typedef struct { + UINT8 Hour; + UINT8 Minute; + UINT8 Second; +} EFI_HII_TIME; + +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; +} EFI_HII_DATE; + +typedef struct { + EFI_QUESTION_ID QuestionId; + EFI_FORM_ID FormId; + EFI_GUID FormSetGuid; + EFI_STRING_ID DevicePath; +} EFI_HII_REF; + +typedef union { + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + BOOLEAN b; + EFI_HII_TIME time; + EFI_HII_DATE date; + EFI_STRING_ID string; ///< EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION + EFI_HII_REF ref; ///< EFI_IFR_TYPE_REF + // UINT8 buffer[]; ///< EFI_IFR_TYPE_BUFFER +} EFI_IFR_TYPE_VALUE; + +// +// IFR Opcodes +// +#define EFI_IFR_FORM_OP 0x01 +#define EFI_IFR_SUBTITLE_OP 0x02 +#define EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_IMAGE_OP 0x04 +#define EFI_IFR_ONE_OF_OP 0x05 +#define EFI_IFR_CHECKBOX_OP 0x06 +#define EFI_IFR_NUMERIC_OP 0x07 +#define EFI_IFR_PASSWORD_OP 0x08 +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 +#define EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_LOCKED_OP 0x0B +#define EFI_IFR_ACTION_OP 0x0C +#define EFI_IFR_RESET_BUTTON_OP 0x0D +#define EFI_IFR_FORM_SET_OP 0x0E +#define EFI_IFR_REF_OP 0x0F +#define EFI_IFR_NO_SUBMIT_IF_OP 0x10 +#define EFI_IFR_INCONSISTENT_IF_OP 0x11 +#define EFI_IFR_EQ_ID_VAL_OP 0x12 +#define EFI_IFR_EQ_ID_ID_OP 0x13 +#define EFI_IFR_EQ_ID_VAL_LIST_OP 0x14 +#define EFI_IFR_AND_OP 0x15 +#define EFI_IFR_OR_OP 0x16 +#define EFI_IFR_NOT_OP 0x17 +#define EFI_IFR_RULE_OP 0x18 +#define EFI_IFR_GRAY_OUT_IF_OP 0x19 +#define EFI_IFR_DATE_OP 0x1A +#define EFI_IFR_TIME_OP 0x1B +#define EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_REFRESH_OP 0x1D +#define EFI_IFR_DISABLE_IF_OP 0x1E +#define EFI_IFR_ANIMATION_OP 0x1F +#define EFI_IFR_TO_LOWER_OP 0x20 +#define EFI_IFR_TO_UPPER_OP 0x21 +#define EFI_IFR_MAP_OP 0x22 +#define EFI_IFR_ORDERED_LIST_OP 0x23 +#define EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_NAME_VALUE_OP 0x25 +#define EFI_IFR_VARSTORE_EFI_OP 0x26 +#define EFI_IFR_VARSTORE_DEVICE_OP 0x27 +#define EFI_IFR_VERSION_OP 0x28 +#define EFI_IFR_END_OP 0x29 +#define EFI_IFR_MATCH_OP 0x2A +#define EFI_IFR_GET_OP 0x2B +#define EFI_IFR_SET_OP 0x2C +#define EFI_IFR_READ_OP 0x2D +#define EFI_IFR_WRITE_OP 0x2E +#define EFI_IFR_EQUAL_OP 0x2F +#define EFI_IFR_NOT_EQUAL_OP 0x30 +#define EFI_IFR_GREATER_THAN_OP 0x31 +#define EFI_IFR_GREATER_EQUAL_OP 0x32 +#define EFI_IFR_LESS_THAN_OP 0x33 +#define EFI_IFR_LESS_EQUAL_OP 0x34 +#define EFI_IFR_BITWISE_AND_OP 0x35 +#define EFI_IFR_BITWISE_OR_OP 0x36 +#define EFI_IFR_BITWISE_NOT_OP 0x37 +#define EFI_IFR_SHIFT_LEFT_OP 0x38 +#define EFI_IFR_SHIFT_RIGHT_OP 0x39 +#define EFI_IFR_ADD_OP 0x3A +#define EFI_IFR_SUBTRACT_OP 0x3B +#define EFI_IFR_MULTIPLY_OP 0x3C +#define EFI_IFR_DIVIDE_OP 0x3D +#define EFI_IFR_MODULO_OP 0x3E +#define EFI_IFR_RULE_REF_OP 0x3F +#define EFI_IFR_QUESTION_REF1_OP 0x40 +#define EFI_IFR_QUESTION_REF2_OP 0x41 +#define EFI_IFR_UINT8_OP 0x42 +#define EFI_IFR_UINT16_OP 0x43 +#define EFI_IFR_UINT32_OP 0x44 +#define EFI_IFR_UINT64_OP 0x45 +#define EFI_IFR_TRUE_OP 0x46 +#define EFI_IFR_FALSE_OP 0x47 +#define EFI_IFR_TO_UINT_OP 0x48 +#define EFI_IFR_TO_STRING_OP 0x49 +#define EFI_IFR_TO_BOOLEAN_OP 0x4A +#define EFI_IFR_MID_OP 0x4B +#define EFI_IFR_FIND_OP 0x4C +#define EFI_IFR_TOKEN_OP 0x4D +#define EFI_IFR_STRING_REF1_OP 0x4E +#define EFI_IFR_STRING_REF2_OP 0x4F +#define EFI_IFR_CONDITIONAL_OP 0x50 +#define EFI_IFR_QUESTION_REF3_OP 0x51 +#define EFI_IFR_ZERO_OP 0x52 +#define EFI_IFR_ONE_OP 0x53 +#define EFI_IFR_ONES_OP 0x54 +#define EFI_IFR_UNDEFINED_OP 0x55 +#define EFI_IFR_LENGTH_OP 0x56 +#define EFI_IFR_DUP_OP 0x57 +#define EFI_IFR_THIS_OP 0x58 +#define EFI_IFR_SPAN_OP 0x59 +#define EFI_IFR_VALUE_OP 0x5A +#define EFI_IFR_DEFAULT_OP 0x5B +#define EFI_IFR_DEFAULTSTORE_OP 0x5C +#define EFI_IFR_FORM_MAP_OP 0x5D +#define EFI_IFR_CATENATE_OP 0x5E +#define EFI_IFR_GUID_OP 0x5F +#define EFI_IFR_SECURITY_OP 0x60 +#define EFI_IFR_MODAL_TAG_OP 0x61 +#define EFI_IFR_REFRESH_ID_OP 0x62 +#define EFI_IFR_WARNING_IF_OP 0x63 + +// +// Definitions of IFR Standard Headers +// Section 27.3.8.2 +// + +typedef struct _EFI_IFR_OP_HEADER { + UINT8 OpCode; + UINT8 Length:7; + UINT8 Scope:1; +} EFI_IFR_OP_HEADER; + +typedef struct _EFI_IFR_STATEMENT_HEADER { + EFI_STRING_ID Prompt; + EFI_STRING_ID Help; +} EFI_IFR_STATEMENT_HEADER; + +typedef struct _EFI_IFR_QUESTION_HEADER { + EFI_IFR_STATEMENT_HEADER Header; + EFI_QUESTION_ID QuestionId; + EFI_VARSTORE_ID VarStoreId; + union { + EFI_STRING_ID VarName; + UINT16 VarOffset; + } VarStoreInfo; + UINT8 Flags; +} EFI_IFR_QUESTION_HEADER; + +// +// Flag values of EFI_IFR_QUESTION_HEADER +// +#define EFI_IFR_FLAG_READ_ONLY 0x01 +#define EFI_IFR_FLAG_CALLBACK 0x04 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80 + +// +// Definition for Opcode Reference +// Section 27.3.8.3 +// +typedef struct _EFI_IFR_DEFAULTSTORE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DefaultName; + UINT16 DefaultId; +} EFI_IFR_DEFAULTSTORE; + +// +// Default Identifier of default store +// +#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000 +#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001 +#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_END 0x7fff +#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000 +#define EFI_HII_DEFAULT_CLASS_HARDWARE_END 0xbfff +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000 +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END 0xffff + +typedef struct _EFI_IFR_VARSTORE { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_VARSTORE_ID VarStoreId; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE; + +typedef struct _EFI_IFR_VARSTORE_EFI { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; + UINT32 Attributes; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE_EFI; + +typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; +} EFI_IFR_VARSTORE_NAME_VALUE; + +typedef struct _EFI_IFR_FORM_SET { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID Help; + UINT8 Flags; + // EFI_GUID ClassGuid[]; +} EFI_IFR_FORM_SET; + +typedef struct _EFI_IFR_END { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END; + +typedef struct _EFI_IFR_FORM { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + EFI_STRING_ID FormTitle; +} EFI_IFR_FORM; + +typedef struct _EFI_IFR_IMAGE { + EFI_IFR_OP_HEADER Header; + EFI_IMAGE_ID Id; +} EFI_IFR_IMAGE; + +typedef struct _EFI_IFR_MODAL_TAG { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODAL_TAG; + +typedef struct _EFI_IFR_LOCKED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LOCKED; + +typedef struct _EFI_IFR_RULE { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE; + +typedef struct _EFI_IFR_DEFAULT { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_DEFAULT; + +typedef struct _EFI_IFR_DEFAULT_2 { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; +} EFI_IFR_DEFAULT_2; + +typedef struct _EFI_IFR_VALUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VALUE; + +typedef struct _EFI_IFR_SUBTITLE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + UINT8 Flags; +} EFI_IFR_SUBTITLE; + +#define EFI_IFR_FLAGS_HORIZONTAL 0x01 + +typedef struct _EFI_IFR_CHECKBOX { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_CHECKBOX; + +#define EFI_IFR_CHECKBOX_DEFAULT 0x01 +#define EFI_IFR_CHECKBOX_DEFAULT_MFG 0x02 + +typedef struct _EFI_IFR_TEXT { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_STRING_ID TextTwo; +} EFI_IFR_TEXT; + +typedef struct _EFI_IFR_REF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; +} EFI_IFR_REF; + +typedef struct _EFI_IFR_REF2 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_REF2; + +typedef struct _EFI_IFR_REF3 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; +} EFI_IFR_REF3; + +typedef struct _EFI_IFR_REF4 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; + EFI_STRING_ID DevicePath; +} EFI_IFR_REF4; + +typedef struct _EFI_IFR_REF5 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_REF5; + +typedef struct _EFI_IFR_RESET_BUTTON { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_DEFAULT_ID DefaultId; +} EFI_IFR_RESET_BUTTON; + +typedef struct _EFI_IFR_ACTION { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_STRING_ID QuestionConfig; +} EFI_IFR_ACTION; + +typedef struct _EFI_IFR_ACTION_1 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_ACTION_1; + +typedef struct _EFI_IFR_DATE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_DATE; + +// +// Flags that describe the behavior of the question. +// +#define EFI_QF_DATE_YEAR_SUPPRESS 0x01 +#define EFI_QF_DATE_MONTH_SUPPRESS 0x02 +#define EFI_QF_DATE_DAY_SUPPRESS 0x04 + +#define EFI_QF_DATE_STORAGE 0x30 +#define QF_DATE_STORAGE_NORMAL 0x00 +#define QF_DATE_STORAGE_TIME 0x10 +#define QF_DATE_STORAGE_WAKEUP 0x20 + +typedef union { + struct { + UINT8 MinValue; + UINT8 MaxValue; + UINT8 Step; + } u8; + struct { + UINT16 MinValue; + UINT16 MaxValue; + UINT16 Step; + } u16; + struct { + UINT32 MinValue; + UINT32 MaxValue; + UINT32 Step; + } u32; + struct { + UINT64 MinValue; + UINT64 MaxValue; + UINT64 Step; + } u64; +} MINMAXSTEP_DATA; + +typedef struct _EFI_IFR_NUMERIC { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_NUMERIC; + +// +// Flags related to the numeric question +// +#define EFI_IFR_NUMERIC_SIZE 0x03 +#define EFI_IFR_NUMERIC_SIZE_1 0x00 +#define EFI_IFR_NUMERIC_SIZE_2 0x01 +#define EFI_IFR_NUMERIC_SIZE_4 0x02 +#define EFI_IFR_NUMERIC_SIZE_8 0x03 + +#define EFI_IFR_DISPLAY 0x30 +#define EFI_IFR_DISPLAY_INT_DEC 0x00 +#define EFI_IFR_DISPLAY_UINT_DEC 0x10 +#define EFI_IFR_DISPLAY_UINT_HEX 0x20 + +typedef struct _EFI_IFR_ONE_OF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_ONE_OF; + +typedef struct _EFI_IFR_STRING { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MinSize; + UINT8 MaxSize; + UINT8 Flags; +} EFI_IFR_STRING; + +#define EFI_IFR_STRING_MULTI_LINE 0x01 + +typedef struct _EFI_IFR_PASSWORD { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT16 MinSize; + UINT16 MaxSize; +} EFI_IFR_PASSWORD; + +typedef struct _EFI_IFR_ORDERED_LIST { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MaxContainers; + UINT8 Flags; +} EFI_IFR_ORDERED_LIST; + +#define EFI_IFR_UNIQUE_SET 0x01 +#define EFI_IFR_NO_EMPTY_SET 0x02 + +typedef struct _EFI_IFR_TIME { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_TIME; + +// +// A bit-mask that determines which unique settings are active for this opcode. +// +#define QF_TIME_HOUR_SUPPRESS 0x01 +#define QF_TIME_MINUTE_SUPPRESS 0x02 +#define QF_TIME_SECOND_SUPPRESS 0x04 + +#define QF_TIME_STORAGE 0x30 +#define QF_TIME_STORAGE_NORMAL 0x00 +#define QF_TIME_STORAGE_TIME 0x10 +#define QF_TIME_STORAGE_WAKEUP 0x20 + +typedef struct _EFI_IFR_DISABLE_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DISABLE_IF; + +typedef struct _EFI_IFR_SUPPRESS_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUPPRESS_IF; + +typedef struct _EFI_IFR_GRAY_OUT_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GRAY_OUT_IF; + +typedef struct _EFI_IFR_INCONSISTENT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_INCONSISTENT_IF; + +typedef struct _EFI_IFR_NO_SUBMIT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_NO_SUBMIT_IF; + +typedef struct _EFI_IFR_WARNING_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Warning; + UINT8 TimeOut; +} EFI_IFR_WARNING_IF; + +typedef struct _EFI_IFR_REFRESH { + EFI_IFR_OP_HEADER Header; + UINT8 RefreshInterval; +} EFI_IFR_REFRESH; + +typedef struct _EFI_IFR_VARSTORE_DEVICE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_VARSTORE_DEVICE; + +typedef struct _EFI_IFR_ONE_OF_OPTION { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Option; + UINT8 Flags; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_ONE_OF_OPTION; + +// +// Types of the option's value. +// +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 +#define EFI_IFR_TYPE_UNDEFINED 0x09 +#define EFI_IFR_TYPE_ACTION 0x0A +#define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C + +#define EFI_IFR_OPTION_DEFAULT 0x10 +#define EFI_IFR_OPTION_DEFAULT_MFG 0x20 + +typedef struct _EFI_IFR_GUID { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + //Optional Data Follows +} EFI_IFR_GUID; + +typedef struct _EFI_IFR_REFRESH_ID { + EFI_IFR_OP_HEADER Header; + EFI_GUID RefreshEventGroupId; +} EFI_IFR_REFRESH_ID; + +typedef struct _EFI_IFR_DUP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DUP; + +typedef struct _EFI_IFR_EQ_ID_ID { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; +} EFI_IFR_EQ_ID_ID; + +typedef struct _EFI_IFR_EQ_ID_VAL { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 Value; +} EFI_IFR_EQ_ID_VAL; + +typedef struct _EFI_IFR_EQ_ID_VAL_LIST { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 ListLength; + UINT16 ValueList[1]; +} EFI_IFR_EQ_ID_VAL_LIST; + +typedef struct _EFI_IFR_UINT8 { + EFI_IFR_OP_HEADER Header; + UINT8 Value; +} EFI_IFR_UINT8; + +typedef struct _EFI_IFR_UINT16 { + EFI_IFR_OP_HEADER Header; + UINT16 Value; +} EFI_IFR_UINT16; + +typedef struct _EFI_IFR_UINT32 { + EFI_IFR_OP_HEADER Header; + UINT32 Value; +} EFI_IFR_UINT32; + +typedef struct _EFI_IFR_UINT64 { + EFI_IFR_OP_HEADER Header; + UINT64 Value; +} EFI_IFR_UINT64; + +typedef struct _EFI_IFR_QUESTION_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_QUESTION_REF1; + +typedef struct _EFI_IFR_QUESTION_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF2; + +typedef struct _EFI_IFR_QUESTION_REF3 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF3; + +typedef struct _EFI_IFR_QUESTION_REF3_2 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_QUESTION_REF3_2; + +typedef struct _EFI_IFR_QUESTION_REF3_3 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; + EFI_GUID Guid; +} EFI_IFR_QUESTION_REF3_3; + +typedef struct _EFI_IFR_RULE_REF { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE_REF; + +typedef struct _EFI_IFR_STRING_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID StringId; +} EFI_IFR_STRING_REF1; + +typedef struct _EFI_IFR_STRING_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_STRING_REF2; + +typedef struct _EFI_IFR_THIS { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_THIS; + +typedef struct _EFI_IFR_TRUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TRUE; + +typedef struct _EFI_IFR_FALSE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_FALSE; + +typedef struct _EFI_IFR_ONE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONE; + +typedef struct _EFI_IFR_ONES { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONES; + +typedef struct _EFI_IFR_ZERO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ZERO; + +typedef struct _EFI_IFR_UNDEFINED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_UNDEFINED; + +typedef struct _EFI_IFR_VERSION { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VERSION; + +typedef struct _EFI_IFR_LENGTH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LENGTH; + +typedef struct _EFI_IFR_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT; + +typedef struct _EFI_IFR_BITWISE_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_NOT; + +typedef struct _EFI_IFR_TO_BOOLEAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_BOOLEAN; + +/// +/// For EFI_IFR_TO_STRING, when converting from +/// unsigned integers, these flags control the format: +/// 0 = unsigned decimal. +/// 1 = signed decimal. +/// 2 = hexadecimal (lower-case alpha). +/// 3 = hexadecimal (upper-case alpha). +///@{ +#define EFI_IFR_STRING_UNSIGNED_DEC 0 +#define EFI_IFR_STRING_SIGNED_DEC 1 +#define EFI_IFR_STRING_LOWERCASE_HEX 2 +#define EFI_IFR_STRING_UPPERCASE_HEX 3 +///@} + +/// +/// When converting from a buffer, these flags control the format: +/// 0 = ASCII. +/// 8 = Unicode. +///@{ +#define EFI_IFR_STRING_ASCII 0 +#define EFI_IFR_STRING_UNICODE 8 +///@} + +typedef struct _EFI_IFR_TO_STRING { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_TO_STRING; + +typedef struct _EFI_IFR_TO_UINT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UINT; + +typedef struct _EFI_IFR_TO_UPPER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UPPER; + +typedef struct _EFI_IFR_TO_LOWER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_LOWER; + +typedef struct _EFI_IFR_ADD { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ADD; + +typedef struct _EFI_IFR_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_AND; + +typedef struct _EFI_IFR_BITWISE_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_AND; + +typedef struct _EFI_IFR_BITWISE_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_OR; + +typedef struct _EFI_IFR_CATENATE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CATENATE; + +typedef struct _EFI_IFR_DIVIDE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DIVIDE; + +typedef struct _EFI_IFR_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_EQUAL; + +typedef struct _EFI_IFR_GREATER_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_EQUAL; + +typedef struct _EFI_IFR_GREATER_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_THAN; + +typedef struct _EFI_IFR_LESS_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_EQUAL; + +typedef struct _EFI_IFR_LESS_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_THAN; + +typedef struct _EFI_IFR_MATCH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MATCH; + +typedef struct _EFI_IFR_MULTIPLY { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MULTIPLY; + +typedef struct _EFI_IFR_MODULO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODULO; + +typedef struct _EFI_IFR_NOT_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT_EQUAL; + +typedef struct _EFI_IFR_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_OR; + +typedef struct _EFI_IFR_SHIFT_LEFT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_LEFT; + +typedef struct _EFI_IFR_SHIFT_RIGHT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_RIGHT; + +typedef struct _EFI_IFR_SUBTRACT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUBTRACT; + +typedef struct _EFI_IFR_CONDITIONAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CONDITIONAL; + +// +// Flags governing the matching criteria of EFI_IFR_FIND +// +#define EFI_IFR_FF_CASE_SENSITIVE 0x00 +#define EFI_IFR_FF_CASE_INSENSITIVE 0x01 + +typedef struct _EFI_IFR_FIND { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_FIND; + +typedef struct _EFI_IFR_MID { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MID; + +typedef struct _EFI_IFR_TOKEN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TOKEN; + +// +// Flags specifying whether to find the first matching string +// or the first non-matching string. +// +#define EFI_IFR_FLAGS_FIRST_MATCHING 0x00 +#define EFI_IFR_FLAGS_FIRST_NON_MATCHING 0x01 + +typedef struct _EFI_IFR_SPAN { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SPAN; + +typedef struct _EFI_IFR_SECURITY { + /// + /// Standard opcode header, where Header.Op = EFI_IFR_SECURITY_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Security permission level. + /// + EFI_GUID Permissions; +} EFI_IFR_SECURITY; + +typedef struct _EFI_IFR_FORM_MAP_METHOD { + /// + /// The string identifier which provides the human-readable name of + /// the configuration method for this standards map form. + /// + EFI_STRING_ID MethodTitle; + /// + /// Identifier which uniquely specifies the configuration methods + /// associated with this standards map form. + /// + EFI_GUID MethodIdentifier; +} EFI_IFR_FORM_MAP_METHOD; + +typedef struct _EFI_IFR_FORM_MAP { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_FORM_MAP_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// The unique identifier for this particular form. + /// + EFI_FORM_ID FormId; + /// + /// One or more configuration method's name and unique identifier. + /// + // EFI_IFR_FORM_MAP_METHOD Methods[]; +} EFI_IFR_FORM_MAP; + +typedef struct _EFI_IFR_SET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_SET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when storing the question's value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_SET; + +typedef struct _EFI_IFR_GET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_GET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when retrieving the value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_GET; + +typedef struct _EFI_IFR_READ { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_READ; + +typedef struct _EFI_IFR_WRITE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_WRITE; + +typedef struct _EFI_IFR_MAP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MAP; +// +// Definitions for Keyboard Package +// Releated definitions are in Section of EFI_HII_DATABASE_PROTOCOL +// + +/// +/// Each enumeration values maps a physical key on a keyboard. +/// +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRShift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + /// + /// Used to describe a physical key on a keyboard. + /// + EFI_KEY Key; + /// + /// Unicode character code for the Key. + /// + CHAR16 Unicode; + /// + /// Unicode character code for the key with the shift key being held down. + /// + CHAR16 ShiftedUnicode; + /// + /// Unicode character code for the key with the Alt-GR being held down. + /// + CHAR16 AltGrUnicode; + /// + /// Unicode character code for the key with the Alt-GR and shift keys being held down. + /// + CHAR16 ShiftedAltGrUnicode; + /// + /// Modifier keys are defined to allow for special functionality that is not necessarily + /// accomplished by a printable character. Many of these modifier keys are flags to toggle + /// certain state bits on and off inside of a keyboard driver. + /// + UINT16 Modifier; + UINT16 AffectedAttribute; +} EFI_KEY_DESCRIPTOR; + +/// +/// A key which is affected by all the standard shift modifiers. +/// Most keys would be expected to have this bit active. +/// +#define EFI_AFFECTED_BY_STANDARD_SHIFT 0x0001 + +/// +/// This key is affected by the caps lock so that if a keyboard driver +/// would need to disambiguate between a key which had a "1" defined +/// versus an "a" character. Having this bit turned on would tell +/// the keyboard driver to use the appropriate shifted state or not. +/// +#define EFI_AFFECTED_BY_CAPS_LOCK 0x0002 + +/// +/// Similar to the case of CAPS lock, if this bit is active, the key +/// is affected by the num lock being turned on. +/// +#define EFI_AFFECTED_BY_NUM_LOCK 0x0004 + +typedef struct { + UINT16 LayoutLength; + EFI_GUID Guid; + UINT32 LayoutDescriptorStringOffset; + UINT8 DescriptorCount; + // EFI_KEY_DESCRIPTOR Descriptors[]; +} EFI_HII_KEYBOARD_LAYOUT; + +typedef struct { + EFI_HII_PACKAGE_HEADER Header; + UINT16 LayoutCount; + // EFI_HII_KEYBOARD_LAYOUT Layout[]; +} EFI_HII_KEYBOARD_PACKAGE_HDR; + +// +// Modifier values +// +#define EFI_NULL_MODIFIER 0x0000 +#define EFI_LEFT_CONTROL_MODIFIER 0x0001 +#define EFI_RIGHT_CONTROL_MODIFIER 0x0002 +#define EFI_LEFT_ALT_MODIFIER 0x0003 +#define EFI_RIGHT_ALT_MODIFIER 0x0004 +#define EFI_ALT_GR_MODIFIER 0x0005 +#define EFI_INSERT_MODIFIER 0x0006 +#define EFI_DELETE_MODIFIER 0x0007 +#define EFI_PAGE_DOWN_MODIFIER 0x0008 +#define EFI_PAGE_UP_MODIFIER 0x0009 +#define EFI_HOME_MODIFIER 0x000A +#define EFI_END_MODIFIER 0x000B +#define EFI_LEFT_SHIFT_MODIFIER 0x000C +#define EFI_RIGHT_SHIFT_MODIFIER 0x000D +#define EFI_CAPS_LOCK_MODIFIER 0x000E +#define EFI_NUM_LOCK_MODIFIER 0x000F +#define EFI_LEFT_ARROW_MODIFIER 0x0010 +#define EFI_RIGHT_ARROW_MODIFIER 0x0011 +#define EFI_DOWN_ARROW_MODIFIER 0x0012 +#define EFI_UP_ARROW_MODIFIER 0x0013 +#define EFI_NS_KEY_MODIFIER 0x0014 +#define EFI_NS_KEY_DEPENDENCY_MODIFIER 0x0015 +#define EFI_FUNCTION_KEY_ONE_MODIFIER 0x0016 +#define EFI_FUNCTION_KEY_TWO_MODIFIER 0x0017 +#define EFI_FUNCTION_KEY_THREE_MODIFIER 0x0018 +#define EFI_FUNCTION_KEY_FOUR_MODIFIER 0x0019 +#define EFI_FUNCTION_KEY_FIVE_MODIFIER 0x001A +#define EFI_FUNCTION_KEY_SIX_MODIFIER 0x001B +#define EFI_FUNCTION_KEY_SEVEN_MODIFIER 0x001C +#define EFI_FUNCTION_KEY_EIGHT_MODIFIER 0x001D +#define EFI_FUNCTION_KEY_NINE_MODIFIER 0x001E +#define EFI_FUNCTION_KEY_TEN_MODIFIER 0x001F +#define EFI_FUNCTION_KEY_ELEVEN_MODIFIER 0x0020 +#define EFI_FUNCTION_KEY_TWELVE_MODIFIER 0x0021 + +// +// Keys that have multiple control functions based on modifier +// settings are handled in the keyboard driver implementation. +// For instance, PRINT_KEY might have a modifier held down and +// is still a nonprinting character, but might have an alternate +// control function like SYSREQUEST +// +#define EFI_PRINT_MODIFIER 0x0022 +#define EFI_SYS_REQUEST_MODIFIER 0x0023 +#define EFI_SCROLL_LOCK_MODIFIER 0x0024 +#define EFI_PAUSE_MODIFIER 0x0025 +#define EFI_BREAK_MODIFIER 0x0026 + +#define EFI_LEFT_LOGO_MODIFIER 0x0027 +#define EFI_RIGHT_LOGO_MODIFIER 0x0028 +#define EFI_MENU_MODIFIER 0x0029 + +/// +/// Animation IFR opcode +/// +typedef struct _EFI_IFR_ANIMATION { + /// + /// Standard opcode header, where Header.OpCode is + /// EFI_IFR_ANIMATION_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Animation identifier in the HII database. + /// + EFI_ANIMATION_ID Id; +} EFI_IFR_ANIMATION; + +/// +/// HII animation package header. +/// +typedef struct _EFI_HII_ANIMATION_PACKAGE_HDR { + /// + /// Standard package header, where Header.Type = EFI_HII_PACKAGE_ANIMATIONS. + /// + EFI_HII_PACKAGE_HEADER Header; + /// + /// Offset, relative to this header, of the animation information. If + /// this is zero, then there are no animation sequences in the package. + /// + UINT32 AnimationInfoOffset; +} EFI_HII_ANIMATION_PACKAGE_HDR; + +/// +/// Animation information is encoded as a series of blocks, +/// with each block prefixed by a single byte header EFI_HII_ANIMATION_BLOCK. +/// +typedef struct _EFI_HII_ANIMATION_BLOCK { + UINT8 BlockType; + //UINT8 BlockBody[]; +} EFI_HII_ANIMATION_BLOCK; + +/// +/// Animation block types. +/// +#define EFI_HII_AIBT_END 0x00 +#define EFI_HII_AIBT_OVERLAY_IMAGES 0x10 +#define EFI_HII_AIBT_CLEAR_IMAGES 0x11 +#define EFI_HII_AIBT_RESTORE_SCRN 0x12 +#define EFI_HII_AIBT_OVERLAY_IMAGES_LOOP 0x18 +#define EFI_HII_AIBT_CLEAR_IMAGES_LOOP 0x19 +#define EFI_HII_AIBT_RESTORE_SCRN_LOOP 0x1A +#define EFI_HII_AIBT_DUPLICATE 0x20 +#define EFI_HII_AIBT_SKIP2 0x21 +#define EFI_HII_AIBT_SKIP1 0x22 +#define EFI_HII_AIBT_EXT1 0x30 +#define EFI_HII_AIBT_EXT2 0x31 +#define EFI_HII_AIBT_EXT4 0x32 + +/// +/// Extended block headers used for variable sized animation records +/// which need an explicit length. +/// + +typedef struct _EFI_HII_AIBT_EXT1_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT1. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type. + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT8 Length; +} EFI_HII_AIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_AIBT_EXT2_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT2. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT16 Length; +} EFI_HII_AIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_AIBT_EXT4_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT4. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT32 Length; +} EFI_HII_AIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_ANIMATION_CELL { + /// + /// The X offset from the upper left hand corner of the logical + /// window to position the indexed image. + /// + UINT16 OffsetX; + /// + /// The Y offset from the upper left hand corner of the logical + /// window to position the indexed image. + /// + UINT16 OffsetY; + /// + /// The image to display at the specified offset from the upper left + /// hand corner of the logical window. + /// + EFI_IMAGE_ID ImageId; + /// + /// The number of milliseconds to delay after displaying the indexed + /// image and before continuing on to the next linked image. If value + /// is zero, no delay. + /// + UINT16 Delay; +} EFI_HII_ANIMATION_CELL; + +/// +/// An animation block to describe an animation sequence that does not cycle, and +/// where one image is simply displayed over the previous image. +/// +typedef struct _EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK; + +/// +/// An animation block to describe an animation sequence that does not cycle, +/// and where the logical window is cleared to the specified color before +/// the next image is displayed. +/// +typedef struct _EFI_HII_AIBT_CLEAR_IMAGES_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// The color to clear the logical window to before displaying the + /// indexed image. + /// + EFI_HII_RGB_PIXEL BackgndColor; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_CLEAR_IMAGES_BLOCK; + +/// +/// An animation block to describe an animation sequence that does not cycle, +/// and where the screen is restored to the original state before the next +/// image is displayed. +/// +typedef struct _EFI_HII_AIBT_RESTORE_SCRN_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_RESTORE_SCRN_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where one image is simply displayed over the previous image. +/// +typedef EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK EFI_HII_AIBT_OVERLAY_IMAGES_LOOP_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where the logical window is cleared to the specified color before +/// the next image is displayed. +/// +typedef EFI_HII_AIBT_CLEAR_IMAGES_BLOCK EFI_HII_AIBT_CLEAR_IMAGES_LOOP_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where the screen is restored to the original state before +/// the next image is displayed. +/// +typedef EFI_HII_AIBT_RESTORE_SCRN_BLOCK EFI_HII_AIBT_RESTORE_SCRN_LOOP_BLOCK; + +/// +/// Assigns a new character value to a previously defined animation sequence. +/// +typedef struct _EFI_HII_AIBT_DUPLICATE_BLOCK { + /// + /// The previously defined animation ID with the exact same + /// animation information. + /// + EFI_ANIMATION_ID AnimationId; +} EFI_HII_AIBT_DUPLICATE_BLOCK; + +/// +/// Skips animation IDs. +/// +typedef struct _EFI_HII_AIBT_SKIP1_BLOCK { + /// + /// The unsigned 8-bit value to add to AnimationIdCurrent. + /// + UINT8 SkipCount; +} EFI_HII_AIBT_SKIP1_BLOCK; + +/// +/// Skips animation IDs. +/// +typedef struct _EFI_HII_AIBT_SKIP2_BLOCK { + /// + /// The unsigned 16-bit value to add to AnimationIdCurrent. + /// + UINT16 SkipCount; +} EFI_HII_AIBT_SKIP2_BLOCK; + +#pragma pack() + + + +/// +/// References to string tokens must use this macro to enable scanning for +/// token usages. +/// +/// +/// STRING_TOKEN is not defined in UEFI specification. But it is placed +/// here for the easy access by C files and VFR source files. +/// +#define STRING_TOKEN(t) t + +#endif diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiMultiPhase.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiMultiPhase.h new file mode 100644 index 00000000..33c383ee --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiMultiPhase.h @@ -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.
+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 diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiPxe.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiPxe.h new file mode 100644 index 00000000..15faf100 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiPxe.h @@ -0,0 +1,1772 @@ +/** @file + This header file contains all of the PXE type definitions, + structure prototypes, global variables and constants that + are needed for porting PXE to EFI. + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+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. + + @par Revision Reference: + 32/64-bit PXE specification: + alpha-4, 99-Dec-17. + +**/ + +#ifndef __EFI_PXE_H__ +#define __EFI_PXE_H__ + +#pragma pack(1) + +#define PXE_BUSTYPE(a, b, c, d) \ + ( \ + (((PXE_UINT32) (d) & 0xFF) << 24) | (((PXE_UINT32) (c) & 0xFF) << 16) | (((PXE_UINT32) (b) & 0xFF) << 8) | \ + ((PXE_UINT32) (a) & 0xFF) \ + ) + +/// +/// UNDI ROM ID and devive ID signature. +/// +#define PXE_BUSTYPE_PXE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +/// +/// BUS ROM ID signatures. +/// +#define PXE_BUSTYPE_PCI PXE_BUSTYPE ('P', 'C', 'I', 'R') +#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE ('P', 'C', 'C', 'R') +#define PXE_BUSTYPE_USB PXE_BUSTYPE ('U', 'S', 'B', 'R') +#define PXE_BUSTYPE_1394 PXE_BUSTYPE ('1', '3', '9', '4') + +#define PXE_SWAP_UINT16(n) ((((PXE_UINT16) (n) & 0x00FF) << 8) | (((PXE_UINT16) (n) & 0xFF00) >> 8)) + +#define PXE_SWAP_UINT32(n) \ + ((((PXE_UINT32)(n) & 0x000000FF) << 24) | \ + (((PXE_UINT32)(n) & 0x0000FF00) << 8) | \ + (((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \ + (((PXE_UINT32)(n) & 0xFF000000) >> 24)) + +#define PXE_SWAP_UINT64(n) \ + ((((PXE_UINT64)(n) & 0x00000000000000FFULL) << 56) | \ + (((PXE_UINT64)(n) & 0x000000000000FF00ULL) << 40) | \ + (((PXE_UINT64)(n) & 0x0000000000FF0000ULL) << 24) | \ + (((PXE_UINT64)(n) & 0x00000000FF000000ULL) << 8) | \ + (((PXE_UINT64)(n) & 0x000000FF00000000ULL) >> 8) | \ + (((PXE_UINT64)(n) & 0x0000FF0000000000ULL) >> 24) | \ + (((PXE_UINT64)(n) & 0x00FF000000000000ULL) >> 40) | \ + (((PXE_UINT64)(n) & 0xFF00000000000000ULL) >> 56)) + + +#define PXE_CPBSIZE_NOT_USED 0 ///< zero +#define PXE_DBSIZE_NOT_USED 0 ///< zero +#define PXE_CPBADDR_NOT_USED (PXE_UINT64) 0 ///< zero +#define PXE_DBADDR_NOT_USED (PXE_UINT64) 0 ///< zero +#define PXE_CONST CONST + +#define PXE_VOLATILE volatile + +typedef VOID PXE_VOID; +typedef UINT8 PXE_UINT8; +typedef UINT16 PXE_UINT16; +typedef UINT32 PXE_UINT32; +typedef UINTN PXE_UINTN; + +/// +/// Typedef unsigned long PXE_UINT64. +/// +typedef UINT64 PXE_UINT64; + +typedef PXE_UINT8 PXE_BOOL; +#define PXE_FALSE 0 ///< zero +#define PXE_TRUE (!PXE_FALSE) + +typedef PXE_UINT16 PXE_OPCODE; + +/// +/// Return UNDI operational state. +/// +#define PXE_OPCODE_GET_STATE 0x0000 + +/// +/// Change UNDI operational state from Stopped to Started. +/// +#define PXE_OPCODE_START 0x0001 + +/// +/// Change UNDI operational state from Started to Stopped. +/// +#define PXE_OPCODE_STOP 0x0002 + +/// +/// Get UNDI initialization information. +/// +#define PXE_OPCODE_GET_INIT_INFO 0x0003 + +/// +/// Get NIC configuration information. +/// +#define PXE_OPCODE_GET_CONFIG_INFO 0x0004 + +/// +/// Changed UNDI operational state from Started to Initialized. +/// +#define PXE_OPCODE_INITIALIZE 0x0005 + +/// +/// Re-initialize the NIC H/W. +/// +#define PXE_OPCODE_RESET 0x0006 + +/// +/// Change the UNDI operational state from Initialized to Started. +/// +#define PXE_OPCODE_SHUTDOWN 0x0007 + +/// +/// Read & change state of external interrupt enables. +/// +#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008 + +/// +/// Read & change state of packet receive filters. +/// +#define PXE_OPCODE_RECEIVE_FILTERS 0x0009 + +/// +/// Read & change station MAC address. +/// +#define PXE_OPCODE_STATION_ADDRESS 0x000A + +/// +/// Read traffic statistics. +/// +#define PXE_OPCODE_STATISTICS 0x000B + +/// +/// Convert multicast IP address to multicast MAC address. +/// +#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C + +/// +/// Read or change non-volatile storage on the NIC. +/// +#define PXE_OPCODE_NVDATA 0x000D + +/// +/// Get & clear interrupt status. +/// +#define PXE_OPCODE_GET_STATUS 0x000E + +/// +/// Fill media header in packet for transmit. +/// +#define PXE_OPCODE_FILL_HEADER 0x000F + +/// +/// Transmit packet(s). +/// +#define PXE_OPCODE_TRANSMIT 0x0010 + +/// +/// Receive packet. +/// +#define PXE_OPCODE_RECEIVE 0x0011 + +/// +/// Last valid PXE UNDI OpCode number. +/// +#define PXE_OPCODE_LAST_VALID 0x0011 + +typedef PXE_UINT16 PXE_OPFLAGS; + +#define PXE_OPFLAGS_NOT_USED 0x0000 + +// +// ////////////////////////////////////// +// UNDI Get State +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Start +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Stop +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// +// No Opflags + +//////////////////////////////////////// +// UNDI Get Config Info +// +// No Opflags + +/// +/// UNDI Initialize +/// +#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001 +#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000 +#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001 + +/// +/// +/// UNDI Reset +/// +#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001 +#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002 + +/// +/// UNDI Shutdown. +/// +/// No OpFlags. + +/// +/// UNDI Interrupt Enables. +/// +/// +/// Select whether to enable or disable external interrupt signals. +/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS. +/// +#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000 +#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000 +#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000 +#define PXE_OPFLAGS_INTERRUPT_READ 0x0000 + +/// +/// Enable receive interrupts. An external interrupt will be generated +/// after a complete non-error packet has been received. +/// +#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001 + +/// +/// Enable transmit interrupts. An external interrupt will be generated +/// after a complete non-error packet has been transmitted. +/// +#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002 + +/// +/// Enable command interrupts. An external interrupt will be generated +/// when command execution stops. +/// +#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004 + +/// +/// Generate software interrupt. Setting this bit generates an external +/// interrupt, if it is supported by the hardware. +/// +#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008 + +/// +/// UNDI Receive Filters. +/// +/// +/// Select whether to enable or disable receive filters. +/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000 +#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000 +#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000 +#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000 + +/// +/// To reset the contents of the multicast MAC address filter list, +/// set this OpFlag: +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000 + +/// +/// Enable unicast packet receiving. Packets sent to the current station +/// MAC address will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +/// +/// Enable broadcast packet receiving. Packets sent to the broadcast +/// MAC address will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +/// +/// Enable filtered multicast packet receiving. Packets sent to any +/// of the multicast MAC addresses in the multicast MAC address filter +/// list will be received. If the filter list is empty, no multicast +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +/// +/// Enable promiscuous packet receiving. All packets will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +/// +/// Enable promiscuous multicast packet receiving. All multicast +/// packets will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +/// +/// UNDI Station Address. +/// +#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_WRITE 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001 + +/// +/// UNDI Statistics. +/// +#define PXE_OPFLAGS_STATISTICS_READ 0x0000 +#define PXE_OPFLAGS_STATISTICS_RESET 0x0001 + +/// +/// UNDI MCast IP to MAC. +/// +/// +/// Identify the type of IP address in the CPB. +/// +#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003 +#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000 +#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001 + +/// +/// UNDI NvData. +/// +/// +/// Select the type of non-volatile data operation. +/// +#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001 +#define PXE_OPFLAGS_NVDATA_READ 0x0000 +#define PXE_OPFLAGS_NVDATA_WRITE 0x0001 + +/// +/// UNDI Get Status. +/// +/// +/// Return current interrupt status. This will also clear any interrupts +/// that are currently set. This can be used in a polling routine. The +/// interrupt flags are still set and cleared even when the interrupts +/// are disabled. +/// +#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001 + +/// +/// Return list of transmitted buffers for recycling. Transmit buffers +/// must not be changed or unallocated until they have recycled. After +/// issuing a transmit command, wait for a transmit complete interrupt. +/// When a transmit complete interrupt is received, read the transmitted +/// buffers. Do not plan on getting one buffer per interrupt. Some +/// NICs and UNDIs may transmit multiple buffers per interrupt. +/// +#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002 + +/// +/// Return current media status. +/// +#define PXE_OPFLAGS_GET_MEDIA_STATUS 0x0004 + +/// +/// UNDI Fill Header. +/// +#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000 + +/// +/// UNDI Transmit. +/// +/// +/// S/W UNDI only. Return after the packet has been transmitted. A +/// transmit complete interrupt will still be generated and the transmit +/// buffer will have to be recycled. +/// +#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000 + +#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002 +#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002 +#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000 + +/// +/// UNDI Receive. +/// +/// No OpFlags. +/// + +/// +/// PXE STATFLAGS. +/// +typedef PXE_UINT16 PXE_STATFLAGS; + +#define PXE_STATFLAGS_INITIALIZE 0x0000 + +/// +/// Common StatFlags that can be returned by all commands. +/// +/// +/// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be +/// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs +/// that support command queuing. +/// +#define PXE_STATFLAGS_STATUS_MASK 0xC000 +#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000 +#define PXE_STATFLAGS_COMMAND_FAILED 0x8000 +#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000 + +/// +/// UNDI Get State. +/// +#define PXE_STATFLAGS_GET_STATE_MASK 0x0003 +#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002 +#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001 +#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000 + +/// +/// UNDI Start. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Get Init Info. +/// +#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001 +#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001 + +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK 0x0002 +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED 0x0002 + +/// +/// UNDI Initialize. +/// +#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001 + +/// +/// UNDI Reset. +/// +#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001 + +/// +/// UNDI Shutdown. +/// +/// No additional StatFlags. + +/// +/// UNDI Interrupt Enables. +/// +/// +/// If set, receive interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001 + +/// +/// If set, transmit interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002 + +/// +/// If set, command interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004 + +/// +/// UNDI Receive Filters. +/// + +/// +/// If set, unicast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +/// +/// If set, broadcast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +/// +/// If set, multicast packets that match up with the multicast address +/// filter list will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +/// +/// If set, all packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +/// +/// If set, all multicast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +/// +/// UNDI Station Address. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Statistics. +/// +/// No additional StatFlags. +/// + +/// +//// UNDI MCast IP to MAC. +//// +//// No additional StatFlags. + +/// +/// UNDI NvData. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Get Status. +/// + +/// +/// Use to determine if an interrupt has occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F +#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000 + +/// +/// If set, at least one receive interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001 + +/// +/// If set, at least one transmit interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002 + +/// +/// If set, at least one command interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004 + +/// +/// If set, at least one software interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008 + +/// +/// This flag is set if the transmitted buffer queue is empty. This flag +/// will be set if all transmitted buffer addresses get written into the DB. +/// +#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010 + +/// +/// This flag is set if no transmitted buffer addresses were written +/// into the DB. (This could be because DBsize was too small.) +/// +#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020 + +/// +/// This flag is set if there is no media detected. +/// +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA 0x0040 + +/// +/// UNDI Fill Header. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Transmit. +/// +/// No additional StatFlags. + +/// +/// UNDI Receive +///. + +/// +/// No additional StatFlags. +/// +typedef PXE_UINT16 PXE_STATCODE; + +#define PXE_STATCODE_INITIALIZE 0x0000 + +/// +/// Common StatCodes returned by all UNDI commands, UNDI protocol functions +/// and BC protocol functions. +/// +#define PXE_STATCODE_SUCCESS 0x0000 + +#define PXE_STATCODE_INVALID_CDB 0x0001 +#define PXE_STATCODE_INVALID_CPB 0x0002 +#define PXE_STATCODE_BUSY 0x0003 +#define PXE_STATCODE_QUEUE_FULL 0x0004 +#define PXE_STATCODE_ALREADY_STARTED 0x0005 +#define PXE_STATCODE_NOT_STARTED 0x0006 +#define PXE_STATCODE_NOT_SHUTDOWN 0x0007 +#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008 +#define PXE_STATCODE_NOT_INITIALIZED 0x0009 +#define PXE_STATCODE_DEVICE_FAILURE 0x000A +#define PXE_STATCODE_NVDATA_FAILURE 0x000B +#define PXE_STATCODE_UNSUPPORTED 0x000C +#define PXE_STATCODE_BUFFER_FULL 0x000D +#define PXE_STATCODE_INVALID_PARAMETER 0x000E +#define PXE_STATCODE_INVALID_UNDI 0x000F +#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010 +#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011 +#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012 +#define PXE_STATCODE_NO_DATA 0x0013 + +typedef PXE_UINT16 PXE_IFNUM; + +/// +/// This interface number must be passed to the S/W UNDI Start command. +/// +#define PXE_IFNUM_START 0x0000 + +/// +/// This interface number is returned by the S/W UNDI Get State and +/// Start commands if information in the CDB, CPB or DB is invalid. +/// +#define PXE_IFNUM_INVALID 0x0000 + +typedef PXE_UINT16 PXE_CONTROL; + +/// +/// Setting this flag directs the UNDI to queue this command for later +/// execution if the UNDI is busy and it supports command queuing. +/// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error +/// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL +/// error is returned. +/// +#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002 + +/// +/// These two bit values are used to determine if there are more UNDI +/// CDB structures following this one. If the link bit is set, there +/// must be a CDB structure following this one. Execution will start +/// on the next CDB structure as soon as this one completes successfully. +/// If an error is generated by this command, execution will stop. +/// +#define PXE_CONTROL_LINK 0x0001 +#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000 + +typedef PXE_UINT8 PXE_FRAME_TYPE; + +#define PXE_FRAME_TYPE_NONE 0x00 +#define PXE_FRAME_TYPE_UNICAST 0x01 +#define PXE_FRAME_TYPE_BROADCAST 0x02 +#define PXE_FRAME_TYPE_FILTERED_MULTICAST 0x03 +#define PXE_FRAME_TYPE_PROMISCUOUS 0x04 +#define PXE_FRAME_TYPE_PROMISCUOUS_MULTICAST 0x05 + +#define PXE_FRAME_TYPE_MULTICAST PXE_FRAME_TYPE_FILTERED_MULTICAST + +typedef PXE_UINT32 PXE_IPV4; + +typedef PXE_UINT32 PXE_IPV6[4]; +#define PXE_MAC_LENGTH 32 + +typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH]; + +typedef PXE_UINT8 PXE_IFTYPE; +typedef UINT16 PXE_MEDIA_PROTOCOL; + +/// +/// This information is from the ARP section of RFC 1700. +/// +/// 1 Ethernet (10Mb) [JBP] +/// 2 Experimental Ethernet (3Mb) [JBP] +/// 3 Amateur Radio AX.25 [PXK] +/// 4 Proteon ProNET Token Ring [JBP] +/// 5 Chaos [GXP] +/// 6 IEEE 802 Networks [JBP] +/// 7 ARCNET [JBP] +/// 8 Hyperchannel [JBP] +/// 9 Lanstar [TU] +/// 10 Autonet Short Address [MXB1] +/// 11 LocalTalk [JKR1] +/// 12 LocalNet (IBM* PCNet or SYTEK* LocalNET) [JXM] +/// 13 Ultra link [RXD2] +/// 14 SMDS [GXC1] +/// 15 Frame Relay [AGM] +/// 16 Asynchronous Transmission Mode (ATM) [JXB2] +/// 17 HDLC [JBP] +/// 18 Fibre Channel [Yakov Rekhter] +/// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach] +/// 20 Serial Line [JBP] +/// 21 Asynchronous Transmission Mode (ATM) [MXB1] +/// +/// * Other names and brands may be claimed as the property of others. +/// +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +typedef struct s_pxe_hw_undi { + PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE. + PXE_UINT8 Len; ///< sizeof(PXE_HW_UNDI). + PXE_UINT8 Fudge; ///< makes 8-bit cksum equal zero. + PXE_UINT8 Rev; ///< PXE_ROMID_REV. + PXE_UINT8 IFcnt; ///< physical connector count lower byte. + PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER. + PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER. + PXE_UINT8 IFcntExt; ///< physical connector count upper byte. + PXE_UINT8 reserved; ///< zero, not used. + PXE_UINT32 Implementation; ///< implementation flags. + ///< reserved ///< vendor use. + ///< UINT32 Status; ///< status port. + ///< UINT32 Command; ///< command port. + ///< UINT64 CDBaddr; ///< CDB address port. + ///< +} PXE_HW_UNDI; + +/// +/// Status port bit definitions. +/// + +/// +/// UNDI operation state. +/// +#define PXE_HWSTAT_STATE_MASK 0xC0000000 +#define PXE_HWSTAT_BUSY 0xC0000000 +#define PXE_HWSTAT_INITIALIZED 0x80000000 +#define PXE_HWSTAT_STARTED 0x40000000 +#define PXE_HWSTAT_STOPPED 0x00000000 + +/// +/// If set, last command failed. +/// +#define PXE_HWSTAT_COMMAND_FAILED 0x20000000 + +/// +/// If set, identifies enabled receive filters. +/// +#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000 +#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800 +#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400 +#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200 +#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100 + +/// +/// If set, identifies enabled external interrupts. +/// +#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080 +#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040 +#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020 +#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010 + +/// +/// If set, identifies pending interrupts. +/// +#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008 +#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004 +#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002 +#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001 + +/// +/// Command port definitions. +/// + +/// +/// If set, CDB identified in CDBaddr port is given to UNDI. +/// If not set, other bits in this word will be processed. +/// +#define PXE_HWCMD_ISSUE_COMMAND 0x80000000 +#define PXE_HWCMD_INTS_AND_FILTS 0x00000000 + +/// +/// Use these to enable/disable receive filters. +/// +#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000 +#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800 +#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400 +#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200 +#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100 + +/// +/// Use these to enable/disable external interrupts. +/// +#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080 +#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040 +#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020 +#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010 + +/// +/// Use these to clear pending external interrupts. +/// +#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008 +#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004 +#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002 +#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001 + +typedef struct s_pxe_sw_undi { + PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE. + PXE_UINT8 Len; ///< sizeof(PXE_SW_UNDI). + PXE_UINT8 Fudge; ///< makes 8-bit cksum zero. + PXE_UINT8 Rev; ///< PXE_ROMID_REV. + PXE_UINT8 IFcnt; ///< physical connector count lower byte. + PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER. + PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER. + PXE_UINT8 IFcntExt; ///< physical connector count upper byte. + PXE_UINT8 reserved1; ///< zero, not used. + PXE_UINT32 Implementation; ///< Implementation flags. + PXE_UINT64 EntryPoint; ///< API entry point. + PXE_UINT8 reserved2[3]; ///< zero, not used. + PXE_UINT8 BusCnt; ///< number of bustypes supported. + PXE_UINT32 BusType[1]; ///< list of supported bustypes. +} PXE_SW_UNDI; + +typedef union u_pxe_undi { + PXE_HW_UNDI hw; + PXE_SW_UNDI sw; +} PXE_UNDI; + +/// +/// Signature of !PXE structure. +/// +#define PXE_ROMID_SIGNATURE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +/// +/// !PXE structure format revision +///. +#define PXE_ROMID_REV 0x02 + +/// +/// UNDI command interface revision. These are the values that get sent +/// in option 94 (Client Network Interface Identifier) in the DHCP Discover +/// and PXE Boot Server Request packets. +/// +#define PXE_ROMID_MAJORVER 0x03 +#define PXE_ROMID_MINORVER 0x01 + +/// +/// Implementation flags. +/// +#define PXE_ROMID_IMP_HW_UNDI 0x80000000 +#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000 +#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000 +#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000 +#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000 +#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000 +#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000 +#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800 +#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400 +#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000 +#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200 +#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100 +#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080 +#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040 +#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020 +#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010 +#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008 +#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004 +#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002 +#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001 + +typedef struct s_pxe_cdb { + PXE_OPCODE OpCode; + PXE_OPFLAGS OpFlags; + PXE_UINT16 CPBsize; + PXE_UINT16 DBsize; + PXE_UINT64 CPBaddr; + PXE_UINT64 DBaddr; + PXE_STATCODE StatCode; + PXE_STATFLAGS StatFlags; + PXE_UINT16 IFnum; + PXE_CONTROL Control; +} PXE_CDB; + +typedef union u_pxe_ip_addr { + PXE_IPV6 IPv6; + PXE_IPV4 IPv4; +} PXE_IP_ADDR; + +typedef union pxe_device { + /// + /// PCI and PC Card NICs are both identified using bus, device + /// and function numbers. For PC Card, this may require PC + /// Card services to be loaded in the BIOS or preboot + /// environment. + /// + struct { + /// + /// See S/W UNDI ROMID structure definition for PCI and + /// PCC BusType definitions. + /// + PXE_UINT32 BusType; + + /// + /// Bus, device & function numbers that locate this device. + /// + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + } + PCI, PCC; + +} PXE_DEVICE; + +/// +/// cpb and db definitions +/// +#define MAX_PCI_CONFIG_LEN 64 ///< # of dwords. +#define MAX_EEPROM_LEN 128 ///< # of dwords. +#define MAX_XMIT_BUFFERS 32 ///< recycling Q length for xmit_done. +#define MAX_MCAST_ADDRESS_CNT 8 + +typedef struct s_pxe_cpb_start_30 { + /// + /// PXE_VOID Delay(UINTN microseconds); + /// + /// UNDI will never request a delay smaller than 10 microseconds + /// and will always request delays in increments of 10 microseconds. + /// The Delay() CallBack routine must delay between n and n + 10 + /// microseconds before returning control to the UNDI. + /// + /// This field cannot be set to zero. + /// + UINT64 Delay; + + /// + /// PXE_VOID Block(UINT32 enable); + /// + /// UNDI may need to block multi-threaded/multi-processor access to + /// critical code sections when programming or accessing the network + /// device. To this end, a blocking service is needed by the UNDI. + /// When UNDI needs a block, it will call Block() passing a non-zero + /// value. When UNDI no longer needs a block, it will call Block() + /// with a zero value. When called, if the Block() is already enabled, + /// do not return control to the UNDI until the previous Block() is + /// disabled. + /// + /// This field cannot be set to zero. + /// + UINT64 Block; + + /// + /// PXE_VOID Virt2Phys(UINT64 virtual, UINT64 physical_ptr); + /// + /// UNDI will pass the virtual address of a buffer and the virtual + /// address of a 64-bit physical buffer. Convert the virtual address + /// to a physical address and write the result to the physical address + /// buffer. If virtual and physical addresses are the same, just + /// copy the virtual address to the physical address buffer. + /// + /// This field can be set to zero if virtual and physical addresses + /// are equal. + /// + UINT64 Virt2Phys; + /// + /// PXE_VOID Mem_IO(UINT8 read_write, UINT8 len, UINT64 port, + /// UINT64 buf_addr); + /// + /// UNDI will read or write the device io space using this call back + /// function. It passes the number of bytes as the len parameter and it + /// will be either 1,2,4 or 8. + /// + /// This field can not be set to zero. + /// + UINT64 Mem_IO; +} PXE_CPB_START_30; + +typedef struct s_pxe_cpb_start_31 { + /// + /// PXE_VOID Delay(UINT64 UnqId, UINTN microseconds); + /// + /// UNDI will never request a delay smaller than 10 microseconds + /// and will always request delays in increments of 10 microseconds. + /// The Delay() CallBack routine must delay between n and n + 10 + /// microseconds before returning control to the UNDI. + /// + /// This field cannot be set to zero. + /// + UINT64 Delay; + + /// + /// PXE_VOID Block(UINT64 unq_id, UINT32 enable); + /// + /// UNDI may need to block multi-threaded/multi-processor access to + /// critical code sections when programming or accessing the network + /// device. To this end, a blocking service is needed by the UNDI. + /// When UNDI needs a block, it will call Block() passing a non-zero + /// value. When UNDI no longer needs a block, it will call Block() + /// with a zero value. When called, if the Block() is already enabled, + /// do not return control to the UNDI until the previous Block() is + /// disabled. + /// + /// This field cannot be set to zero. + /// + UINT64 Block; + + /// + /// PXE_VOID Virt2Phys(UINT64 UnqId, UINT64 virtual, UINT64 physical_ptr); + /// + /// UNDI will pass the virtual address of a buffer and the virtual + /// address of a 64-bit physical buffer. Convert the virtual address + /// to a physical address and write the result to the physical address + /// buffer. If virtual and physical addresses are the same, just + /// copy the virtual address to the physical address buffer. + /// + /// This field can be set to zero if virtual and physical addresses + /// are equal. + /// + UINT64 Virt2Phys; + /// + /// PXE_VOID Mem_IO(UINT64 UnqId, UINT8 read_write, UINT8 len, UINT64 port, + /// UINT64 buf_addr); + /// + /// UNDI will read or write the device io space using this call back + /// function. It passes the number of bytes as the len parameter and it + /// will be either 1,2,4 or 8. + /// + /// This field can not be set to zero. + /// + UINT64 Mem_IO; + /// + /// PXE_VOID Map_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + /// UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual address of a buffer, direction of the data + /// flow from/to the mapped buffer (the constants are defined below) + /// and a place holder (pointer) for the mapped address. + /// This call will Map the given address to a physical DMA address and write + /// the result to the mapped_addr pointer. If there is no need to + /// map the given address to a lower address (i.e. the given address is + /// associated with a physical address that is already compatible to be + /// used with the DMA, it converts the given virtual address to it's + /// physical address and write that in the mapped address pointer. + /// + /// This field can be set to zero if there is no mapping service available. + /// + UINT64 Map_Mem; + + /// + /// PXE_VOID UnMap_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + /// UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual and mapped addresses of a buffer. + /// This call will un map the given address. + /// + /// This field can be set to zero if there is no unmapping service available. + /// + UINT64 UnMap_Mem; + + /// + /// PXE_VOID Sync_Mem(UINT64 unq_id, UINT64 virtual, + /// UINT32 size, UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual and mapped addresses of a buffer. + /// This call will synchronize the contents of both the virtual and mapped. + /// buffers for the given Direction. + /// + /// This field can be set to zero if there is no service available. + /// + UINT64 Sync_Mem; + + /// + /// protocol driver can provide anything for this Unique_ID, UNDI remembers + /// that as just a 64bit value assocaited to the interface specified by + /// the ifnum and gives it back as a parameter to all the call-back routines + /// when calling for that interface! + /// + UINT64 Unique_ID; +} PXE_CPB_START_31; + +#define TO_AND_FROM_DEVICE 0 +#define FROM_DEVICE 1 +#define TO_DEVICE 2 + +#define PXE_DELAY_MILLISECOND 1000 +#define PXE_DELAY_SECOND 1000000 +#define PXE_IO_READ 0 +#define PXE_IO_WRITE 1 +#define PXE_MEM_READ 2 +#define PXE_MEM_WRITE 4 + +typedef struct s_pxe_db_get_init_info { + /// + /// Minimum length of locked memory buffer that must be given to + /// the Initialize command. Giving UNDI more memory will generally + /// give better performance. + /// + /// If MemoryRequired is zero, the UNDI does not need and will not + /// use system memory to receive and transmit packets. + /// + PXE_UINT32 MemoryRequired; + + /// + /// Maximum frame data length for Tx/Rx excluding the media header. + /// + PXE_UINT32 FrameDataLen; + + /// + /// Supported link speeds are in units of mega bits. Common ethernet + /// values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero + /// filled. + /// + PXE_UINT32 LinkSpeeds[4]; + + /// + /// Number of non-volatile storage items. + /// + PXE_UINT32 NvCount; + + /// + /// Width of non-volatile storage item in bytes. 0, 1, 2 or 4 + /// + PXE_UINT16 NvWidth; + + /// + /// Media header length. This is the typical media header length for + /// this UNDI. This information is needed when allocating receive + /// and transmit buffers. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Number of bytes in the NIC hardware (MAC) address. + /// + PXE_UINT16 HWaddrLen; + + /// + /// Maximum number of multicast MAC addresses in the multicast + /// MAC address filter list. + /// + PXE_UINT16 MCastFilterCnt; + + /// + /// Default number and size of transmit and receive buffers that will + /// be allocated by the UNDI. If MemoryRequired is non-zero, this + /// allocation will come out of the memory buffer given to the Initialize + /// command. If MemoryRequired is zero, this allocation will come out of + /// memory on the NIC. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + /// + /// Hardware interface types defined in the Assigned Numbers RFC + /// and used in DHCP and ARP packets. + /// See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros. + /// + PXE_UINT8 IFtype; + + /// + /// Supported duplex. See PXE_DUPLEX_xxxxx #defines below. + /// + PXE_UINT8 SupportedDuplexModes; + + /// + /// Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below. + /// + PXE_UINT8 SupportedLoopBackModes; +} PXE_DB_GET_INIT_INFO; + +#define PXE_MAX_TXRX_UNIT_ETHER 1500 + +#define PXE_HWADDR_LEN_ETHER 0x0006 +#define PXE_MAC_HEADER_LEN_ETHER 0x000E + +#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1 +#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2 + +#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1 +#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2 + +typedef struct s_pxe_pci_config_info { + /// + /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + /// For PCI bus devices, this field is set to PXE_BUSTYPE_PCI. + /// + UINT32 BusType; + + /// + /// This identifies the PCI network device that this UNDI interface. + /// is bound to. + /// + UINT16 Bus; + UINT8 Device; + UINT8 Function; + + /// + /// This is a copy of the PCI configuration space for this + /// network device. + /// + union { + UINT8 Byte[256]; + UINT16 Word[128]; + UINT32 Dword[64]; + } Config; +} PXE_PCI_CONFIG_INFO; + +typedef struct s_pxe_pcc_config_info { + /// + /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + /// For PCC bus devices, this field is set to PXE_BUSTYPE_PCC. + /// + PXE_UINT32 BusType; + + /// + /// This identifies the PCC network device that this UNDI interface + /// is bound to. + /// + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + /// + /// This is a copy of the PCC configuration space for this + /// network device. + /// + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCC_CONFIG_INFO; + +typedef union u_pxe_db_get_config_info { + PXE_PCI_CONFIG_INFO pci; + PXE_PCC_CONFIG_INFO pcc; +} PXE_DB_GET_CONFIG_INFO; + +typedef struct s_pxe_cpb_initialize { + /// + /// Address of first (lowest) byte of the memory buffer. This buffer must + /// be in contiguous physical memory and cannot be swapped out. The UNDI + /// will be using this for transmit and receive buffering. + /// + PXE_UINT64 MemoryAddr; + + /// + /// MemoryLength must be greater than or equal to MemoryRequired + /// returned by the Get Init Info command. + /// + PXE_UINT32 MemoryLength; + + /// + /// Desired link speed in Mbit/sec. Common ethernet values are 10, 100 + /// and 1000. Setting a value of zero will auto-detect and/or use the + /// default link speed (operation depends on UNDI/NIC functionality). + /// + PXE_UINT32 LinkSpeed; + + /// + /// Suggested number and size of receive and transmit buffers to + /// allocate. If MemoryAddr and MemoryLength are non-zero, this + /// allocation comes out of the supplied memory buffer. If MemoryAddr + /// and MemoryLength are zero, this allocation comes out of memory + /// on the NIC. + /// + /// If these fields are set to zero, the UNDI will allocate buffer + /// counts and sizes as it sees fit. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + /// + /// The following configuration parameters are optional and must be zero + /// to use the default values. + /// + PXE_UINT8 DuplexMode; + + PXE_UINT8 LoopBackMode; +} PXE_CPB_INITIALIZE; + +#define PXE_DUPLEX_DEFAULT 0x00 +#define PXE_FORCE_FULL_DUPLEX 0x01 +#define PXE_ENABLE_FULL_DUPLEX 0x02 +#define PXE_FORCE_HALF_DUPLEX 0x04 +#define PXE_DISABLE_FULL_DUPLEX 0x08 + +#define LOOPBACK_NORMAL 0 +#define LOOPBACK_INTERNAL 1 +#define LOOPBACK_EXTERNAL 2 + +typedef struct s_pxe_db_initialize { + /// + /// Actual amount of memory used from the supplied memory buffer. This + /// may be less that the amount of memory suppllied and may be zero if + /// the UNDI and network device do not use external memory buffers. + /// + /// Memory used by the UNDI and network device is allocated from the + /// lowest memory buffer address. + /// + PXE_UINT32 MemoryUsed; + + /// + /// Actual number and size of receive and transmit buffers that were + /// allocated. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; +} PXE_DB_INITIALIZE; + +typedef struct s_pxe_cpb_receive_filters { + /// + /// List of multicast MAC addresses. This list, if present, will + /// replace the existing multicast MAC address filter list. + /// + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_CPB_RECEIVE_FILTERS; + +typedef struct s_pxe_db_receive_filters { + /// + /// Filtered multicast MAC address list. + /// + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_DB_RECEIVE_FILTERS; + +typedef struct s_pxe_cpb_station_address { + /// + /// If supplied and supported, the current station MAC address + /// will be changed. + /// + PXE_MAC_ADDR StationAddr; +} PXE_CPB_STATION_ADDRESS; + +typedef struct s_pxe_dpb_station_address { + /// + /// Current station MAC address. + /// + PXE_MAC_ADDR StationAddr; + + /// + /// Station broadcast MAC address. + /// + PXE_MAC_ADDR BroadcastAddr; + + /// + /// Permanent station MAC address. + /// + PXE_MAC_ADDR PermanentAddr; +} PXE_DB_STATION_ADDRESS; + +typedef struct s_pxe_db_statistics { + /// + /// Bit field identifying what statistic data is collected by the + /// UNDI/NIC. + /// If bit 0x00 is set, Data[0x00] is collected. + /// If bit 0x01 is set, Data[0x01] is collected. + /// If bit 0x20 is set, Data[0x20] is collected. + /// If bit 0x21 is set, Data[0x21] is collected. + /// Etc. + /// + PXE_UINT64 Supported; + + /// + /// Statistic data. + /// + PXE_UINT64 Data[64]; +} PXE_DB_STATISTICS; + +/// +/// Total number of frames received. Includes frames with errors and +/// dropped frames. +/// +#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00 + +/// +/// Number of valid frames received and copied into receive buffers. +/// +#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01 + +/// +/// Number of frames below the minimum length for the media. +/// This would be <64 for ethernet. +/// +#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02 + +/// +/// Number of frames longer than the maxminum length for the +/// media. This would be >1500 for ethernet. +/// +#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03 + +/// +/// Valid frames that were dropped because receive buffers were full. +/// +#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04 + +/// +/// Number of valid unicast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05 + +/// +/// Number of valid broadcast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06 + +/// +/// Number of valid mutlicast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07 + +/// +/// Number of frames w/ CRC or alignment errors. +/// +#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08 + +/// +/// Total number of bytes received. Includes frames with errors +/// and dropped frames. +/// +#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09 + +/// +/// Transmit statistics. +/// +#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A +#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B +#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C +#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D +#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E +#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F +#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10 +#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11 +#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12 +#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13 + +/// +/// Number of collisions detection on this subnet. +/// +#define PXE_STATISTICS_COLLISIONS 0x14 + +/// +/// Number of frames destined for unsupported protocol. +/// +#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15 + +typedef struct s_pxe_cpb_mcast_ip_to_mac { + /// + /// Multicast IP address to be converted to multicast MAC address. + /// + PXE_IP_ADDR IP; +} PXE_CPB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_db_mcast_ip_to_mac { + /// + /// Multicast MAC address. + /// + PXE_MAC_ADDR MAC; +} PXE_DB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_cpb_nvdata_sparse { + /// + /// NvData item list. Only items in this list will be updated. + /// + struct { + /// + /// Non-volatile storage address to be changed. + /// + PXE_UINT32 Addr; + + /// + /// Data item to write into above storage address. + /// + union { + PXE_UINT8 Byte; + PXE_UINT16 Word; + PXE_UINT32 Dword; + } Data; + } Item[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_SPARSE; + +/// +/// When using bulk update, the size of the CPB structure must be +/// the same size as the non-volatile NIC storage. +/// +typedef union u_pxe_cpb_nvdata_bulk { + /// + /// Array of byte-wide data items. + /// + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + /// + /// Array of word-wide data items. + /// + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + /// + /// Array of dword-wide data items. + /// + PXE_UINT32 Dword[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_BULK; + +typedef struct s_pxe_db_nvdata { + /// + /// Arrays of data items from non-volatile storage. + /// + union { + /// + /// Array of byte-wide data items. + /// + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + /// + /// Array of word-wide data items. + /// + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + /// + /// Array of dword-wide data items. + /// + PXE_UINT32 Dword[MAX_EEPROM_LEN]; + } Data; +} PXE_DB_NVDATA; + +typedef struct s_pxe_db_get_status { + /// + /// Length of next receive frame (header + data). If this is zero, + /// there is no next receive frame available. + /// + PXE_UINT32 RxFrameLen; + + /// + /// Reserved, set to zero. + /// + PXE_UINT32 reserved; + + /// + /// Addresses of transmitted buffers that need to be recycled. + /// + PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS]; +} PXE_DB_GET_STATUS; + +typedef struct s_pxe_cpb_fill_header { + /// + /// Source and destination MAC addresses. These will be copied into + /// the media header without doing byte swapping. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Address of first byte of media header. The first byte of packet data + /// follows the last byte of the media header. + /// + PXE_UINT64 MediaHeader; + + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 PacketLen; + + /// + /// Protocol type. This will be copied into the media header without + /// doing byte swapping. Protocol type numbers can be obtained from + /// the Assigned Numbers RFC 1700. + /// + PXE_UINT16 Protocol; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaHeaderLen; +} PXE_CPB_FILL_HEADER; + +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define MAX_XMIT_FRAGMENTS 16 + +typedef struct s_pxe_cpb_fill_header_fragmented { + /// + /// Source and destination MAC addresses. These will be copied into + /// the media header without doing byte swapping. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 PacketLen; + + /// + /// Protocol type. This will be copied into the media header without + /// doing byte swapping. Protocol type numbers can be obtained from + /// the Assigned Numbers RFC 1700. + /// + PXE_MEDIA_PROTOCOL Protocol; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Number of packet fragment descriptors. + /// + PXE_UINT16 FragCnt; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT16 reserved; + + /// + /// Array of packet fragment descriptors. The first byte of the media + /// header is the first byte of the first fragment. + /// + struct { + /// + /// Address of this packet fragment. + /// + PXE_UINT64 FragAddr; + + /// + /// Length of this packet fragment. + /// + PXE_UINT32 FragLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_FILL_HEADER_FRAGMENTED; + +typedef struct s_pxe_cpb_transmit { + /// + /// Address of first byte of frame buffer. This is also the first byte + /// of the media header. + /// + PXE_UINT64 FrameAddr; + + /// + /// Length of the data portion of the frame buffer in bytes. Do not + /// include the length of the media header. + /// + PXE_UINT32 DataLen; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaheaderLen; + + /// + /// Reserved, must be zero. + /// + PXE_UINT16 reserved; +} PXE_CPB_TRANSMIT; + +typedef struct s_pxe_cpb_transmit_fragments { + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 FrameLen; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaheaderLen; + + /// + /// Number of packet fragment descriptors. + /// + PXE_UINT16 FragCnt; + + /// + /// Array of frame fragment descriptors. The first byte of the first + /// fragment is also the first byte of the media header. + /// + struct { + /// + /// Address of this frame fragment. + /// + PXE_UINT64 FragAddr; + + /// + /// Length of this frame fragment. + /// + PXE_UINT32 FragLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_TRANSMIT_FRAGMENTS; + +typedef struct s_pxe_cpb_receive { + /// + /// Address of first byte of receive buffer. This is also the first byte + /// of the frame header. + /// + PXE_UINT64 BufferAddr; + + /// + /// Length of receive buffer. This must be large enough to hold the + /// received frame (media header + data). If the length of smaller than + /// the received frame, data will be lost. + /// + PXE_UINT32 BufferLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; +} PXE_CPB_RECEIVE; + +typedef struct s_pxe_db_receive { + /// + /// Source and destination MAC addresses from media header. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Length of received frame. May be larger than receive buffer size. + /// The receive buffer will not be overwritten. This is how to tell + /// if data was lost because the receive buffer was too small. + /// + PXE_UINT32 FrameLen; + + /// + /// Protocol type from media header. + /// + PXE_MEDIA_PROTOCOL Protocol; + + /// + /// Length of media header in received frame. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Type of receive frame. + /// + PXE_FRAME_TYPE Type; + + /// + /// Reserved, must be zero. + /// + PXE_UINT8 reserved[7]; + +} PXE_DB_RECEIVE; + +#pragma pack() + +#endif diff --git a/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiSpec.h b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiSpec.h new file mode 100644 index 00000000..7a7c0b3e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/Uefi/UefiSpec.h @@ -0,0 +1,2144 @@ +/** @file + Include file that supports UEFI. + + This include file must contain things defined in the UEFI 2.4 specification. + If a code construct is defined in the UEFI 2.4 specification it must be included + by this include file. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+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_SPEC_H__ +#define __UEFI_SPEC_H__ + +#include "efi/Uefi/UefiMultiPhase.h" + +#include "efi/Protocol/DevicePath.h" +#include "efi/Protocol/SimpleTextIn.h" +#include "efi/Protocol/SimpleTextInEx.h" +#include "efi/Protocol/SimpleTextOut.h" + +/// +/// Enumeration of EFI memory allocation types. +/// +typedef enum { + /// + /// Allocate any available range of pages that satisfies the request. + /// + AllocateAnyPages, + /// + /// Allocate any available range of pages whose uppermost address is less than + /// or equal to a specified maximum address. + /// + AllocateMaxAddress, + /// + /// Allocate pages at a specified address. + /// + AllocateAddress, + /// + /// Maximum enumeration value that may be used for bounds checking. + /// + MaxAllocateType +} EFI_ALLOCATE_TYPE; + +// +// Bit definitions for EFI_TIME.Daylight +// +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +/// +/// Value definition for EFI_TIME.TimeZone. +/// +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + +// +// Memory cacheability attributes +// +#define EFI_MEMORY_UC 0x0000000000000001ULL +#define EFI_MEMORY_WC 0x0000000000000002ULL +#define EFI_MEMORY_WT 0x0000000000000004ULL +#define EFI_MEMORY_WB 0x0000000000000008ULL +#define EFI_MEMORY_UCE 0x0000000000000010ULL +// +// Physical memory protection attributes +// +#define EFI_MEMORY_WP 0x0000000000001000ULL +#define EFI_MEMORY_RP 0x0000000000002000ULL +#define EFI_MEMORY_XP 0x0000000000004000ULL +// +// Runtime memory attribute +// +#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL + +/// +/// Memory descriptor version number. +/// +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +/// +/// Definition of an EFI memory descriptor. +/// +typedef struct { + /// + /// Type of the memory region. See EFI_MEMORY_TYPE. + /// + UINT32 Type; + /// + /// Physical address of the first byte of the memory region. Must aligned + /// on a 4 KB boundary. + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// Virtual address of the first byte of the memory region. Must aligned + /// on a 4 KB boundary. + /// + EFI_VIRTUAL_ADDRESS VirtualStart; + /// + /// Number of 4KB pages in the memory region. + /// + UINT64 NumberOfPages; + /// + /// Attributes of the memory region that describe the bit mask of capabilities + /// for that memory region, and not necessarily the current settings for that + /// memory region. + /// + UINT64 Attribute; +} EFI_MEMORY_DESCRIPTOR; + +/** + Allocates memory pages from the system. + + @param Type The type of allocation to perform. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory The pointer to a physical address. On input, the way in which the address is + used depends on the value of Type. + + @retval EFI_SUCCESS The requested pages were allocated. + @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or + AllocateMaxAddress or AllocateAddress. + 2) MemoryType is in the range + 3) Memory is NULL. + EfiMaxMemoryType..0x7FFFFFFF. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_NOT_FOUND The requested pages could not be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_PAGES)( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param Memory The base physical address of the pages to be freed. + @param Pages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_PAGES)( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + Returns the current memory map. + + @param MemoryMapSize A pointer to the size, in bytes, of the MemoryMap buffer. + On input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware if + the buffer was large enough, or the size of the buffer needed to contain + the map if the buffer was too small. + @param MemoryMap A pointer to the buffer in which firmware places the current memory + map. + @param MapKey A pointer to the location in which firmware returns the key for the + current memory map. + @param DescriptorSize A pointer to the location in which firmware returns the size, in bytes, of + an individual EFI_MEMORY_DESCRIPTOR. + @param DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current buffer size + needed to hold the memory map is returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER 1) MemoryMapSize is NULL. + 2) The MemoryMap buffer is not too small and MemoryMap is + NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_MAP)( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +/** + Allocates pool memory. + + @param PoolType The type of pool to allocate. + @param Size The number of bytes to allocate from the pool. + @param Buffer A pointer to a pointer to the allocated buffer if the call succeeds; + undefined otherwise. + + @retval EFI_SUCCESS The requested number of bytes was allocated. + @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. + @retval EFI_INVALID_PARAMETER PoolType was invalid or Buffer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_POOL)( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Returns pool memory to the system. + + @param Buffer The pointer to the buffer to free. + + @retval EFI_SUCCESS The memory was returned to the system. + @retval EFI_INVALID_PARAMETER Buffer was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_POOL)( + IN VOID *Buffer + ); + +/** + Changes the runtime addressing mode of EFI firmware from physical to virtual. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP)( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR *VirtualMap + ); + +/** + Connects one or more drivers to a controller. + + @param ControllerHandle The handle of the controller to which driver(s) are to be connected. + @param DriverImageHandle A pointer to an ordered list handles that support the + EFI_DRIVER_BINDING_PROTOCOL. + @param RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + @param Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the controller specified + by ControllerHandle have been created. If FALSE, then + the tree of controllers is only expanded one level. + + @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle. + 2) No drivers were connected to ControllerHandle, but + RemainingDevicePath is not NULL, and it is an End Device + Path Node. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances + present in the system. + 2) No drivers were connected to ControllerHandle. + @retval EFI_SECURITY_VIOLATION + The user has no permission to start UEFI device drivers on the device path + associated with the ControllerHandle or specified by the RemainingDevicePath. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle, OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, OPTIONAL + IN BOOLEAN Recursive + ); + +/** + Disconnects one or more drivers from a controller. + + @param ControllerHandle The handle of the controller from which driver(s) are to be disconnected. + @param DriverImageHandle The driver to disconnect from ControllerHandle. + If DriverImageHandle is NULL, then all the drivers currently managing + ControllerHandle are disconnected from ControllerHandle. + @param ChildHandle The handle of the child to destroy. + If ChildHandle is NULL, then all the children of ControllerHandle are + destroyed before the drivers are disconnected from ControllerHandle. + + @retval EFI_SUCCESS 1) One or more drivers were disconnected from the controller. + 2) On entry, no drivers are managing ControllerHandle. + 3) DriverImageHandle is not NULL, and on entry + DriverImageHandle is not managing ControllerHandle. + @retval EFI_INVALID_PARAMETER 1) ControllerHandle is NULL. + 2) DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE. + 3) ChildHandle is not NULL, and it is not a valid EFI_HANDLE. + 4) DriverImageHandle does not support the EFI_DRIVER_BINDING_PROTOCOL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to disconnect any drivers from + ControllerHandle. + @retval EFI_DEVICE_ERROR The controller could not be disconnected because of a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISCONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle, OPTIONAL + IN EFI_HANDLE ChildHandle OPTIONAL + ); + + + +// +// ConvertPointer DebugDisposition type. +// +#define EFI_OPTIONAL_PTR 0x00000001 + +/** + Determines the new virtual address that is to be used on subsequent memory accesses. + + @param DebugDisposition Supplies type information for the pointer being converted. + @param Address A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + + @retval EFI_SUCCESS The pointer pointed to by Address was modified. + @retval EFI_INVALID_PARAMETER 1) Address is NULL. + 2) *Address is NULL and DebugDisposition does + not have the EFI_OPTIONAL_PTR bit set. + @retval EFI_NOT_FOUND The pointer pointed to by Address was not found to be part + of the current memory map. This is normally fatal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONVERT_POINTER)( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + + +// +// These types can be ORed together as needed - for example, +// EVT_TIMER might be Ored with EVT_NOTIFY_WAIT or +// EVT_NOTIFY_SIGNAL. +// +#define EVT_TIMER 0x80000000 +#define EVT_RUNTIME 0x40000000 +#define EVT_NOTIFY_WAIT 0x00000100 +#define EVT_NOTIFY_SIGNAL 0x00000200 + +#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +// +// The event's NotifyContext pointer points to a runtime memory +// address. +// The event is deprecated in UEFI2.0 and later specifications. +// +#define EVT_RUNTIME_CONTEXT 0x20000000 + + +/** + Invoke a notification event + + @param Event Event whose notification function is being invoked. + @param Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +typedef +VOID +(EFIAPI *EFI_EVENT_NOTIFY)( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Creates an event. + + @param Type The type of event to create and its mode and attributes. + @param NotifyTpl The task priority level of event notifications, if needed. + @param NotifyFunction The pointer to the event's notification function, if any. + @param NotifyContext The pointer to the notification function's context; corresponds to parameter + Context in the notification function. + @param Event The pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT)( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT EFI_EVENT *Event + ); + +/** + Creates an event in a group. + + @param Type The type of event to create and its mode and attributes. + @param NotifyTpl The task priority level of event notifications,if needed. + @param NotifyFunction The pointer to the event's notification function, if any. + @param NotifyContext The pointer to the notification function's context; corresponds to parameter + Context in the notification function. + @param EventGroup The pointer to the unique identifier of the group to which this event belongs. + If this is NULL, then the function behaves as if the parameters were passed + to CreateEvent. + @param Event The pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT_EX)( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, + IN CONST VOID *NotifyContext OPTIONAL, + IN CONST EFI_GUID *EventGroup OPTIONAL, + OUT EFI_EVENT *Event + ); + +/// +/// Timer delay types +/// +typedef enum { + /// + /// An event's timer settings is to be cancelled and not trigger time is to be set/ + /// + TimerCancel, + /// + /// An event is to be signaled periodically at a specified interval from the current time. + /// + TimerPeriodic, + /// + /// An event is to be signaled once at a specified interval from the current time. + /// + TimerRelative +} EFI_TIMER_DELAY; + +/** + Sets the type of timer and the trigger time for a timer event. + + @param Event The timer event that is to be signaled at the specified time. + @param Type The type of time that is specified in TriggerTime. + @param TriggerTime The number of 100ns units until the timer expires. + A TriggerTime of 0 is legal. + If Type is TimerRelative and TriggerTime is 0, then the timer + event will be signaled on the next timer tick. + If Type is TimerPeriodic and TriggerTime is 0, then the timer + event will be signaled on every timer tick. + + @retval EFI_SUCCESS The event has been set to be signaled at the requested time. + @retval EFI_INVALID_PARAMETER Event or Type is not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER)( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + +/** + Signals an event. + + @param Event The event to signal. + + @retval EFI_SUCCESS The event has been signaled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIGNAL_EVENT)( + IN EFI_EVENT Event + ); + +/** + Stops execution until an event is signaled. + + @param NumberOfEvents The number of events in the Event array. + @param Event An array of EFI_EVENT. + @param Index The pointer to the index of the event which satisfied the wait condition. + + @retval EFI_SUCCESS The event indicated by Index was signaled. + @retval EFI_INVALID_PARAMETER 1) NumberOfEvents is 0. + 2) The event indicated by Index is of type + EVT_NOTIFY_SIGNAL. + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WAIT_FOR_EVENT)( + IN UINTN NumberOfEvents, + IN EFI_EVENT *Event, + OUT UINTN *Index + ); + +/** + Closes an event. + + @param Event The event to close. + + @retval EFI_SUCCESS The event has been closed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_EVENT)( + IN EFI_EVENT Event + ); + +/** + Checks whether an event is in the signaled state. + + @param Event The event to check. + + @retval EFI_SUCCESS The event is in the signaled state. + @retval EFI_NOT_READY The event is not in the signaled state. + @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CHECK_EVENT)( + IN EFI_EVENT Event + ); + + +// +// Task priority level +// +#define TPL_APPLICATION 4 +#define TPL_CALLBACK 8 +#define TPL_NOTIFY 16 +#define TPL_HIGH_LEVEL 31 + + +/** + Raises a task's priority level and returns its previous level. + + @param NewTpl The new task priority level. + + @return Previous task priority level + +**/ +typedef +EFI_TPL +(EFIAPI *EFI_RAISE_TPL)( + IN EFI_TPL NewTpl + ); + +/** + Restores a task's priority level to its previous value. + + @param OldTpl The previous task priority level to restore. + +**/ +typedef +VOID +(EFIAPI *EFI_RESTORE_TPL)( + IN EFI_TPL OldTpl + ); + +/** + Returns the value of a variable. + + @param VariableName A Null-terminated string that is the name of the vendor's + variable. + @param VendorGuid A unique identifier for the vendor. + @param Attributes If not NULL, a pointer to the memory location to return the + attributes bitmask for the variable. + @param DataSize On input, the size in bytes of the return Data buffer. + On output the size of data returned in Data. + @param Data The buffer to return the contents of the variable. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. + @retval EFI_INVALID_PARAMETER VariableName is NULL. + @retval EFI_INVALID_PARAMETER VendorGuid is NULL. + @retval EFI_INVALID_PARAMETER DataSize is NULL. + @retval EFI_INVALID_PARAMETER The DataSize is not too small and Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_VARIABLE)( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + Enumerates the current variable names. + + @param VariableNameSize The size of the VariableName buffer. + @param VariableName On input, supplies the last VariableName that was returned + by GetNextVariableName(). On output, returns the Nullterminated + string of the current variable. + @param VendorGuid On input, supplies the last VendorGuid that was returned by + GetNextVariableName(). On output, returns the + VendorGuid of the current variable. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The next variable was not found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result. + @retval EFI_INVALID_PARAMETER VariableNameSize is NULL. + @retval EFI_INVALID_PARAMETER VariableName is NULL. + @retval EFI_INVALID_PARAMETER VendorGuid is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME)( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +/** + Sets the value of a variable. + + @param VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo + does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VARIABLE)( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + + +/// +/// This provides the capabilities of the +/// real time clock device as exposed through the EFI interfaces. +/// +typedef struct { + /// + /// Provides the reporting resolution of the real-time clock device in + /// counts per second. For a normal PC-AT CMOS RTC device, this + /// value would be 1 Hz, or 1, to indicate that the device only reports + /// the time to the resolution of 1 second. + /// + UINT32 Resolution; + /// + /// Provides the timekeeping accuracy of the real-time clock in an + /// error rate of 1E-6 parts per million. For a clock with an accuracy + /// of 50 parts per million, the value in this field would be + /// 50,000,000. + /// + UINT32 Accuracy; + /// + /// A TRUE indicates that a time set operation clears the device's + /// time below the Resolution reporting level. A FALSE + /// indicates that the state below the Resolution level of the + /// device is not cleared when the time is set. Normal PC-AT CMOS + /// RTC devices set this value to FALSE. + /// + BOOLEAN SetsToZero; +} EFI_TIME_CAPABILITIES; + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIME)( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIME)( + IN EFI_TIME *Time + ); + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Enabled is NULL. + @retval EFI_INVALID_PARAMETER Pending is NULL. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_WAKEUP_TIME)( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + If Enable is FALSE, then this parameter is optional, and may be NULL. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WAKEUP_TIME)( + IN BOOLEAN Enable, + IN EFI_TIME *Time OPTIONAL + ); + +/** + Loads an EFI image into memory. + + @param BootPolicy If TRUE, indicates that the request originates from the boot + manager, and that the boot manager is attempting to load + FilePath as a boot selection. Ignored if SourceBuffer is + not NULL. + @param ParentImageHandle The caller's image handle. + @param DevicePath The DeviceHandle specific file path from which the image is + loaded. + @param SourceBuffer If not NULL, a pointer to the memory location containing a copy + of the image to be loaded. + @param SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL. + @param ImageHandle The pointer to the returned image handle that is created when the + image is successfully loaded. + + @retval EFI_SUCCESS Image was loaded into memory correctly. + @retval EFI_NOT_FOUND Both SourceBuffer and DevicePath are NULL. + @retval EFI_INVALID_PARAMETER One or more parametes are invalid. + @retval EFI_UNSUPPORTED The image type is not supported. + @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient resources. + @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not + understood. + @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error. + @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the + image from being loaded. NULL is returned in *ImageHandle. + @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a + valid EFI_LOADED_IMAGE_PROTOCOL. However, the current + platform policy specifies that the image should not be started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_LOAD)( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ); + +/** + Transfers control to a loaded image's entry point. + + @param ImageHandle Handle of image to be started. + @param ExitDataSize The pointer to the size, in bytes, of ExitData. + @param ExitData The pointer to a pointer to a data buffer that includes a Null-terminated + string, optionally followed by additional binary data. + + @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image + has already been initialized with StartImage. + @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started. + @return Exit code from image + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_START)( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +/** + Terminates a loaded EFI image and returns control to boot services. + + @param ImageHandle Handle that identifies the image. This parameter is passed to the + image on entry. + @param ExitStatus The image's exit code. + @param ExitDataSize The size, in bytes, of ExitData. Ignored if ExitStatus is EFI_SUCCESS. + @param ExitData The pointer to a data buffer that includes a Null-terminated string, + optionally followed by additional binary data. The string is a + description that the caller may use to further indicate the reason + for the image's exit. ExitData is only valid if ExitStatus + is something other than EFI_SUCCESS. The ExitData buffer + must be allocated by calling AllocatePool(). + + @retval EFI_SUCCESS The image specified by ImageHandle was unloaded. + @retval EFI_INVALID_PARAMETER The image specified by ImageHandle has been loaded and + started with LoadImage() and StartImage(), but the + image is not the currently executing image. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT)( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_UNLOAD)( + IN EFI_HANDLE ImageHandle + ); + +/** + Terminates all boot services. + + @param ImageHandle Handle that identifies the exiting image. + @param MapKey Key to the latest memory map. + + @retval EFI_SUCCESS Boot services have been terminated. + @retval EFI_INVALID_PARAMETER MapKey is incorrect. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT_BOOT_SERVICES)( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + +/** + Induces a fine-grained stall. + + @param Microseconds The number of microseconds to stall execution. + + @retval EFI_SUCCESS Execution was stalled at least the requested number of + Microseconds. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STALL)( + IN UINTN Microseconds + ); + +/** + Sets the system's watchdog timer. + + @param Timeout The number of seconds to set the watchdog timer to. + @param WatchdogCode The numeric code to log on a watchdog timer timeout event. + @param DataSize The size, in bytes, of WatchdogData. + @param WatchdogData A data buffer that includes a Null-terminated string, optionally + followed by additional binary data. + + @retval EFI_SUCCESS The timeout has been set. + @retval EFI_INVALID_PARAMETER The supplied WatchdogCode is invalid. + @retval EFI_UNSUPPORTED The system does not have a watchdog timer. + @retval EFI_DEVICE_ERROR The watchdog timer could not be programmed due to a hardware + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WATCHDOG_TIMER)( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ); + +/// +/// Enumeration of reset types. +/// +typedef enum { + /// + /// Used to induce a system-wide reset. This sets all circuitry within the + /// system to its initial state. This type of reset is asynchronous to system + /// operation and operates withgout regard to cycle boundaries. EfiColdReset + /// is tantamount to a system power cycle. + /// + EfiResetCold, + /// + /// Used to induce a system-wide initialization. The processors are set to their + /// initial state, and pending cycles are not corrupted. If the system does + /// not support this reset type, then an EfiResetCold must be performed. + /// + EfiResetWarm, + /// + /// Used to induce an entry into a power state equivalent to the ACPI G2/S5 or G3 + /// state. If the system does not support this reset type, then when the system + /// is rebooted, it should exhibit the EfiResetCold attributes. + /// + EfiResetShutdown, + /// + /// Used to induce a system-wide reset. The exact type of the reset is defined by + /// the EFI_GUID that follows the Null-terminated Unicode string passed into + /// ResetData. If the platform does not recognize the EFI_GUID in ResetData the + /// platform must pick a supported reset type to perform. The platform may + /// optionally log the parameters from any non-normal reset that occurs. + /// + EfiResetPlatformSpecific +} EFI_RESET_TYPE; + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + string, optionally followed by additional binary data. + +**/ +typedef +VOID +(EFIAPI *EFI_RESET_SYSTEM)( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + Returns a monotonically increasing count for the platform. + + @param Count The pointer to returned value. + + @retval EFI_SUCCESS The next monotonic count was returned. + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT)( + OUT UINT64 *Count + ); + +/** + Returns the next high 32 bits of the platform's monotonic counter. + + @param HighCount The pointer to returned value. + + @retval EFI_SUCCESS The next high monotonic count was returned. + @retval EFI_INVALID_PARAMETER HighCount is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT)( + OUT UINT32 *HighCount + ); + +/** + Computes and returns a 32-bit CRC for a data buffer. + + @param Data A pointer to the buffer on which the 32-bit CRC is to be computed. + @param DataSize The number of bytes in the buffer Data. + @param Crc32 The 32-bit CRC that was computed for the data buffer specified by Data + and DataSize. + + @retval EFI_SUCCESS The 32-bit CRC was computed for the data buffer and returned in + Crc32. + @retval EFI_INVALID_PARAMETER Data is NULL. + @retval EFI_INVALID_PARAMETER Crc32 is NULL. + @retval EFI_INVALID_PARAMETER DataSize is 0. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CALCULATE_CRC32)( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *Crc32 + ); + +/** + Copies the contents of one buffer to another buffer. + + @param Destination The pointer to the destination buffer of the memory copy. + @param Source The pointer to the source buffer of the memory copy. + @param Length Number of bytes to copy from Source to Destination. + +**/ +typedef +VOID +(EFIAPI *EFI_COPY_MEM)( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +/** + The SetMem() function fills a buffer with a specified value. + + @param Buffer The pointer to the buffer to fill. + @param Size Number of bytes in Buffer to fill. + @param Value Value to fill Buffer with. + +**/ +typedef +VOID +(EFIAPI *EFI_SET_MEM)( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/// +/// Enumeration of EFI Interface Types +/// +typedef enum { + /// + /// Indicates that the supplied protocol interface is supplied in native form. + /// + EFI_NATIVE_INTERFACE +} EFI_INTERFACE_TYPE; + +/** + Installs a protocol interface on a device handle. If the handle does not exist, it is created and added + to the list of handles in the system. InstallMultipleProtocolInterfaces() performs + more error checking than InstallProtocolInterface(), so it is recommended that + InstallMultipleProtocolInterfaces() be used in place of + InstallProtocolInterface() + + @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed. + @param Protocol The numeric ID of the protocol interface. + @param InterfaceType Indicates whether Interface is supplied in native form. + @param Interface A pointer to the protocol interface. + + @retval EFI_SUCCESS The protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES Space for a new handle could not be allocated. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER InterfaceType is not EFI_NATIVE_INTERFACE. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE)( + IN OUT EFI_HANDLE *Handle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + +/** + Installs one or more protocol interfaces into the boot services environment. + + @param Handle The pointer to a handle to install the new protocol interfaces on, + or a pointer to NULL if a new handle is to be allocated. + @param ... A variable argument list containing pairs of protocol GUIDs and protocol + interfaces. + + @retval EFI_SUCCESS All the protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in + the handle database. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)( + IN OUT EFI_HANDLE *Handle, + ... + ); + +/** + Reinstalls a protocol interface on a device handle. + + @param Handle Handle on which the interface is to be reinstalled. + @param Protocol The numeric ID of the interface. + @param OldInterface A pointer to the old interface. NULL can be used if a structure is not + associated with Protocol. + @param NewInterface A pointer to the new interface. + + @retval EFI_SUCCESS The protocol interface was reinstalled. + @retval EFI_NOT_FOUND The OldInterface on the handle was not found. + @retval EFI_ACCESS_DENIED The protocol interface could not be reinstalled, + because OldInterface is still being used by a + driver that will not release it. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ); + +/** + Removes a protocol interface from a device handle. It is recommended that + UninstallMultipleProtocolInterfaces() be used in place of + UninstallProtocolInterface(). + + @param Handle The handle on which the interface was installed. + @param Protocol The numeric ID of the interface. + @param Interface A pointer to the interface. + + @retval EFI_SUCCESS The interface was removed. + @retval EFI_NOT_FOUND The interface was not found. + @retval EFI_ACCESS_DENIED The interface was not removed because the interface + is still being used by a driver. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + Removes one or more protocol interfaces into the boot services environment. + + @param Handle The handle to remove the protocol interfaces from. + @param ... A variable argument list containing pairs of protocol GUIDs and + protocol interfaces. + + @retval EFI_SUCCESS All the protocol interfaces were removed. + @retval EFI_INVALID_PARAMETER One of the protocol interfaces was not previously installed on Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)( + IN EFI_HANDLE Handle, + ... + ); + +/** + Queries a handle to determine if it supports a specified protocol. + + @param Handle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + + @retval EFI_SUCCESS The interface information for the specified protocol was returned. + @retval EFI_UNSUPPORTED The device does not support the specified protocol. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HANDLE_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +/** + Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the + handle, it opens the protocol on behalf of the calling agent. + + @param Handle The handle for the protocol interface that is being opened. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + @param AgentHandle The handle of the agent that is opening the protocol interface + specified by Protocol and Interface. + @param ControllerHandle If the agent that is opening a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that requires the protocol interface. If the agent does not follow + the UEFI Driver Model, then this parameter is optional and may + be NULL. + @param Attributes The open mode of the protocol interface specified by Handle + and Protocol. + + @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the + protocol interface was returned in Interface. + @retval EFI_UNSUPPORTED Handle does not support Protocol. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment. + @retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent + handle is the same as AgentHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface, OPTIONAL + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ); + + +/** + Closes a protocol on a handle that was opened using OpenProtocol(). + + @param Handle The handle for the protocol interface that was previously opened + with OpenProtocol(), and is now being closed. + @param Protocol The published unique identifier of the protocol. + @param AgentHandle The handle of the agent that is closing the protocol interface. + @param ControllerHandle If the agent that opened a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that required the protocol interface. + + @retval EFI_SUCCESS The protocol instance was closed. + @retval EFI_INVALID_PARAMETER 1) Handle is NULL. + 2) AgentHandle is NULL. + 3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE. + 4) Protocol is NULL. + @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol. + 2) The protocol interface specified by Handle and Protocol is not + currently open by AgentHandle and ControllerHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + +/// +/// EFI Oprn Protocol Information Entry +/// +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +/** + Retrieves the list of agents that currently have a protocol interface opened. + + @param Handle The handle for the protocol interface that is being queried. + @param Protocol The published unique identifier of the protocol. + @param EntryBuffer A pointer to a buffer of open protocol information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + @param EntryCount A pointer to the number of entries in EntryBuffer. + + @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, and the + number of entries was returned EntryCount. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. + @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ); + +/** + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + + @param Handle The handle from which to retrieve the list of protocol interface + GUIDs. + @param ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are + installed on Handle. + @param ProtocolBufferCount A pointer to the number of GUID pointers present in + ProtocolBuffer. + + @retval EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL. + @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + +/** + Creates an event that is to be signaled whenever an interface is installed for a specified protocol. + + @param Protocol The numeric ID of the protocol for which the event is to be registered. + @param Event Event that is to be signaled whenever a protocol interface is registered + for Protocol. + @param Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS The notification event has been registered. + @retval EFI_OUT_OF_RESOURCES Space for the notification event could not be allocated. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Event is NULL. + @retval EFI_INVALID_PARAMETER Registration is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY)( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + +/// +/// Enumeration of EFI Locate Search Types +/// +typedef enum { + /// + /// Retrieve all the handles in the handle database. + /// + AllHandles, + /// + /// Retrieve the next handle fron a RegisterProtocolNotify() event. + /// + ByRegisterNotify, + /// + /// Retrieve the set of handles from the handle database that support a + /// specified protocol. + /// + ByProtocol +} EFI_LOCATE_SEARCH_TYPE; + +/** + Returns an array of handles that support a specified protocol. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Specifies the protocol to search by. + @param SearchKey Specifies the search key. + @param BufferSize On input, the size in bytes of Buffer. On output, the size in bytes of + the array returned in Buffer (if the buffer was large enough) or the + size, in bytes, of the buffer needed to obtain the array (if the buffer was + not large enough). + @param Buffer The buffer in which the array is returned. + + @retval EFI_SUCCESS The array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. + @retval EFI_INVALID_PARAMETER SearchType is not a member of EFI_LOCATE_SEARCH_TYPE. + @retval EFI_INVALID_PARAMETER SearchType is ByRegisterNotify and SearchKey is NULL. + @retval EFI_INVALID_PARAMETER SearchType is ByProtocol and Protocol is NULL. + @retval EFI_INVALID_PARAMETER One or more matches are found and BufferSize is NULL. + @retval EFI_INVALID_PARAMETER BufferSize is large enough for the result and Buffer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE)( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + +/** + Locates the handle to a device on the device path that supports the specified protocol. + + @param Protocol Specifies the protocol to search for. + @param DevicePath On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the device + path. + @param Device A pointer to the returned device handle. + + @retval EFI_SUCCESS The resulting handle was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_DEVICE_PATH)( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ); + +/** + Adds, updates, or removes a configuration table entry from the EFI System Table. + + @param Guid A pointer to the GUID for the entry to add, update, or remove. + @param Table A pointer to the configuration table for the entry to add, update, or + remove. May be NULL. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_NOT_FOUND An attempt was made to delete a nonexistent entry. + @retval EFI_INVALID_PARAMETER Guid is NULL. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE)( + IN EFI_GUID *Guid, + IN VOID *Table + ); + +/** + Returns an array of handles that support the requested protocol in a buffer allocated from pool. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Provides the protocol to search by. + This parameter is only valid for a SearchType of ByProtocol. + @param SearchKey Supplies the search key depending on the SearchType. + @param NoHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested array of handles that + support Protocol. + + @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of + handles in Buffer was returned in NoHandles. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results. + @retval EFI_INVALID_PARAMETER NoHandles is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE_BUFFER)( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +/** + Returns the first protocol instance that matches the given protocol. + + @param Protocol Provides the protocol to search for. + @param Registration Optional registration key returned from + RegisterProtocolNotify(). + @param Interface On return, a pointer to the first interface that matches Protocol and + Registration. + + @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in + Interface. + @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and + Registration. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_PROTOCOL)( + IN EFI_GUID *Protocol, + IN VOID *Registration, OPTIONAL + OUT VOID **Interface + ); + +/// +/// EFI Capsule Block Descriptor +/// +typedef struct { + /// + /// Length in bytes of the data pointed to by DataBlock/ContinuationPointer. + /// + UINT64 Length; + union { + /// + /// Physical address of the data block. This member of the union is + /// used if Length is not equal to zero. + /// + EFI_PHYSICAL_ADDRESS DataBlock; + /// + /// Physical address of another block of + /// EFI_CAPSULE_BLOCK_DESCRIPTOR structures. This + /// member of the union is used if Length is equal to zero. If + /// ContinuationPointer is zero this entry represents the end of the list. + /// + EFI_PHYSICAL_ADDRESS ContinuationPointer; + } Union; +} EFI_CAPSULE_BLOCK_DESCRIPTOR; + +/// +/// EFI Capsule Header. +/// +typedef struct { + /// + /// A GUID that defines the contents of a capsule. + /// + EFI_GUID CapsuleGuid; + /// + /// The size of the capsule header. This may be larger than the size of + /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply + /// extended header entries + /// + UINT32 HeaderSize; + /// + /// Bit-mapped list describing the capsule attributes. The Flag values + /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values + /// of 0x10000 - 0xFFFFFFFF are defined by this specification + /// + UINT32 Flags; + /// + /// Size in bytes of the capsule. + /// + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +/// +/// The EFI System Table entry must point to an array of capsules +/// that contain the same CapsuleGuid value. The array must be +/// prefixed by a UINT32 that represents the size of the array of capsules. +/// +typedef struct { + /// + /// the size of the array of capsules. + /// + UINT32 CapsuleArrayNumber; + /// + /// Point to an array of capsules that contain the same CapsuleGuid value. + /// + VOID* CapsulePtr[1]; +} EFI_CAPSULE_TABLE; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +/** + Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended + consumption, the firmware may process the capsule immediately. If the payload should persist + across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must + be passed into ResetSystem() and will cause the capsule to be processed by the firmware as + part of the reset process. + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param ScatterGatherList Physical pointer to a set of + EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the + location in physical memory of a set of capsules. + + @retval EFI_SUCCESS Valid capsule was passed. If + CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the + capsule has been successfully processed by the firmware. + @retval EFI_INVALID_PARAMETER CapsuleSize is NULL, or an incompatible set of flags were + set in the capsule header. + @retval EFI_INVALID_PARAMETER CapsuleCount is 0. + @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform. + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has been previously called this error indicates the capsule + is compatible with this platform but is not capable of being submitted or processed + in runtime. The caller may resubmit the capsule prior to ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previously called then this error indicates + the capsule is compatible with this platform but there are insufficient resources to process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UPDATE_CAPSULE)( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +/** + Returns if the capsule can be supported via UpdateCapsule(). + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can + support as an argument to UpdateCapsule() via + CapsuleHeaderArray and ScatterGatherList. + @param ResetType Returns the type of reset required for the capsule update. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform, and + MaximumCapsuleSize and ResetType are undefined. + @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL. + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has been previously called this error indicates the capsule + is compatible with this platform but is not capable of being submitted or processed + in runtime. The caller may resubmit the capsule prior to ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previously called then this error indicates + the capsule is compatible with this platform but there are insufficient resources to process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES)( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +/** + Returns information about the EFI variables. + + @param Attributes Attributes bitmask to specify the type of variables on + which to return information. + @param MaximumVariableStorageSize On output the maximum size of the storage space + available for the EFI variables associated with the + attributes specified. + @param RemainingVariableStorageSize Returns the remaining size of the storage space + available for the EFI variables associated with the + attributes specified. + @param MaximumVariableSize Returns the maximum size of the individual EFI + variables associated with the attributes specified. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied + @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the + MaximumVariableStorageSize, + RemainingVariableStorageSize, MaximumVariableSize + are undefined. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_VARIABLE_INFO)( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + +// +// Firmware should stop at a firmware user interface on next boot +// +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x0000000000000010 + +// +// EFI Runtime Services Table +// +#define EFI_SYSTEM_TABLE_SIGNATURE SIGNATURE_64 ('I','B','I',' ','S','Y','S','T') +#define EFI_2_40_SYSTEM_TABLE_REVISION ((2 << 16) | (40)) +#define EFI_2_31_SYSTEM_TABLE_REVISION ((2 << 16) | (31)) +#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) +#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) +#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) +#define EFI_SYSTEM_TABLE_REVISION EFI_2_40_SYSTEM_TABLE_REVISION +#define EFI_SPECIFICATION_VERSION EFI_SYSTEM_TABLE_REVISION + +#define EFI_RUNTIME_SERVICES_SIGNATURE SIGNATURE_64 ('R','U','N','T','S','E','R','V') +#define EFI_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +/// +/// EFI Runtime Services Table. +/// +typedef struct { + /// + /// The table header for the EFI Runtime Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Time Services + // + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + + // + // Virtual Memory Services + // + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + + // + // Variable Services + // + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + + // + // UEFI 2.0 Capsule Services + // + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + + // + // Miscellaneous UEFI 2.0 Service + // + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; +} EFI_RUNTIME_SERVICES; + + +#define EFI_BOOT_SERVICES_SIGNATURE SIGNATURE_64 ('B','O','O','T','S','E','R','V') +#define EFI_BOOT_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +/// +/// EFI Boot Services Table. +/// +typedef struct { + /// + /// The table header for the EFI Boot Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Task Priority Services + // + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory Services + // + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & Timer Services + // + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol Handler Services + // + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + VOID *Reserved; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image Services + // + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + // + // 32-bit CRC Services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Miscellaneous Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; + EFI_CREATE_EVENT_EX CreateEventEx; +} EFI_BOOT_SERVICES; + +/// +/// Contains a set of GUID/pointer pairs comprised of the ConfigurationTable field in the +/// EFI System Table. +/// +typedef struct { + /// + /// The 128-bit GUID value that uniquely identifies the system configuration table. + /// + EFI_GUID VendorGuid; + /// + /// A pointer to the table associated with VendorGuid. + /// + VOID *VendorTable; +} EFI_CONFIGURATION_TABLE; + +/// +/// EFI System Table +/// +typedef struct { + /// + /// The table header for the EFI System Table. + /// + EFI_TABLE_HEADER Hdr; + /// + /// A pointer to a null terminated string that identifies the vendor + /// that produces the system firmware for the platform. + /// + CHAR16 *FirmwareVendor; + /// + /// A firmware vendor specific value that identifies the revision + /// of the system firmware for the platform. + /// + UINT32 FirmwareRevision; + /// + /// The handle for the active console input device. This handle must support + /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. + /// + EFI_HANDLE ConsoleInHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is + /// associated with ConsoleInHandle. + /// + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + /// + /// The handle for the active console output device. + /// + EFI_HANDLE ConsoleOutHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface + /// that is associated with ConsoleOutHandle. + /// + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + /// + /// The handle for the active standard error console device. + /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + /// + EFI_HANDLE StandardErrorHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface + /// that is associated with StandardErrorHandle. + /// + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + /// + /// A pointer to the EFI Runtime Services Table. + /// + EFI_RUNTIME_SERVICES *RuntimeServices; + /// + /// A pointer to the EFI Boot Services Table. + /// + EFI_BOOT_SERVICES *BootServices; + /// + /// The number of system configuration tables in the buffer ConfigurationTable. + /// + UINTN NumberOfTableEntries; + /// + /// A pointer to the system configuration tables. + /// The number of entries in the table is NumberOfTableEntries. + /// + EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including + both device drivers and bus drivers. + + @param ImageHandle The firmware allocated handle for the UEFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_ENTRY_POINT)( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// EFI Load Options Attributes +// +#define LOAD_OPTION_ACTIVE 0x00000001 +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#define LOAD_OPTION_HIDDEN 0x00000008 +#define LOAD_OPTION_CATEGORY 0x00001F00 + +#define LOAD_OPTION_CATEGORY_BOOT 0x00000000 +#define LOAD_OPTION_CATEGORY_APP 0x00000100 + +#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001 +#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002 +#define EFI_BOOT_OPTION_SUPPORT_COUNT 0x00000300 + +/// +/// EFI Boot Key Data +/// +typedef union { + struct { + /// + /// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0. + /// + UINT32 Revision : 8; + /// + /// Either the left or right Shift keys must be pressed (1) or must not be pressed (0). + /// + UINT32 ShiftPressed : 1; + /// + /// Either the left or right Control keys must be pressed (1) or must not be pressed (0). + /// + UINT32 ControlPressed : 1; + /// + /// Either the left or right Alt keys must be pressed (1) or must not be pressed (0). + /// + UINT32 AltPressed : 1; + /// + /// Either the left or right Logo keys must be pressed (1) or must not be pressed (0). + /// + UINT32 LogoPressed : 1; + /// + /// The Menu key must be pressed (1) or must not be pressed (0). + /// + UINT32 MenuPressed : 1; + /// + /// The SysReq key must be pressed (1) or must not be pressed (0). + /// + UINT32 SysReqPressed : 1; + UINT32 Reserved : 16; + /// + /// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If + /// zero, then only the shift state is considered. If more than one, then the boot option will + /// only be launched if all of the specified keys are pressed with the same shift state. + /// + UINT32 InputKeyCount : 2; + } Options; + UINT32 PackedValue; +} EFI_BOOT_KEY_DATA; + +/// +/// EFI Key Option. +/// +#pragma pack(1) +typedef struct { + /// + /// Specifies options about how the key will be processed. + /// + EFI_BOOT_KEY_DATA KeyData; + /// + /// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to + /// which BootOption refers. If the CRC-32s do not match this value, then this key + /// option is ignored. + /// + UINT32 BootOptionCrc; + /// + /// The Boot#### option which will be invoked if this key is pressed and the boot option + /// is active (LOAD_OPTION_ACTIVE is set). + /// + UINT16 BootOption; + /// + /// The key codes to compare against those returned by the + /// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols. + /// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions. + /// + //EFI_INPUT_KEY Keys[]; +} EFI_KEY_OPTION; +#pragma pack() + +// +// EFI File location to boot from on removable media devices +// +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 L"\\EFI\\BOOT\\BOOTIA32.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 L"\\EFI\\BOOT\\BOOTIA64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_X64 L"\\EFI\\BOOT\\BOOTX64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_ARM L"\\EFI\\BOOT\\BOOTARM.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 L"\\EFI\\BOOT\\BOOTAA64.EFI" + +#if defined (MDE_CPU_IA32) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 +#elif defined (MDE_CPU_IPF) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 +#elif defined (MDE_CPU_X64) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_X64 +#elif defined (MDE_CPU_EBC) +#elif defined (MDE_CPU_ARM) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_ARM +#elif defined (MDE_CPU_AARCH64) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 +#else + #error Unknown Processor Type +#endif + +#include "efi/Uefi/UefiPxe.h" +#include "efi/Uefi/UefiGpt.h" +#include "efi/Uefi/UefiInternalFormRepresentation.h" + +#endif diff --git a/wimboot/wimboot-2.7.3/src/efi/X64/ProcessorBind.h b/wimboot/wimboot-2.7.3/src/efi/X64/ProcessorBind.h new file mode 100644 index 00000000..9b4c61b3 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/X64/ProcessorBind.h @@ -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.
+ 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 + diff --git a/wimboot/wimboot-2.7.3/src/efi/import.pl b/wimboot/wimboot-2.7.3/src/efi/import.pl new file mode 100644 index 00000000..2369ce36 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efi/import.pl @@ -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 ); diff --git a/wimboot/wimboot-2.7.3/src/efiblock.c b/wimboot/wimboot-2.7.3/src/efiblock.c new file mode 100644 index 00000000..fd794111 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efiblock.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#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; diff --git a/wimboot/wimboot-2.7.3/src/efiblock.h b/wimboot/wimboot-2.7.3/src/efiblock.h new file mode 100644 index 00000000..cd34fbb8 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efiblock.h @@ -0,0 +1,38 @@ +#ifndef _EFIBLOCK_H +#define _EFIBLOCK_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/efiboot.c b/wimboot/wimboot-2.7.3/src/efiboot.c new file mode 100644 index 00000000..5c800e9d --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efiboot.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#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 ); +} diff --git a/wimboot/wimboot-2.7.3/src/efiboot.h b/wimboot/wimboot-2.7.3/src/efiboot.h new file mode 100644 index 00000000..6671ef1c --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efiboot.h @@ -0,0 +1,38 @@ +#ifndef _EFIBOOT_H +#define _EFIBOOT_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/efifile.c b/wimboot/wimboot-2.7.3/src/efifile.c new file mode 100644 index 00000000..93353874 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efifile.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#include +#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() ); + } +} diff --git a/wimboot/wimboot-2.7.3/src/efifile.h b/wimboot/wimboot-2.7.3/src/efifile.h new file mode 100644 index 00000000..885ea5cf --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efifile.h @@ -0,0 +1,39 @@ +#ifndef _EFIFILE_H +#define _EFIFILE_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/efiguid.c b/wimboot/wimboot-2.7.3/src/efiguid.c new file mode 100644 index 00000000..00313fad --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efiguid.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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; diff --git a/wimboot/wimboot-2.7.3/src/efimain.c b/wimboot/wimboot-2.7.3/src/efimain.c new file mode 100644 index 00000000..0faa2178 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efimain.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/efipath.c b/wimboot/wimboot-2.7.3/src/efipath.c new file mode 100644 index 00000000..b4f1c5c5 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efipath.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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; +} diff --git a/wimboot/wimboot-2.7.3/src/efipath.h b/wimboot/wimboot-2.7.3/src/efipath.h new file mode 100644 index 00000000..ec7e8c35 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efipath.h @@ -0,0 +1,89 @@ +#ifndef _EFIPATH_H +#define _EFIPATH_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/efireloc.c b/wimboot/wimboot-2.7.3/src/efireloc.c new file mode 100644 index 00000000..4972b159 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/efireloc.c @@ -0,0 +1,556 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/errno.h b/wimboot/wimboot-2.7.3/src/errno.h new file mode 100644 index 00000000..bcda1cd7 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/errno.h @@ -0,0 +1,30 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/huffman.c b/wimboot/wimboot-2.7.3/src/huffman.c new file mode 100644 index 00000000..54fb704b --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/huffman.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/huffman.h b/wimboot/wimboot-2.7.3/src/huffman.h new file mode 100644 index 00000000..ee38c92b --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/huffman.h @@ -0,0 +1,110 @@ +#ifndef _HUFFMAN_H +#define _HUFFMAN_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + +/** 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<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 */ diff --git a/wimboot/wimboot-2.7.3/src/i386.i b/wimboot/wimboot-2.7.3/src/i386.i new file mode 100644 index 00000000..099070dc --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/i386.i @@ -0,0 +1 @@ + .code32 diff --git a/wimboot/wimboot-2.7.3/src/int13.c b/wimboot/wimboot-2.7.3/src/int13.c new file mode 100644 index 00000000..4538f9fd --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/int13.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#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; + } + } +} diff --git a/wimboot/wimboot-2.7.3/src/int13.h b/wimboot/wimboot-2.7.3/src/int13.h new file mode 100644 index 00000000..e765ffa7 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/int13.h @@ -0,0 +1,120 @@ +#ifndef _INT13_H +#define _INT13_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c b/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c new file mode 100644 index 00000000..5cc72310 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c @@ -0,0 +1,466 @@ +/* + * Copyright (C) 2006 Michael Brown . + * + * 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 +#include +#include +#include +#include +#include + +/** @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 = ""; + } 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; +} diff --git a/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h b/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h new file mode 100644 index 00000000..c48c97a8 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h @@ -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 +#include +#include + +/** + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/lznt1.c b/wimboot/wimboot-2.7.3/src/lznt1.c new file mode 100644 index 00000000..9695ee47 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/lznt1.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/lznt1.h b/wimboot/wimboot-2.7.3/src/lznt1.h new file mode 100644 index 00000000..d78da55f --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/lznt1.h @@ -0,0 +1,47 @@ +#ifndef _LZNT1_H +#define _LZNT1_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/lzx.c b/wimboot/wimboot-2.7.3/src/lzx.c new file mode 100644 index 00000000..15d0a559 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/lzx.c @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#include +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/lzx.h b/wimboot/wimboot-2.7.3/src/lzx.h new file mode 100644 index 00000000..9913f125 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/lzx.h @@ -0,0 +1,180 @@ +#ifndef _LZX_H +#define _LZX_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#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 */ diff --git a/wimboot/wimboot-2.7.3/src/main.c b/wimboot/wimboot-2.7.3/src/main.c new file mode 100644 index 00000000..f0ff3818 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/main.c @@ -0,0 +1,515 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#include +#include +#include +#include +#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" ); +} diff --git a/wimboot/wimboot-2.7.3/src/memmap.c b/wimboot/wimboot-2.7.3/src/memmap.c new file mode 100644 index 00000000..e7ef8a9b --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/memmap.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * 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 +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/memmap.h b/wimboot/wimboot-2.7.3/src/memmap.h new file mode 100644 index 00000000..30ecb8e3 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/memmap.h @@ -0,0 +1,58 @@ +#ifndef _MEMMAP_H +#define _MEMMAP_H + +/* + * Copyright (C) 2021 Michael Brown . + * + * 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 + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/paging.c b/wimboot/wimboot-2.7.3/src/paging.c new file mode 100644 index 00000000..ba043af9 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/paging.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * 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 +#include +#include +#include +#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 ); +} diff --git a/wimboot/wimboot-2.7.3/src/paging.h b/wimboot/wimboot-2.7.3/src/paging.h new file mode 100644 index 00000000..8dbcfb77 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/paging.h @@ -0,0 +1,79 @@ +#ifndef _PAGING_H +#define _PAGING_H + +/* + * Copyright (C) 2021 Michael Brown . + * + * 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 + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/pause.c b/wimboot/wimboot-2.7.3/src/pause.c new file mode 100644 index 00000000..72c50f0f --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/pause.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 +#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" ); + } +} diff --git a/wimboot/wimboot-2.7.3/src/pause.h b/wimboot/wimboot-2.7.3/src/pause.h new file mode 100644 index 00000000..4fe364b2 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/pause.h @@ -0,0 +1,32 @@ +#ifndef _PAUSE_H +#define _PAUSE_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/peloader.c b/wimboot/wimboot-2.7.3/src/peloader.c new file mode 100644 index 00000000..7576933a --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/peloader.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#include +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/peloader.h b/wimboot/wimboot-2.7.3/src/peloader.h new file mode 100644 index 00000000..08a30571 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/peloader.h @@ -0,0 +1,195 @@ +#ifndef _PELOADER_H +#define _PELOADER_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#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 */ diff --git a/wimboot/wimboot-2.7.3/src/rotate.h b/wimboot/wimboot-2.7.3/src/rotate.h new file mode 100644 index 00000000..7f087551 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/rotate.h @@ -0,0 +1,51 @@ +#ifndef _ROTATE_H +#define _ROTATE_H + +/** @file + * + * Bit operations + */ + +#include + +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 */ diff --git a/wimboot/wimboot-2.7.3/src/script.lds b/wimboot/wimboot-2.7.3/src/script.lds new file mode 100644 index 00000000..64643bd1 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/script.lds @@ -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.*) + } +} diff --git a/wimboot/wimboot-2.7.3/src/sha1.c b/wimboot/wimboot-2.7.3/src/sha1.c new file mode 100644 index 00000000..fc5c061e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/sha1.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#include +#include +#include +#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 ) ); +} diff --git a/wimboot/wimboot-2.7.3/src/sha1.h b/wimboot/wimboot-2.7.3/src/sha1.h new file mode 100644 index 00000000..af52274d --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/sha1.h @@ -0,0 +1,72 @@ +#ifndef _SHA1_H +#define _SHA1_H + +/** @file + * + * SHA-1 algorithm + * + */ + +#include + +/** 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 */ diff --git a/wimboot/wimboot-2.7.3/src/stdarg.h b/wimboot/wimboot-2.7.3/src/stdarg.h new file mode 100644 index 00000000..80c5a002 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stdarg.h @@ -0,0 +1,36 @@ +#ifndef _STDARG_H +#define _STDARG_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/stddef.h b/wimboot/wimboot-2.7.3/src/stddef.h new file mode 100644 index 00000000..d1f8edbc --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stddef.h @@ -0,0 +1,40 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + +#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 */ diff --git a/wimboot/wimboot-2.7.3/src/stdint.h b/wimboot/wimboot-2.7.3/src/stdint.h new file mode 100644 index 00000000..297994b2 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stdint.h @@ -0,0 +1,48 @@ +#ifndef _STDINT_H +#define _STDINT_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 */ diff --git a/wimboot/wimboot-2.7.3/src/stdio.c b/wimboot/wimboot-2.7.3/src/stdio.c new file mode 100644 index 00000000..c119bd3c --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stdio.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include +#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; +} diff --git a/wimboot/wimboot-2.7.3/src/stdio.h b/wimboot/wimboot-2.7.3/src/stdio.h new file mode 100644 index 00000000..72cd4521 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stdio.h @@ -0,0 +1,46 @@ +#ifndef _STDIO_H +#define _STDIO_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 +#include + +extern int putchar ( int character ); +extern int getchar ( void ); + +extern int __attribute__ (( format ( printf, 1, 2 ) )) +printf ( const char *fmt, ... ); + +extern int __attribute__ (( format ( printf, 3, 4 ) )) +snprintf ( char *buf, size_t size, const char *fmt, ... ); + +extern int vprintf ( const char *fmt, va_list args ); + +extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ); + +#endif /* _STDIO_H */ diff --git a/wimboot/wimboot-2.7.3/src/stdlib.h b/wimboot/wimboot-2.7.3/src/stdlib.h new file mode 100644 index 00000000..64cb91a3 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/stdlib.h @@ -0,0 +1,32 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 library + * + */ + +extern unsigned long strtoul ( const char *nptr, char **endptr, int base ); + +#endif /* _STDLIB_H */ diff --git a/wimboot/wimboot-2.7.3/src/string.c b/wimboot/wimboot-2.7.3/src/string.c new file mode 100644 index 00000000..6c0aaf77 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/string.c @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * String functions + * + */ + +#include +#include +#include +#include "ctype.h" +#include "wctype.h" + +/** + * Copy memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * memcpy ( void *dest, const void *src, size_t len ) { + void *edi = dest; + const void *esi = src; + int discard_ecx; + + /* Perform dword-based copy for bulk, then byte-based for remainder */ + __asm__ __volatile__ ( "rep movsl" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len >> 2 ) + : "memory" ); + __asm__ __volatile__ ( "rep movsb" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len & 3 ) + : "memory" ); + return dest; +} + +/** + * Copy memory area backwards + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +static void * memcpy_reverse ( void *dest, const void *src, size_t len ) { + void *edi = ( dest + len - 1 ); + const void *esi = ( src + len - 1 ); + int discard_ecx; + + /* Assume memmove() is not performance-critical, and perform a + * bytewise copy for simplicity. + * + * Disable interrupts to avoid known problems on platforms + * that assume the direction flag always remains cleared. + */ + __asm__ __volatile__ ( "pushf\n\t" + "cli\n\t" + "std\n\t" + "rep movsb\n\t" + "popf\n\t" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), + "2" ( len ) + : "memory" ); + return dest; +} + +/** + * Copy (possibly overlapping) memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * memmove ( void *dest, const void *src, size_t len ) { + + if ( dest <= src ) { + return memcpy ( dest, src, len ); + } else { + return memcpy_reverse ( dest, src, len ); + } +} + +/** + * Set memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * memset ( void *dest, int c, size_t len ) { + void *edi = dest; + int eax = c; + int discard_ecx; + + /* Expand byte to whole dword */ + eax |= ( eax << 8 ); + eax |= ( eax << 16 ); + + /* Perform dword-based set for bulk, then byte-based for remainder */ + __asm__ __volatile__ ( "rep stosl" + : "=&D" ( edi ), "=&a" ( eax ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( eax ), "2" ( len >> 2 ) + : "memory" ); + __asm__ __volatile__ ( "rep stosb" + : "=&D" ( edi ), "=&a" ( eax ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( eax ), "2" ( len & 3 ) + : "memory" ); + return dest; +} + +/** + * Compare memory areas + * + * @v src1 First source area + * @v src2 Second source area + * @v len Length + * @ret diff Difference + */ +int memcmp ( const void *src1, const void *src2, size_t len ) { + const uint8_t *bytes1 = src1; + const uint8_t *bytes2 = src2; + int diff; + + while ( len-- ) { + if ( ( diff = ( *(bytes1++) - *(bytes2++) ) ) ) + return diff; + } + return 0; +} + +/** + * Compare two strings + * + * @v str1 First string + * @v str2 Second string + * @ret diff Difference + */ +int strcmp ( const char *str1, const char *str2 ) { + int c1; + int c2; + + do { + c1 = *(str1++); + c2 = *(str2++); + } while ( ( c1 != '\0' ) && ( c1 == c2 ) ); + + return ( c1 - c2 ); +} + +/** + * Compare two strings, case-insensitively + * + * @v str1 First string + * @v str2 Second string + * @ret diff Difference + */ +int strcasecmp ( const char *str1, const char *str2 ) { + int c1; + int c2; + + do { + c1 = toupper ( *(str1++) ); + c2 = toupper ( *(str2++) ); + } while ( ( c1 != '\0' ) && ( c1 == c2 ) ); + + return ( c1 - c2 ); +} + +/** + * Compare two wide-character strings, case-insensitively + * + * @v str1 First string + * @v str2 Second string + * @ret diff Difference + */ +int wcscasecmp ( const wchar_t *str1, const wchar_t *str2 ) { + int c1; + int c2; + + do { + c1 = towupper ( *(str1++) ); + c2 = towupper ( *(str2++) ); + } while ( ( c1 != L'\0' ) && ( c1 == c2 ) ); + + return ( c1 - c2 ); +} + +/** + * Get length of string + * + * @v str String + * @ret len Length + */ +size_t strlen ( const char *str ) { + size_t len = 0; + + while ( *(str++) ) + len++; + return len; +} + +/** + * Get length of wide-character string + * + * @v str String + * @ret len Length (in characters) + */ +size_t wcslen ( const wchar_t *str ) { + size_t len = 0; + + while ( *(str++) ) + len++; + return len; +} + +/** + * Find character in wide-character string + * + * @v str String + * @v c Wide character + * @ret first First occurrence of wide character in string, or NULL + */ +wchar_t * wcschr ( const wchar_t *str, wchar_t c ) { + + for ( ; *str ; str++ ) { + if ( *str == c ) + return ( ( wchar_t * )str ); + } + return NULL; +} + +char *strchr(const char *str, char c) { + for ( ; *str ; str++ ) { + if ( *str == c ) + return ( ( char * )str ); + } + return NULL; +} + +/** + * Check to see if character is a space + * + * @v c Character + * @ret isspace Character is a space + */ +int isspace ( int c ) { + switch ( c ) { + case ' ' : + case '\f' : + case '\n' : + case '\r' : + case '\t' : + case '\v' : + return 1; + default: + return 0; + } +} + +/** + * Convert a string to an unsigned integer + * + * @v nptr String + * @v endptr End pointer to fill in (or NULL) + * @v base Numeric base + * @ret val Value + */ +unsigned long strtoul ( const char *nptr, char **endptr, int base ) { + unsigned long val = 0; + int negate = 0; + unsigned int digit; + + /* Skip any leading whitespace */ + while ( isspace ( *nptr ) ) + nptr++; + + /* Parse sign, if present */ + if ( *nptr == '+' ) { + nptr++; + } else if ( *nptr == '-' ) { + nptr++; + negate = 1; + } + + /* Parse base */ + if ( base == 0 ) { + + /* Default to decimal */ + base = 10; + + /* Check for octal or hexadecimal markers */ + if ( *nptr == '0' ) { + nptr++; + base = 8; + if ( ( *nptr | 0x20 ) == 'x' ) { + nptr++; + base = 16; + } + } + } + + /* Parse digits */ + for ( ; ; nptr++ ) { + digit = *nptr; + if ( digit >= 'a' ) { + digit = ( digit - 'a' + 10 ); + } else if ( digit >= 'A' ) { + digit = ( digit - 'A' + 10 ); + } else if ( digit <= '9' ) { + digit = ( digit - '0' ); + } + if ( digit >= ( unsigned int ) base ) + break; + val = ( ( val * base ) + digit ); + } + + /* Record end marker, if applicable */ + if ( endptr ) + *endptr = ( ( char * ) nptr ); + + /* Return value */ + return ( negate ? -val : val ); +} diff --git a/wimboot/wimboot-2.7.3/src/string.h b/wimboot/wimboot-2.7.3/src/string.h new file mode 100644 index 00000000..b48d9bc2 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/string.h @@ -0,0 +1,39 @@ +#ifndef _STRING_H +#define _STRING_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * String operations + * + */ + +#include + +extern void * memcpy ( void *dest, const void *src, size_t len ); +extern void * memmove ( void *dest, const void *src, size_t len ); +extern void * memset ( void *dest, int c, size_t len ); +extern int memcmp ( const void *src1, const void *src2, size_t len ); +extern int strcmp ( const char *str1, const char *str2 ); +extern size_t strlen ( const char *str ); + +#endif /* _STRING_H */ diff --git a/wimboot/wimboot-2.7.3/src/strings.h b/wimboot/wimboot-2.7.3/src/strings.h new file mode 100644 index 00000000..9a59b79e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/strings.h @@ -0,0 +1,32 @@ +#ifndef _STRINGS_H +#define _STRINGS_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * String operations + * + */ + +extern int strcasecmp ( const char *str1, const char *str2 ); + +#endif /* _STRINGS_H */ diff --git a/wimboot/wimboot-2.7.3/src/vdisk.c b/wimboot/wimboot-2.7.3/src/vdisk.c new file mode 100644 index 00000000..7885a5b4 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/vdisk.c @@ -0,0 +1,665 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Virtual disk + * + */ + +#include +#include +#include +#include +#include "ctype.h" +#include "wimboot.h" +#include "vdisk.h" + +/** Virtual files */ +struct vdisk_file vdisk_files[VDISK_MAX_FILES]; + +/** + * Read from virtual Master Boot Record + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_mbr ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_mbr *mbr = data; + + /* Construct MBR */ + memset ( mbr, 0, sizeof ( *mbr ) ); + mbr->partitions[0].bootable = VDISK_MBR_BOOTABLE; + mbr->partitions[0].type = VDISK_MBR_TYPE_FAT32; + mbr->partitions[0].start = VDISK_PARTITION_LBA; + mbr->partitions[0].length = VDISK_PARTITION_COUNT; + mbr->signature = VDISK_MBR_SIGNATURE; + mbr->magic = VDISK_MBR_MAGIC; +} + +/** + * Read from virtual Volume Boot Record + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_vbr ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_vbr *vbr = data; + + /* Construct VBR */ + memset ( vbr, 0, sizeof ( *vbr ) ); + vbr->jump[0] = VDISK_VBR_JUMP_WTF_MS; + memcpy ( vbr->oemid, VDISK_VBR_OEMID, sizeof ( vbr->oemid ) ); + vbr->bytes_per_sector = VDISK_SECTOR_SIZE; + vbr->sectors_per_cluster = VDISK_CLUSTER_COUNT; + vbr->reserved_sectors = VDISK_RESERVED_COUNT; + vbr->fats = 1; + vbr->media = VDISK_VBR_MEDIA; + vbr->sectors_per_track = VDISK_SECTORS_PER_TRACK; + vbr->heads = VDISK_HEADS; + vbr->hidden_sectors = VDISK_VBR_LBA; + vbr->sectors = VDISK_PARTITION_COUNT; + vbr->sectors_per_fat = VDISK_SECTORS_PER_FAT; + vbr->root = VDISK_ROOT_CLUSTER; + vbr->fsinfo = VDISK_FSINFO_SECTOR; + vbr->backup = VDISK_BACKUP_VBR_SECTOR; + vbr->signature = VDISK_VBR_SIGNATURE; + vbr->serial = VDISK_VBR_SERIAL; + memcpy ( vbr->label, VDISK_VBR_LABEL, sizeof ( vbr->label ) ); + memcpy ( vbr->system, VDISK_VBR_SYSTEM, sizeof ( vbr->system ) ); + vbr->magic = VDISK_VBR_MAGIC; +} + +/** + * Read from virtual FSInfo + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_fsinfo ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_fsinfo *fsinfo = data; + + /* Construct FSInfo */ + memset ( fsinfo, 0, sizeof ( *fsinfo ) ); + fsinfo->magic1 = VDISK_FSINFO_MAGIC1; + fsinfo->magic2 = VDISK_FSINFO_MAGIC2; + fsinfo->next_free = VDISK_FSINFO_NEXT_FREE; + fsinfo->magic3 = VDISK_FSINFO_MAGIC3; +} + +/** + * Read from virtual FAT + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_fat ( uint64_t lba, unsigned int count, void *data ) { + uint32_t *next = data; + uint32_t start; + uint32_t end; + uint32_t file_end_marker; + unsigned int i; + + /* Calculate window within FAT */ + start = ( ( lba - VDISK_FAT_LBA ) * + ( VDISK_SECTOR_SIZE / sizeof ( *next ) ) ); + end = ( start + ( count * ( VDISK_SECTOR_SIZE / sizeof ( *next ) ) ) ); + next -= start; + + /* Start by marking each cluster as chaining to the next */ + for ( i = start ; i < end ; i++ ) + next[i] = ( i + 1 ); + + /* Add first-sector special values, if applicable */ + if ( start == 0 ) { + next[0] = ( ( VDISK_FAT_END_MARKER & ~0xff ) | + VDISK_VBR_MEDIA ); + for ( i = 1; i < ( VDISK_SECTOR_SIZE / sizeof ( *next ) ); i++ ) + next[i] = VDISK_FAT_END_MARKER; + } + + /* Add end-of-file markers, if applicable */ + for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { + if ( vdisk_files[i].read ) { + file_end_marker = ( VDISK_FILE_CLUSTER ( i ) + + ( ( vdisk_files[i].xlen - 1 ) / + VDISK_CLUSTER_SIZE ) ); + if ( ( file_end_marker >= start ) && + ( file_end_marker < end ) ) { + next[file_end_marker] = VDISK_FAT_END_MARKER; + } + } + } +} + +/** + * Initialise empty directory + * + * @v dir Virtual directory + * @ret dirent Starting (i.e. final) directory entry + */ +static union vdisk_directory_entry * +vdisk_empty_dir ( struct vdisk_directory *dir ) { + unsigned int i; + + /* Mark all entries as present and deleted */ + memset ( dir, 0, sizeof ( *dir ) ); + for ( i = 0 ; i < VDISK_DIRENT_PER_SECTOR ; i++ ) { + dir->entry[i].deleted = VDISK_DIRENT_DELETED; + } + + return &dir->entry[ VDISK_DIRENT_PER_SECTOR - 1 ]; +} + +/** + * Construct directory entry + * + * @v dirent Starting (i.e. final) directory entry + * @v name File name + * @v len File length + * @v attr File attributes + * @v cluster File starting cluster + * @ret next Next available directory entry + */ +static union vdisk_directory_entry * +vdisk_directory_entry ( union vdisk_directory_entry *dirent, const char *name, + size_t len,unsigned int attr, uint32_t cluster ) { + union vdisk_directory_entry *dos = dirent; + union vdisk_directory_entry *lfn = ( dos - 1 ); + uint8_t *checksum_data; + uint8_t checksum; + unsigned int sequence; + uint16_t *lfn_char; + char c; + unsigned int i; + + /* Populate directory entry (with invalid 8.3 filename) */ + memset ( dos->dos.filename.raw, ' ', sizeof ( dos->dos.filename.raw ) ); + dos->dos.attr = attr; + dos->dos.size = len; + dos->dos.cluster_high = ( cluster >> 16 ); + dos->dos.cluster_low = ( cluster & 0xffff ); + + /* Calculate checksum of 8.3 filename */ + checksum = 0; + checksum_data = dos->dos.filename.raw; + for ( i = 0 ; i < sizeof ( dos->dos.filename.raw ) ; i++ ) { + checksum = ( ( ( ( checksum & 1 ) << 7 ) | + ( checksum >> 1 ) ) + + *(checksum_data++) ); + } + + /* Construct long filename record */ + lfn_char = &lfn->lfn.name_1[0]; + sequence = 1; + while ( 1 ) { + + /* Initialise long filename, if necessary */ + if ( lfn->lfn.attr != VDISK_LFN_ATTR ) { + lfn->lfn.sequence = sequence++; + memset ( lfn->lfn.name_1, 0xff, + sizeof ( lfn->lfn.name_1 ) ); + lfn->lfn.attr = VDISK_LFN_ATTR; + lfn->lfn.checksum = checksum; + memset ( lfn->lfn.name_2, 0xff, + sizeof ( lfn->lfn.name_2 ) ); + memset ( lfn->lfn.name_3, 0xff, + sizeof ( lfn->lfn.name_3 ) ); + } + + /* Add character to long filename */ + c = *(name++); + *lfn_char = c; + if ( ! c ) + break; + + /* Move to next character within long filename */ + if ( lfn_char == &lfn->lfn.name_1[4] ) { + lfn_char = &lfn->lfn.name_2[0]; + } else if ( lfn_char == &lfn->lfn.name_2[5] ) { + lfn_char = &lfn->lfn.name_3[0]; + } else if ( lfn_char == &lfn->lfn.name_3[1] ) { + lfn--; + lfn_char = &lfn->lfn.name_1[0]; + } else { + lfn_char++; + } + } + lfn->lfn.sequence |= VDISK_LFN_END; + + return ( lfn - 1 ); +} + +/** + * Read subdirectories from virtual root directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_root ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_directory *dir = data; + union vdisk_directory_entry *dirent; + + /* Construct subdirectories */ + dirent = vdisk_empty_dir ( dir ); + dirent = vdisk_directory_entry ( dirent, "BOOT", 0, VDISK_DIRECTORY, + VDISK_BOOT_CLUSTER ); + dirent = vdisk_directory_entry ( dirent, "SOURCES", 0, VDISK_DIRECTORY, + VDISK_SOURCES_CLUSTER ); + dirent = vdisk_directory_entry ( dirent, "EFI", 0, VDISK_DIRECTORY, + VDISK_EFI_CLUSTER ); +} + +/** + * Read subdirectories from virtual boot directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_boot ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_directory *dir = data; + union vdisk_directory_entry *dirent; + + /* Construct subdirectories */ + dirent = vdisk_empty_dir ( dir ); + dirent = vdisk_directory_entry ( dirent, "FONTS", 0, VDISK_DIRECTORY, + VDISK_FONTS_CLUSTER ); + dirent = vdisk_directory_entry ( dirent, "RESOURCES", 0, + VDISK_DIRECTORY, + VDISK_RESOURCES_CLUSTER ); +} + +/** + * Read subdirectories from virtual sources directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_sources ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_directory *dir = data; + + /* Construct subdirectories */ + vdisk_empty_dir ( dir ); +} + +/** + * Read subdirectories from virtual fonts directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_fonts ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_directory *dir = data; + + /* Construct subdirectories */ + vdisk_empty_dir ( dir ); +} + +/** + * Read subdirectories from virtual resources directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_resources ( uint64_t lba __unused, + unsigned int count __unused, void *data ) { + struct vdisk_directory *dir = data; + + /* Construct subdirectories */ + vdisk_empty_dir ( dir ); +} + +/** + * Read subdirectories from virtual EFI directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_efi ( uint64_t lba __unused, unsigned int count __unused, + void *data ) { + struct vdisk_directory *dir = data; + union vdisk_directory_entry *dirent; + + /* Construct subdirectories */ + dirent = vdisk_empty_dir ( dir ); + dirent = vdisk_directory_entry ( dirent, "BOOT", 0, VDISK_DIRECTORY, + VDISK_BOOT_CLUSTER ); + dirent = vdisk_directory_entry ( dirent, "MICROSOFT", 0, + VDISK_DIRECTORY, + VDISK_MICROSOFT_CLUSTER ); +} + +/** + * Read subdirectories from virtual Microsoft directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_microsoft ( uint64_t lba __unused, + unsigned int count __unused, void *data ) { + struct vdisk_directory *dir = data; + union vdisk_directory_entry *dirent; + + /* Construct subdirectories */ + dirent = vdisk_empty_dir ( dir ); + dirent = vdisk_directory_entry ( dirent, "BOOT", 0, VDISK_DIRECTORY, + VDISK_BOOT_CLUSTER ); +} + +/** + * Read files from virtual directory + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_dir_files ( uint64_t lba, unsigned int count, void *data ) { + struct vdisk_directory *dir; + union vdisk_directory_entry *dirent; + struct vdisk_file *file; + unsigned int idx; + + for ( ; count ; lba++, count--, data += VDISK_SECTOR_SIZE ) { + + /* Initialise directory */ + dir = data; + vdisk_empty_dir ( dir ); + dirent = &dir->entry[ VDISK_DIRENT_PER_SECTOR - 1 ]; + + /* Identify file */ + idx = VDISK_FILE_DIRENT_IDX ( lba ); + assert ( idx < ( sizeof ( vdisk_files ) / + sizeof ( vdisk_files[0] ) ) ); + file = &vdisk_files[idx]; + if ( ! file->read ) + continue; + + /* Populate directory entry */ + vdisk_directory_entry ( dirent, file->name, file->xlen, + VDISK_READ_ONLY, + VDISK_FILE_CLUSTER ( idx ) ); + } +} + +/** + * Read from virtual file (or empty space) + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +static void vdisk_file ( uint64_t lba, unsigned int count, void *data ) { + struct vdisk_file *file; + size_t offset; + size_t len; + size_t copy_len; + size_t pad_len; + size_t patch_len; + + /* Construct file portion */ + file = &vdisk_files[ VDISK_FILE_IDX ( lba ) ]; + offset = VDISK_FILE_OFFSET ( lba ); + len = ( count * VDISK_SECTOR_SIZE ); + + /* Copy any initialised-data portion */ + copy_len = ( ( offset < file->len ) ? ( file->len - offset ) : 0 ); + if ( copy_len > len ) + copy_len = len; + if ( copy_len ) + file->read ( file, data, offset, copy_len ); + + /* Zero any uninitialised-data portion */ + pad_len = ( len - copy_len ); + memset ( ( data + copy_len ), 0, pad_len ); + + /* Patch any applicable portion */ + patch_len = ( ( offset < file->xlen ) ? ( file->xlen - offset ) : 0 ); + if ( patch_len > len ) + patch_len = len; + if ( file->patch ) + file->patch ( file, data, offset, patch_len ); +} + +/** A virtual disk region */ +struct vdisk_region { + /** Name */ + const char *name; + /** Starting LBA */ + uint64_t lba; + /** Number of blocks */ + unsigned int count; + /** + * Build data from this region + * + * @v start Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ + void ( * build ) ( uint64_t lba, unsigned int count, void *data ); +}; + +/** Define a virtual disk region */ +#define VDISK_REGION( _name, _build, _lba, _count ) { \ + .name = _name, \ + .lba = _lba, \ + .count = _count, \ + .build = _build, \ + } + +/** Define a virtual disk directory region */ +#define VDISK_DIRECTORY_REGION( _name, _build_subdirs, _lba ) { \ + .name = _name " subdirs", \ + .lba = _lba, \ + .count = 1, \ + .build = _build_subdirs, \ + }, { \ + .name = _name " files", \ + .lba = ( _lba + 1 ), \ + .count = ( VDISK_CLUSTER_COUNT - 1 ), \ + .build = vdisk_dir_files, \ + } + +/** Virtual disk regions */ +static struct vdisk_region vdisk_regions[] = { + VDISK_REGION ( "MBR", vdisk_mbr, + VDISK_MBR_LBA, VDISK_MBR_COUNT ), + VDISK_REGION ( "VBR", vdisk_vbr, + VDISK_VBR_LBA, VDISK_VBR_COUNT ), + VDISK_REGION ( "FSInfo", vdisk_fsinfo, + VDISK_FSINFO_LBA, VDISK_FSINFO_COUNT ), + VDISK_REGION ( "VBR Backup", vdisk_vbr, + VDISK_BACKUP_VBR_LBA, VDISK_BACKUP_VBR_COUNT ), + VDISK_REGION ( "FAT", vdisk_fat, + VDISK_FAT_LBA, VDISK_FAT_COUNT ), + VDISK_DIRECTORY_REGION ( "Root", vdisk_root, VDISK_ROOT_LBA ), + VDISK_DIRECTORY_REGION ( "Boot", vdisk_boot, VDISK_BOOT_LBA ), + VDISK_DIRECTORY_REGION ( "Sources", vdisk_sources, VDISK_SOURCES_LBA ), + VDISK_DIRECTORY_REGION ( "Fonts", vdisk_fonts, VDISK_FONTS_LBA ), + VDISK_DIRECTORY_REGION ( "Resources", vdisk_resources, + VDISK_RESOURCES_LBA ), + VDISK_DIRECTORY_REGION ( "EFI", vdisk_efi, VDISK_EFI_LBA ), + VDISK_DIRECTORY_REGION ( "Microsoft", vdisk_microsoft, + VDISK_MICROSOFT_LBA ), +}; + +/** + * Read from virtual disk + * + * @v lba Starting LBA + * @v count Number of blocks to read + * @v data Data buffer + */ +void vdisk_read ( uint64_t lba, unsigned int count, void *data ) { + struct vdisk_region *region; + void ( * build ) ( uint64_t lba, unsigned int count, void *data ); + const char *name; + uint64_t start = lba; + uint64_t end = ( lba + count ); + uint64_t frag_start = start; + uint64_t frag_end; + int file_idx; + uint64_t file_end; + uint64_t region_start; + uint64_t region_end; + unsigned int frag_count; + unsigned int i; + + DBG2 ( "Read to %p from %#llx+%#x: ", data, lba, count ); + + do { + /* Initialise fragment to fill remaining space */ + frag_end = end; + name = NULL; + build = NULL; + + /* Truncate fragment and generate data */ + file_idx = VDISK_FILE_IDX ( frag_start ); + if ( file_idx >= 0 ) { + + /* Truncate fragment to end of file */ + file_end = VDISK_FILE_LBA ( file_idx + 1 ); + if ( frag_end > file_end ) + frag_end = file_end; + + /* Generate data from file */ + if ( file_idx < VDISK_MAX_FILES ) { + name = vdisk_files[file_idx].name; + build = vdisk_file; + } + + } else { + + /* Truncate fragment to region boundaries */ + for ( i = 0 ; i < ( sizeof ( vdisk_regions ) / + sizeof ( vdisk_regions[0] ) ); i++){ + region = &vdisk_regions[i]; + region_start = region->lba; + region_end = ( region_start + region->count ); + + /* Avoid crossing start of any region */ + if ( ( frag_start < region_start ) && + ( frag_end > region_start ) ){ + frag_end = region_start; + } + + /* Ignore unless we overlap with this region */ + if ( ( frag_start >= region_end ) || + ( frag_end <= region_start ) ) { + continue; + } + + /* Avoid crossing end of region */ + if ( frag_end > region_end ) + frag_end = region_end; + + /* Found a suitable region */ + name = region->name; + build = region->build; + break; + } + } + + /* Generate data from this region */ + frag_count = ( frag_end - frag_start ); + DBG2 ( "%s%s (%#x)", ( ( frag_start == start ) ? "" : ", " ), + ( name ? name : "empty" ), frag_count ); + if ( build ) { + build ( frag_start, frag_count, data ); + } else { + memset ( data, 0, ( frag_count * VDISK_SECTOR_SIZE ) ); + } + + /* Move to next fragment */ + frag_start += frag_count; + data += ( frag_count * VDISK_SECTOR_SIZE ); + + } while ( frag_start != end ); + + DBG2 ( "\n" ); +} + +/** + * Add file to virtual disk + * + * @v name Name + * @v opaque Opaque token + * @v len Length + * @v read Read data method + * @ret file Virtual file + */ +struct vdisk_file * vdisk_add_file ( const char *name, void *opaque, size_t len, + void ( * read ) ( struct vdisk_file *file, + void *data, + size_t offset, + size_t len ) ) { + static unsigned int index = 0; + struct vdisk_file *file; + + /* Sanity check */ + if ( index >= VDISK_MAX_FILES ) + die ( "Too many files\n" ); + + /* Store file */ + file = &vdisk_files[index++]; + snprintf ( file->name, sizeof ( file->name ), "%s", name ); + file->opaque = opaque; + file->len = len; + file->xlen = len; + file->read = read; + DBG ( "Using %s via %p len %#zx\n", file->name, file->opaque, + file->len ); + + return file; +} + +/** + * Patch virtual file + * + * @v file Virtual file + * @v patch Patch method + */ +void vdisk_patch_file ( struct vdisk_file *file, + void ( * patch ) ( struct vdisk_file *file, void *data, + size_t offset, size_t len ) ) { + + /* Record patch method */ + file->patch = patch; + + /* Allow patch method to update file length */ + patch ( file, NULL, 0, 0 ); +} diff --git a/wimboot/wimboot-2.7.3/src/vdisk.h b/wimboot/wimboot-2.7.3/src/vdisk.h new file mode 100644 index 00000000..7cae51c7 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/vdisk.h @@ -0,0 +1,623 @@ +#ifndef _VDISK_H +#define _VDISK_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Virtual disk emulation + * + */ + +#include + +/** Number of cylinders */ +#define VDISK_CYLINDERS 1024 /* Maximum possible */ + +/** Number of heads */ +#define VDISK_HEADS 255 + +/** Number of sectors per track */ +#define VDISK_SECTORS_PER_TRACK 63 + +/** Sector size (in bytes) */ +#define VDISK_SECTOR_SIZE 512 + +/** Partition start LBA */ +#define VDISK_PARTITION_LBA 128 + +/** Cluster size (in sectors) */ +#define VDISK_CLUSTER_COUNT 64 + +/** Cluster size (in bytes) */ +#define VDISK_CLUSTER_SIZE ( VDISK_CLUSTER_COUNT * VDISK_SECTOR_SIZE ) + +/** Number of clusters */ +#define VDISK_CLUSTERS 0x03ffc000ULL /* Fill 2TB disk */ + +/** Maximum number of virtual files + * + * The total number of files must be strictly less than the number of + * sectors per cluster. + */ +#define VDISK_MAX_FILES ( VDISK_CLUSTER_COUNT - 1 ) + +/** Maximum file size (in sectors) */ +#define VDISK_FILE_COUNT 0x800000UL /* max for 32-bit address space */ + +/** Maximum file size (in clusters) */ +#define VDISK_FILE_CLUSTERS ( VDISK_FILE_COUNT / VDISK_CLUSTER_COUNT ) + +/** File starting LBA */ +#define VDISK_FILE_LBA( idx ) ( ( (idx) + 1 ) * VDISK_FILE_COUNT ) + +/** File index from LBA */ +#define VDISK_FILE_IDX( lba ) ( ( (lba) / VDISK_FILE_COUNT ) - 1 ) + +/** File offset (in bytes) from LBA */ +#define VDISK_FILE_OFFSET( lba ) \ + ( ( (lba) % VDISK_FILE_COUNT ) * VDISK_SECTOR_SIZE ) + +/** File index from directory entry LBA */ +#define VDISK_FILE_DIRENT_IDX( lba ) ( ( (lba) - 1 ) % VDISK_CLUSTER_COUNT ) + +/** Number of sectors allocated for FAT */ +#define VDISK_SECTORS_PER_FAT \ + ( ( ( VDISK_CLUSTERS * sizeof ( uint32_t ) + \ + VDISK_CLUSTER_SIZE - 1 ) / VDISK_CLUSTER_SIZE ) \ + * VDISK_CLUSTER_COUNT ) + +/** Number of reserved sectors */ +#define VDISK_RESERVED_COUNT VDISK_CLUSTER_COUNT + +/** Starting cluster number for file */ +#define VDISK_FILE_CLUSTER( idx ) \ + ( ( ( ( VDISK_FILE_COUNT - VDISK_PARTITION_LBA - \ + VDISK_RESERVED_COUNT - VDISK_SECTORS_PER_FAT ) / \ + VDISK_CLUSTER_COUNT ) + 2 ) + \ + ( (idx) * VDISK_FILE_CLUSTERS ) ) + +/** Total number of sectors within partition */ +#define VDISK_PARTITION_COUNT \ + ( VDISK_RESERVED_COUNT + VDISK_SECTORS_PER_FAT + \ + ( VDISK_CLUSTERS * VDISK_CLUSTER_COUNT ) ) + +/** Number of sectors */ +#define VDISK_COUNT ( VDISK_PARTITION_LBA + VDISK_PARTITION_COUNT ) + +/** Calculate sector from cluster */ +#define VDISK_CLUSTER_SECTOR( cluster ) \ + ( ( ( (cluster) - 2 ) * VDISK_CLUSTER_COUNT ) + \ + VDISK_RESERVED_COUNT + VDISK_SECTORS_PER_FAT ) + +/***************************************************************************** + * + * Master Boot Record + * + ***************************************************************************** + */ + +/** Master Boot Record LBA */ +#define VDISK_MBR_LBA 0x00000000 + +/** Master Boot Record sector count */ +#define VDISK_MBR_COUNT 1 + +/** Partition table entry */ +struct vdisk_partition { + /** Bootable flag */ + uint8_t bootable; + /** C/H/S start address */ + uint8_t chs_start[3]; + /** System indicator (partition type) */ + uint8_t type; + /** C/H/S end address */ + uint8_t chs_end[3]; + /** Linear start address */ + uint32_t start; + /** Linear length */ + uint32_t length; +} __attribute__ (( packed )); + +/** Master Boot Record */ +struct vdisk_mbr { + /** Code area */ + uint8_t code[440]; + /** Disk signature */ + uint32_t signature; + /** Padding */ + uint8_t pad[2]; + /** Partition table */ + struct vdisk_partition partitions[4]; + /** 0x55aa signature */ + uint16_t magic; +} __attribute__ (( packed )); + +/** MBR boot partition indiciator */ +#define VDISK_MBR_BOOTABLE 0x80 + +/** MBR type indicator for FAT32 */ +#define VDISK_MBR_TYPE_FAT32 0x0c + +/** MBR signature */ +#define VDISK_MBR_SIGNATURE 0xc0ffeeee + +/** MBR magic */ +#define VDISK_MBR_MAGIC 0xaa55 + +/***************************************************************************** + * + * Volume Boot Record + * + ***************************************************************************** + */ + +/** Volume Boot Record LBA */ +#define VDISK_VBR_LBA VDISK_PARTITION_LBA + +/** Volume Boot Record sector count */ +#define VDISK_VBR_COUNT 1 + +/** Volume Boot Record */ +struct vdisk_vbr { + /** Jump instruction */ + uint8_t jump[3]; + /** OEM identifier */ + char oemid[8]; + /** Number of bytes per sector */ + uint16_t bytes_per_sector; + /** Number of sectors per cluster */ + uint8_t sectors_per_cluster; + /** Number of reserved sectors */ + uint16_t reserved_sectors; + /** Number of FATs */ + uint8_t fats; + /** Number of root directory entries (FAT12/FAT16 only) */ + uint16_t root_directory_entries; + /** Total number of sectors (0 if more than 65535) */ + uint16_t sectors_short; + /** Media descriptor type */ + uint8_t media; + /** Number of sectors per FAT (FAT12/FAT16 only) */ + uint16_t sectors_per_fat_short; + /** Number of sectors per track */ + uint16_t sectors_per_track; + /** Number of heads */ + uint16_t heads; + /** Number of hidden sectors (i.e. LBA of start of partition) */ + uint32_t hidden_sectors; + /** Total number of sectors */ + uint32_t sectors; + + /* FAT32-specific fields */ + + /** Sectors per FAT */ + uint32_t sectors_per_fat; + /** Flags */ + uint16_t flags; + /** FAT version number */ + uint16_t version; + /** Root directory cluster */ + uint32_t root; + /** FSInfo sector */ + uint16_t fsinfo; + /** Backup boot sector */ + uint16_t backup; + /** Reserved */ + uint8_t reserved[12]; + /** Drive number */ + uint8_t drive; + /** Windows NT flags */ + uint8_t nt_flags; + /** Signature */ + uint8_t signature; + /** Volume ID serial */ + uint32_t serial; + /** Label (space-padded) */ + char label[11]; + /** System identifier */ + char system[8]; + /** Boot code */ + uint8_t code[420]; + /** 0x55aa signature */ + uint16_t magic; +} __attribute__ (( packed )); + +/** VBR jump instruction + * + * bootmgr.exe will actually fail unless this is present. Someone + * must read specification documents without bothering to understand + * what's really happening. + */ +#define VDISK_VBR_JUMP_WTF_MS 0xe9 + +/** VBR OEM ID */ +#define VDISK_VBR_OEMID "wimboot\0" + +/** VBR media type */ +#define VDISK_VBR_MEDIA 0xf8 + +/** VBR signature */ +#define VDISK_VBR_SIGNATURE 0x29 + +/** VBR serial number */ +#define VDISK_VBR_SERIAL 0xf00df00d + +/** VBR label */ +#define VDISK_VBR_LABEL "wimboot " + +/** VBR system identifier */ +#define VDISK_VBR_SYSTEM "FAT32 " + +/** VBR magic */ +#define VDISK_VBR_MAGIC 0xaa55 + +/***************************************************************************** + * + * FSInfo + * + ***************************************************************************** + */ + +/** FSInfo sector */ +#define VDISK_FSINFO_SECTOR 0x00000001 + +/** FSInfo LBA */ +#define VDISK_FSINFO_LBA ( VDISK_VBR_LBA + VDISK_FSINFO_SECTOR ) + +/** FSInfo sector count */ +#define VDISK_FSINFO_COUNT 1 + +/** FSInfo */ +struct vdisk_fsinfo { + /** First signature */ + uint32_t magic1; + /** Reserved */ + uint8_t reserved_1[480]; + /** Second signature */ + uint32_t magic2; + /** Free cluster count */ + uint32_t free_count; + /** Next free cluster */ + uint32_t next_free; + /** Reserved */ + uint8_t reserved_2[12]; + /** Third signature */ + uint32_t magic3; +} __attribute__ (( packed )); + +/** FSInfo first signature */ +#define VDISK_FSINFO_MAGIC1 0x41615252 + +/** FSInfo second signature */ +#define VDISK_FSINFO_MAGIC2 0x61417272 + +/** FSInfo next free cluster */ +#define VDISK_FSINFO_NEXT_FREE 0xffffffff /* No free clusters */ + +/** FSInfo third signature */ +#define VDISK_FSINFO_MAGIC3 0xaa550000 + +/***************************************************************************** + * + * Backup Volume Boot Record + * + ***************************************************************************** + */ + +/** Backup Volume Boot Record sector */ +#define VDISK_BACKUP_VBR_SECTOR 0x00000006 + +/** Backup Volume Boot Record LBA */ +#define VDISK_BACKUP_VBR_LBA ( VDISK_VBR_LBA + VDISK_BACKUP_VBR_SECTOR ) + +/** Backup Volume Boot Record sector count */ +#define VDISK_BACKUP_VBR_COUNT 1 + +/***************************************************************************** + * + * File Allocation Table + * + ***************************************************************************** + */ + +/** FAT sector */ +#define VDISK_FAT_SECTOR VDISK_RESERVED_COUNT + +/** FAT LBA */ +#define VDISK_FAT_LBA ( VDISK_VBR_LBA + VDISK_FAT_SECTOR ) + +/** FAT sector count */ +#define VDISK_FAT_COUNT VDISK_SECTORS_PER_FAT + +/** FAT end marker */ +#define VDISK_FAT_END_MARKER 0x0ffffff8 + +/***************************************************************************** + * + * Directory entries + * + ***************************************************************************** + */ + +/** An 8.3 filename record */ +struct vdisk_short_filename { + /** Filename */ + union { + /** Structured 8.3 base name and extension */ + struct { + /** Base name */ + char base[8]; + /** Extension */ + char ext[3]; + } __attribute__ (( packed )); + /** Raw bytes */ + uint8_t raw[11]; + } filename; + /** Attributes */ + uint8_t attr; + /** Reserved */ + uint8_t reserved; + /** Creation time in tenths of a second */ + uint8_t created_deciseconds; + /** Creation time (HMS packed) */ + uint16_t created_time; + /** Creation date (YMD packed) */ + uint16_t created_date; + /** Last accessed date (YMD packed) */ + uint16_t accessed_date; + /** High 16 bits of starting cluster number */ + uint16_t cluster_high; + /** Modification time (HMS packed) */ + uint16_t modified_time; + /** Modification date (YMD packed) */ + uint16_t modified_date; + /** Low 16 bits of starting cluster number */ + uint16_t cluster_low; + /** Size */ + uint32_t size; +} __attribute__ (( packed )); + +/** A long filename record */ +struct vdisk_long_filename { + /** Sequence number */ + uint8_t sequence; + /** Name characters */ + uint16_t name_1[5]; + /** Attributes */ + uint8_t attr; + /** Type */ + uint8_t type; + /** Checksum of 8.3 name */ + uint8_t checksum; + /** Name characters */ + uint16_t name_2[6]; + /** Reserved */ + uint16_t reserved; + /** Name characters */ + uint16_t name_3[2]; +} __attribute__ (( packed )); + +/** Directory entry attributes */ +enum vdisk_directory_entry_attributes { + VDISK_READ_ONLY = 0x01, + VDISK_HIDDEN = 0x02, + VDISK_SYSTEM = 0x04, + VDISK_VOLUME_LABEL = 0x08, + VDISK_DIRECTORY = 0x10, +}; + +/** Long filename end-of-sequence marker */ +#define VDISK_LFN_END 0x40 + +/** Long filename attributes */ +#define VDISK_LFN_ATTR \ + ( VDISK_READ_ONLY | VDISK_HIDDEN | VDISK_SYSTEM | VDISK_VOLUME_LABEL ) + +/** A directory entry */ +union vdisk_directory_entry { + /** Deleted file marker */ + uint8_t deleted; + /** 8.3 filename */ + struct vdisk_short_filename dos; + /** Long filename */ + struct vdisk_long_filename lfn; +} __attribute__ (( packed )); + +/** Magic marker for deleted files */ +#define VDISK_DIRENT_DELETED 0xe5 + +/** Number of directory entries per sector */ +#define VDISK_DIRENT_PER_SECTOR \ + ( VDISK_SECTOR_SIZE / \ + sizeof ( union vdisk_directory_entry ) ) + +/** A directory sector */ +struct vdisk_directory { + /** Entries */ + union vdisk_directory_entry entry[VDISK_DIRENT_PER_SECTOR]; +} __attribute__ (( packed )); + +/***************************************************************************** + * + * Root directory + * + ***************************************************************************** + */ + +/** Root directory cluster */ +#define VDISK_ROOT_CLUSTER 2 + +/** Root directory sector */ +#define VDISK_ROOT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_ROOT_CLUSTER ) + +/** Root directory LBA */ +#define VDISK_ROOT_LBA ( VDISK_VBR_LBA + VDISK_ROOT_SECTOR ) + +/***************************************************************************** + * + * Boot directory + * + ***************************************************************************** + */ + +/** Boot directory cluster */ +#define VDISK_BOOT_CLUSTER 3 + +/** Boot directory sector */ +#define VDISK_BOOT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_BOOT_CLUSTER ) + +/** Boot directory LBA */ +#define VDISK_BOOT_LBA ( VDISK_VBR_LBA + VDISK_BOOT_SECTOR ) + +/***************************************************************************** + * + * Sources directory + * + ***************************************************************************** + */ + +/** Sources directory cluster */ +#define VDISK_SOURCES_CLUSTER 4 + +/** Sources directory sector */ +#define VDISK_SOURCES_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_SOURCES_CLUSTER ) + +/** Sources directory LBA */ +#define VDISK_SOURCES_LBA ( VDISK_VBR_LBA + VDISK_SOURCES_SECTOR ) + +/***************************************************************************** + * + * Fonts directory + * + ***************************************************************************** + */ + +/** Fonts directory cluster */ +#define VDISK_FONTS_CLUSTER 5 + +/** Fonts directory sector */ +#define VDISK_FONTS_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_FONTS_CLUSTER ) + +/** Fonts directory LBA */ +#define VDISK_FONTS_LBA ( VDISK_VBR_LBA + VDISK_FONTS_SECTOR ) + +/***************************************************************************** + * + * Resources directory + * + ***************************************************************************** + */ + +/** Resources directory cluster */ +#define VDISK_RESOURCES_CLUSTER 6 + +/** Resources directory sector */ +#define VDISK_RESOURCES_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_RESOURCES_CLUSTER ) + +/** Resources directory LBA */ +#define VDISK_RESOURCES_LBA ( VDISK_VBR_LBA + VDISK_RESOURCES_SECTOR ) + +/***************************************************************************** + * + * EFI directory + * + ***************************************************************************** + */ + +/** EFI directory cluster */ +#define VDISK_EFI_CLUSTER 7 + +/** EFI directory sector */ +#define VDISK_EFI_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_EFI_CLUSTER ) + +/** EFI directory LBA */ +#define VDISK_EFI_LBA ( VDISK_VBR_LBA + VDISK_EFI_SECTOR ) + +/***************************************************************************** + * + * Microsoft directory + * + ***************************************************************************** + */ + +/** Microsoft directory cluster */ +#define VDISK_MICROSOFT_CLUSTER 8 + +/** Microsoft directory sector */ +#define VDISK_MICROSOFT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_MICROSOFT_CLUSTER ) + +/** Microsoft directory LBA */ +#define VDISK_MICROSOFT_LBA ( VDISK_VBR_LBA + VDISK_MICROSOFT_SECTOR ) + +/***************************************************************************** + * + * Files + * + ***************************************************************************** + */ + +/** Maximum virtual filename length (excluding NUL) */ +#define VDISK_NAME_LEN 31 + +/** A virtual file */ +struct vdisk_file { + /** Filename */ + char name[ VDISK_NAME_LEN + 1 /* NUL */ ]; + /** Opaque token */ + void *opaque; + /** Length (excluding any zero-padding) */ + size_t len; + /** Length (including any zero-padding) */ + size_t xlen; + /** Read data + * + * @v file Virtual file + * @v data Data buffer + * @v offset Starting offset + * @v len Length + */ + void ( * read ) ( struct vdisk_file *file, void *data, size_t offset, + size_t len ); + /** Patch data (optional) + * + * @v file Virtual file + * @v data Data buffer + * @v offset Starting offset + * @v len Length + */ + void ( * patch ) ( struct vdisk_file *file, void *data, size_t offset, + size_t len ); +}; + +extern struct vdisk_file vdisk_files[VDISK_MAX_FILES]; + +extern void vdisk_read ( uint64_t lba, unsigned int count, void *data ); +extern struct vdisk_file * +vdisk_add_file ( const char *name, void *opaque, size_t len, + void ( * read ) ( struct vdisk_file *file, void *data, + size_t offset, size_t len ) ); +extern void +vdisk_patch_file ( struct vdisk_file *file, + void ( * patch ) ( struct vdisk_file *file, void *data, + size_t offset, size_t len ) ); + +#endif /* _VDISK_H */ diff --git a/wimboot/wimboot-2.7.3/src/vsprintf.c b/wimboot/wimboot-2.7.3/src/vsprintf.c new file mode 100644 index 00000000..ad304693 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/vsprintf.c @@ -0,0 +1,12 @@ +/* + * Quick and dirty wrapper around iPXE's unmodified vsprintf.c + * + */ + +#include +#include +#include "wimboot.h" + +#define FILE_LICENCE(x) + +#include "ipxe/vsprintf.c" diff --git a/wimboot/wimboot-2.7.3/src/wchar.h b/wimboot/wimboot-2.7.3/src/wchar.h new file mode 100644 index 00000000..e7639e68 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wchar.h @@ -0,0 +1,56 @@ +#ifndef _WCHAR_H +#define _WCHAR_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Wide characters + * + */ + +#include + +typedef void mbstate_t; + +/** + * Convert wide character to multibyte sequence + * + * @v buf Buffer + * @v wc Wide character + * @v ps Shift state + * @ret len Number of characters written + * + * This is a stub implementation, sufficient to handle basic ASCII + * characters. + */ +static inline size_t wcrtomb ( char *buf, wchar_t wc, + mbstate_t *ps __attribute__ (( unused )) ) { + *buf = wc; + return 1; +} + +extern int wcscasecmp ( const wchar_t *str1, const wchar_t *str2 ); +extern size_t wcslen ( const wchar_t *str ); +extern wchar_t * wcschr ( const wchar_t *str, wchar_t c ); +extern char *strchr(const char *str, char c); + +#endif /* _WCHAR_H */ diff --git a/wimboot/wimboot-2.7.3/src/wctype.h b/wimboot/wimboot-2.7.3/src/wctype.h new file mode 100644 index 00000000..de70735c --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wctype.h @@ -0,0 +1,53 @@ +#ifndef _WCTYPE_H +#define _WCTYPE_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Wide character types + * + * We don't actually care about wide characters. Internationalisation + * is a user interface concern, and has absolutely no place in the + * boot process. However, UEFI uses wide characters and so we have to + * at least be able to handle the ASCII subset of UCS-2. + * + */ + +#include + +static inline int iswlower ( wint_t c ) { + return islower ( c ); +} + +static inline int iswupper ( wint_t c ) { + return isupper ( c ); +} + +static inline int towupper ( wint_t c ) { + return toupper ( c ); +} + +static inline int iswspace ( wint_t c ) { + return isspace ( c ); +} + +#endif /* _WCTYPE_H */ diff --git a/wimboot/wimboot-2.7.3/src/wim.c b/wimboot/wimboot-2.7.3/src/wim.c new file mode 100644 index 00000000..614305ca --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wim.c @@ -0,0 +1,544 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM images + * + */ + +#include +#include +#include +#include +#include +#include "wimboot.h" +#include "vdisk.h" +#include "lzx.h" +#include "wim.h" + +/** WIM chunk buffer */ +static struct wim_chunk_buffer wim_chunk_buffer; + +/** + * Get WIM header + * + * @v file Virtual file + * @v header WIM header to fill in + * @ret rc Return status code + */ +int wim_header ( struct vdisk_file *file, struct wim_header *header ) { + + /* Sanity check */ + if ( sizeof ( *header ) > file->len ) { + DBG ( "WIM file too short (%#zx bytes)\n", file->len ); + return -1; + } + + /* Read WIM header */ + file->read ( file, header, 0, sizeof ( *header ) ); + + return 0; +} + +/** + * Get compressed chunk offset + * + * @v file Virtual file + * @v resource Resource + * @v chunk Chunk number + * @v offset Offset to fill in + * @ret rc Return status code + */ +static int wim_chunk_offset ( struct vdisk_file *file, + struct wim_resource_header *resource, + unsigned int chunk, size_t *offset ) { + size_t zlen = ( resource->zlen__flags & WIM_RESHDR_ZLEN_MASK ); + unsigned int chunks; + size_t offset_offset; + size_t offset_len; + size_t chunks_len; + union { + uint32_t offset_32; + uint64_t offset_64; + } u; + + /* Special case: zero-length files have no chunks */ + if ( ! resource->len ) { + *offset = 0; + return 0; + } + + /* Calculate chunk parameters */ + chunks = ( ( resource->len + WIM_CHUNK_LEN - 1 ) / WIM_CHUNK_LEN ); + offset_len = ( ( resource->len > 0xffffffffULL ) ? + sizeof ( u.offset_64 ) : sizeof ( u.offset_32 ) ); + chunks_len = ( ( chunks - 1 ) * offset_len ); + + /* Sanity check */ + if ( chunks_len > zlen ) { + DBG ( "Resource too short for %d chunks\n", chunks ); + return -1; + } + + /* Special case: chunk 0 has no offset field */ + if ( ! chunk ) { + *offset = chunks_len; + return 0; + } + + /* Treat out-of-range chunks as being at the end of the + * resource, to allow for length calculation on the final + * chunk. + */ + if ( chunk >= chunks ) { + *offset = zlen; + return 0; + } + + /* Otherwise, read the chunk offset */ + offset_offset = ( ( chunk - 1 ) * offset_len ); + file->read ( file, &u, ( resource->offset + offset_offset ), + offset_len ); + *offset = ( chunks_len + ( ( offset_len == sizeof ( u.offset_64 ) ) ? + u.offset_64 : u.offset_32 ) ); + if ( *offset > zlen ) { + DBG ( "Chunk %d offset lies outside resource\n", chunk ); + return -1; + } + return 0; +} + +/** + * Read chunk from a compressed resource + * + * @v file Virtual file + * @v header WIM header + * @v resource Resource + * @v chunk Chunk number + * @v buf Chunk buffer + * @ret rc Return status code + */ +static int wim_chunk ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *resource, + unsigned int chunk, struct wim_chunk_buffer *buf ) { + ssize_t ( * decompress ) ( const void *data, size_t len, void *buf ); + unsigned int chunks; + size_t offset; + size_t next_offset; + size_t len; + size_t expected_out_len; + ssize_t out_len; + int rc; + + /* Get chunk compressed data offset and length */ + if ( ( rc = wim_chunk_offset ( file, resource, chunk, + &offset ) ) != 0 ) + return rc; + if ( ( rc = wim_chunk_offset ( file, resource, ( chunk + 1 ), + &next_offset ) ) != 0 ) + return rc; + len = ( next_offset - offset ); + + /* Calculate uncompressed length */ + assert ( resource->len > 0 ); + chunks = ( ( resource->len + WIM_CHUNK_LEN - 1 ) / WIM_CHUNK_LEN ); + expected_out_len = WIM_CHUNK_LEN; + if ( chunk >= ( chunks - 1 ) ) + expected_out_len -= ( -resource->len & ( WIM_CHUNK_LEN - 1 ) ); + + /* Read possibly-compressed data */ + if ( len == expected_out_len ) { + + /* Chunk did not compress; read raw data */ + file->read ( file, buf->data, ( resource->offset + offset ), + len ); + + } else { + uint8_t zbuf[len]; + + /* Read compressed data into a temporary buffer */ + file->read ( file, zbuf, ( resource->offset + offset ), len ); + + /* Identify decompressor */ + if ( header->flags & WIM_HDR_LZX ) { + decompress = lzx_decompress; + } else { + DBG ( "Can't handle unknown compression scheme %#08x " + "for %#llx chunk %d at [%#llx+%#llx)\n", + header->flags, resource->offset, + chunk, ( resource->offset + offset ), + ( resource->offset + offset + len ) ); + return -1; + } + + /* Decompress data */ + out_len = decompress ( zbuf, len, NULL ); + if ( out_len < 0 ) + return out_len; + if ( ( ( size_t ) out_len ) != expected_out_len ) { + DBG ( "Unexpected output length %#lx (expected %#zx)\n", + out_len, expected_out_len ); + return -1; + } + decompress ( zbuf, len, buf->data ); + } + + return 0; +} + +/** + * Read from a (possibly compressed) resource + * + * @v file Virtual file + * @v header WIM header + * @v resource Resource + * @v data Data buffer + * @v offset Starting offset + * @v len Length + * @ret rc Return status code + */ +int wim_read ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *resource, void *data, + size_t offset, size_t len ) { + static struct vdisk_file *cached_file; + static size_t cached_resource_offset; + static unsigned int cached_chunk; + size_t zlen = ( resource->zlen__flags & WIM_RESHDR_ZLEN_MASK ); + unsigned int chunk; + size_t skip_len; + size_t frag_len; + int rc; + + /* Sanity checks */ + if ( ( offset + len ) > resource->len ) { + DBG ( "Resource too short (%#llx bytes)\n", resource->len ); + return -1; + } + if ( ( resource->offset + zlen ) > file->len ) { + DBG ( "Resource exceeds length of file\n" ); + return -1; + } + + /* If resource is uncompressed, just read the raw data */ + if ( ! ( resource->zlen__flags & ( WIM_RESHDR_COMPRESSED | + WIM_RESHDR_PACKED_STREAMS ) ) ) { + file->read ( file, data, ( resource->offset + offset ), len ); + return 0; + } + + /* Read from each chunk overlapping the target region */ + while ( len ) { + + /* Calculate chunk number */ + chunk = ( offset / WIM_CHUNK_LEN ); + + /* Read chunk, if not already cached */ + if ( ( file != cached_file ) || + ( resource->offset != cached_resource_offset ) || + ( chunk != cached_chunk ) ) { + + /* Read chunk */ + if ( ( rc = wim_chunk ( file, header, resource, chunk, + &wim_chunk_buffer ) ) != 0 ) + return rc; + + /* Update cache */ + cached_file = file; + cached_resource_offset = resource->offset; + cached_chunk = chunk; + } + + /* Copy fragment from this chunk */ + skip_len = ( offset % WIM_CHUNK_LEN ); + frag_len = ( WIM_CHUNK_LEN - skip_len ); + if ( frag_len > len ) + frag_len = len; + memcpy ( data, ( wim_chunk_buffer.data + skip_len ), frag_len ); + + /* Move to next chunk */ + data += frag_len; + offset += frag_len; + len -= frag_len; + } + + return 0; +} + +/** + * Get number of images + * + * @v file Virtual file + * @v header WIM header + * @v count Count of images to fill in + * @ret rc Return status code + */ +int wim_count ( struct vdisk_file *file, struct wim_header *header, + unsigned int *count ) { + struct wim_lookup_entry entry; + size_t offset; + int rc; + + /* Count metadata entries */ + for ( offset = 0 ; ( offset + sizeof ( entry ) ) <= header->lookup.len ; + offset += sizeof ( entry ) ) { + + /* Read entry */ + if ( ( rc = wim_read ( file, header, &header->lookup, &entry, + offset, sizeof ( entry ) ) ) != 0 ) + return rc; + + /* Check for metadata entries */ + if ( entry.resource.zlen__flags & WIM_RESHDR_METADATA ) { + (*count)++; + DBG2 ( "...found image %d metadata at +%#zx\n", + *count, offset ); + } + } + + return 0; +} + +/** + * Get WIM image metadata + * + * @v file Virtual file + * @v header WIM header + * @v index Image index, or 0 to use boot image + * @v meta Metadata to fill in + * @ret rc Return status code + */ +int wim_metadata ( struct vdisk_file *file, struct wim_header *header, + unsigned int index, struct wim_resource_header *meta ) { + struct wim_lookup_entry entry; + size_t offset; + unsigned int found = 0; + int rc; + + /* If no image index is specified, just use the boot metadata */ + if ( index == 0 ) { + memcpy ( meta, &header->boot, sizeof ( *meta ) ); + return 0; + } + + /* Look for metadata entry */ + for ( offset = 0 ; ( offset + sizeof ( entry ) ) <= header->lookup.len ; + offset += sizeof ( entry ) ) { + + /* Read entry */ + if ( ( rc = wim_read ( file, header, &header->lookup, &entry, + offset, sizeof ( entry ) ) ) != 0 ) + return rc; + + /* Look for our target entry */ + if ( entry.resource.zlen__flags & WIM_RESHDR_METADATA ) { + found++; + DBG2 ( "...found image %d metadata at +%#zx\n", + found, offset ); + if ( found == index ) { + memcpy ( meta, &entry.resource, + sizeof ( *meta ) ); + return 0; + } + } + } + + /* Fail if index was not found */ + DBG ( "Cannot find WIM image index %d in %s\n", index, file->name ); + return -1; +} + +/** + * Get directory entry + * + * @v file Virtual file + * @v header WIM header + * @v meta Metadata + * @v name Name + * @v offset Directory offset (will be updated) + * @v direntry Directory entry to fill in + * @ret rc Return status code + */ +static int wim_direntry ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, + const wchar_t *name, size_t *offset, + struct wim_directory_entry *direntry ) { + wchar_t name_buf[ wcslen ( name ) + 1 /* NUL */ ]; + int rc; + + /* Search directory */ + for ( ; ; *offset += direntry->len ) { + + /* Read length field */ + if ( ( rc = wim_read ( file, header, meta, direntry, *offset, + sizeof ( direntry->len ) ) ) != 0 ) + return rc; + + /* Check for end of this directory */ + if ( ! direntry->len ) { + DBG ( "...directory entry \"%ls\" not found\n", name ); + return -1; + } + + /* Read fixed-length portion of directory entry */ + if ( ( rc = wim_read ( file, header, meta, direntry, *offset, + sizeof ( *direntry ) ) ) != 0 ) + return rc; + + /* Check name length */ + if ( direntry->name_len > sizeof ( name_buf ) ) + continue; + + /* Read name */ + if ( ( rc = wim_read ( file, header, meta, &name_buf, + ( *offset + sizeof ( *direntry ) ), + sizeof ( name_buf ) ) ) != 0 ) + return rc; + + /* Check name */ + if ( wcscasecmp ( name, name_buf ) != 0 ) + continue; + + DBG2 ( "...found entry \"%ls\"\n", name ); + return 0; + } +} + +/** + * Get directory entry for a path + * + * @v file Virtual file + * @v header WIM header + * @v meta Metadata + * @v path Path to file/directory + * @v offset Directory entry offset to fill in + * @v direntry Directory entry to fill in + * @ret rc Return status code + */ +int wim_path ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, const wchar_t *path, + size_t *offset, struct wim_directory_entry *direntry ) { + wchar_t path_copy[ wcslen ( path ) + 1 /* WNUL */ ]; + struct wim_security_header security; + wchar_t *name; + wchar_t *next; + int rc; + + /* Read security data header */ + if ( ( rc = wim_read ( file, header, meta, &security, 0, + sizeof ( security ) ) ) != 0 ) + return rc; + + /* Get root directory offset */ + direntry->subdir = ( ( security.len + sizeof ( uint64_t ) - 1 ) & + ~( sizeof ( uint64_t ) - 1 ) ); + + /* Find directory entry */ + name = memcpy ( path_copy, path, sizeof ( path_copy ) ); + do { + next = wcschr ( name, L'\\' ); + if ( next ) + *next = L'\0'; + *offset = direntry->subdir; + if ( ( rc = wim_direntry ( file, header, meta, name, offset, + direntry ) ) != 0 ) + return rc; + name = ( next + 1 ); + } while ( next ); + + return 0; +} + +/** + * Get file resource + * + * @v file Virtual file + * @v header WIM header + * @v meta Metadata + * @v path Path to file + * @v resource File resource to fill in + * @ret rc Return status code + */ +int wim_file ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, const wchar_t *path, + struct wim_resource_header *resource ) { + struct wim_directory_entry direntry; + struct wim_lookup_entry entry; + size_t offset; + int rc; + + /* Find directory entry */ + if ( ( rc = wim_path ( file, header, meta, path, &offset, + &direntry ) ) != 0 ) + return rc; + + /* File matching file entry */ + for ( offset = 0 ; ( offset + sizeof ( entry ) ) <= header->lookup.len ; + offset += sizeof ( entry ) ) { + + /* Read entry */ + if ( ( rc = wim_read ( file, header, &header->lookup, &entry, + offset, sizeof ( entry ) ) ) != 0 ) + return rc; + + /* Look for our target entry */ + if ( memcmp ( &entry.hash, &direntry.hash, + sizeof ( entry.hash ) ) == 0 ) { + DBG ( "...found file \"%ls\"\n", path ); + memcpy ( resource, &entry.resource, + sizeof ( *resource ) ); + return 0; + } + } + + DBG ( "Cannot find file %ls\n", path ); + return -1; +} + +/** + * Get length of a directory + * + * @v file Virtual file + * @v header WIM header + * @v meta Metadata + * @v offset Directory offset + * @v len Directory length to fill in (excluding terminator) + * @ret rc Return status code + */ +int wim_dir_len ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, size_t offset, + size_t *len ) { + struct wim_directory_entry direntry; + int rc; + + /* Search directory */ + for ( *len = 0 ; ; *len += direntry.len ) { + + /* Read length field */ + if ( ( rc = wim_read ( file, header, meta, &direntry, + ( offset + *len ), + sizeof ( direntry.len ) ) ) != 0 ) + return rc; + + /* Check for end of this directory */ + if ( ! direntry.len ) + return 0; + } +} diff --git a/wimboot/wimboot-2.7.3/src/wim.h b/wimboot/wimboot-2.7.3/src/wim.h new file mode 100644 index 00000000..7ef95d60 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wim.h @@ -0,0 +1,196 @@ +#ifndef _WIM_H +#define _WIM_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM images + * + * The file format is documented in the document "Windows Imaging File + * Format (WIM)", available from + * + * http://www.microsoft.com/en-us/download/details.aspx?id=13096 + * + * The wimlib source code is also a useful reference. + * + */ + +#include + +/** A WIM resource header */ +struct wim_resource_header { + /** Compressed length and flags */ + uint64_t zlen__flags; + /** Offset */ + uint64_t offset; + /** Uncompressed length */ + uint64_t len; +} __attribute__ (( packed )); + +/** WIM resource header length mask */ +#define WIM_RESHDR_ZLEN_MASK 0x00ffffffffffffffULL + +/** WIM resource header flags */ +enum wim_resource_header_flags { + /** Resource contains metadata */ + WIM_RESHDR_METADATA = ( 0x02ULL << 56 ), + /** Resource is compressed */ + WIM_RESHDR_COMPRESSED = ( 0x04ULL << 56 ), + /** Resource is compressed using packed streams */ + WIM_RESHDR_PACKED_STREAMS = ( 0x10ULL << 56 ), +}; + +/** A WIM header */ +struct wim_header { + /** Signature */ + uint8_t signature[8]; + /** Header length */ + uint32_t header_len; + /** Verson */ + uint32_t version; + /** Flags */ + uint32_t flags; + /** Chunk length */ + uint32_t chunk_len; + /** GUID */ + uint8_t guid[16]; + /** Part number */ + uint16_t part; + /** Total number of parts */ + uint16_t parts; + /** Number of images */ + uint32_t images; + /** Lookup table */ + struct wim_resource_header lookup; + /** XML data */ + struct wim_resource_header xml; + /** Boot metadata */ + struct wim_resource_header boot; + /** Boot index */ + uint32_t boot_index; + /** Integrity table */ + struct wim_resource_header integrity; + /** Reserved */ + uint8_t reserved[60]; +} __attribute__ (( packed ));; + +/** WIM header flags */ +enum wim_header_flags { + /** WIM uses Xpress compresson */ + WIM_HDR_XPRESS = 0x00020000, + /** WIM uses LZX compression */ + WIM_HDR_LZX = 0x00040000, +}; + +/** A WIM file hash */ +struct wim_hash { + /** SHA-1 hash */ + uint8_t sha1[20]; +} __attribute__ (( packed )); + +/** A WIM lookup table entry */ +struct wim_lookup_entry { + /** Resource header */ + struct wim_resource_header resource; + /** Part number */ + uint16_t part; + /** Reference count */ + uint32_t refcnt; + /** Hash */ + struct wim_hash hash; +} __attribute__ (( packed )); + +/** WIM chunk length */ +#define WIM_CHUNK_LEN 32768 + +/** A WIM chunk buffer */ +struct wim_chunk_buffer { + /** Data */ + uint8_t data[WIM_CHUNK_LEN]; +}; + +/** Security data */ +struct wim_security_header { + /** Length */ + uint32_t len; + /** Number of entries */ + uint32_t count; +} __attribute__ (( packed )); + +/** Directory entry */ +struct wim_directory_entry { + /** Length */ + uint64_t len; + /** Attributes */ + uint32_t attributes; + /** Security ID */ + uint32_t security; + /** Subdirectory offset */ + uint64_t subdir; + /** Reserved */ + uint8_t reserved1[16]; + /** Creation time */ + uint64_t created; + /** Last access time */ + uint64_t accessed; + /** Last written time */ + uint64_t written; + /** Hash */ + struct wim_hash hash; + /** Reserved */ + uint8_t reserved2[12]; + /** Streams */ + uint16_t streams; + /** Short name length */ + uint16_t short_name_len; + /** Name length */ + uint16_t name_len; +} __attribute__ (( packed )); + +/** Normal file */ +#define WIM_ATTR_NORMAL 0x00000080UL + +/** No security information exists for this file */ +#define WIM_NO_SECURITY 0xffffffffUL + +/** Windows complains if the time fields are left at zero */ +#define WIM_MAGIC_TIME 0x1a7b83d2ad93000ULL + +extern int wim_header ( struct vdisk_file *file, struct wim_header *header ); +extern int wim_count ( struct vdisk_file *file, struct wim_header *header, + unsigned int *count ); +extern int wim_metadata ( struct vdisk_file *file, struct wim_header *header, + unsigned int index, struct wim_resource_header *meta); +extern int wim_read ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *resource, void *data, + size_t offset, size_t len ); +extern int wim_path ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, const wchar_t *path, + size_t *offset, struct wim_directory_entry *direntry ); +extern int wim_file ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, const wchar_t *path, + struct wim_resource_header *resource ); +extern int wim_dir_len ( struct vdisk_file *file, struct wim_header *header, + struct wim_resource_header *meta, size_t offset, + size_t *len ); + +#endif /* _WIM_H */ diff --git a/wimboot/wimboot-2.7.3/src/wimboot.h b/wimboot/wimboot-2.7.3/src/wimboot.h new file mode 100644 index 00000000..7253a62d --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wimboot.h @@ -0,0 +1,159 @@ +#ifndef _WIMBOOT_H +#define _WIMBOOT_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * WIM boot loader + * + */ + +/** Debug switch */ +#ifndef DEBUG +#define DEBUG 1 +#endif + +/** Base segment address + * + * We place everything at 2000:0000, since this region is used by the + * Microsoft first-stage loaders (e.g. pxeboot.n12, etfsboot.com). + */ +#define BASE_SEG 0x2000 + +/** Base linear address */ +#define BASE_ADDRESS ( BASE_SEG << 4 ) + +/** 64 bit long mode code segment */ +#define LM_CS 0x10 + +/** 32 bit protected mode flat code segment */ +#define FLAT_CS 0x20 + +/** 32 bit protected mode flat data segment */ +#define FLAT_DS 0x30 + +/** 16 bit real mode code segment */ +#define REAL_CS 0x50 + +/** 16 bit real mode data segment */ +#define REAL_DS 0x60 + +#ifndef ASSEMBLY + +#include +#include +#include + +/** Construct wide-character version of a string constant */ +#define L( x ) _L ( x ) +#define _L( x ) L ## x + +/** Page size */ +#define PAGE_SIZE 4096 + +/** + * Calculate start page number + * + * @v address Address + * @ret page Start page number + */ +static inline unsigned int page_start ( const void *address ) { + return ( ( ( intptr_t ) address ) / PAGE_SIZE ); +} + +/** + * Calculate end page number + * + * @v address Address + * @ret page End page number + */ +static inline unsigned int page_end ( const void *address ) { + return ( ( ( ( intptr_t ) address ) + PAGE_SIZE - 1 ) / PAGE_SIZE ); +} + +/** + * Calculate page length + * + * @v start Start address + * @v end End address + * @ret num_pages Number of pages + */ +static inline unsigned int page_len ( const void *start, const void *end ) { + return ( page_end ( end ) - page_start ( start ) ); +} + +/** + * Bochs magic breakpoint + * + */ +static inline void bochsbp ( void ) { + __asm__ __volatile__ ( "xchgw %bx, %bx" ); +} + +/** Debugging output */ +#define DBG(...) do { \ + if ( ( DEBUG & 1 ) && ( ! cmdline_quiet ) ) { \ + printf ( __VA_ARGS__ ); \ + } \ + } while ( 0 ) + +/** Verbose debugging output */ +#define DBG2(...) do { \ + if ( ( DEBUG & 2 ) && ( ! cmdline_quiet ) ) { \ + printf ( __VA_ARGS__ ); \ + } \ + } while ( 0 ) + +/* Branch prediction macros */ +#define likely( x ) __builtin_expect ( !! (x), 1 ) +#define unlikely( x ) __builtin_expect ( (x), 0 ) + +/* Mark parameter as unused */ +#define __unused __attribute__ (( unused )) + +#if __x86_64__ +static inline void call_real ( struct bootapp_callback_params *params ) { + /* Not available in 64-bit mode */ + ( void ) params; +} +static inline void call_interrupt ( struct bootapp_callback_params *params ) { + /* Not available in 64-bit mode */ + ( void ) params; +} +static inline void reboot ( void ) { + /* Not available in 64-bit mode */ +} +#else +extern void call_real ( struct bootapp_callback_params *params ); +extern void call_interrupt ( struct bootapp_callback_params *params ); +extern void __attribute__ (( noreturn )) reboot ( void ); +#endif + +extern void __attribute__ (( noreturn, format ( printf, 1, 2 ) )) +die ( const char *fmt, ... ); + +extern unsigned long __stack_chk_guard; +extern void init_cookie ( void ); + +#endif /* ASSEMBLY */ + +#endif /* _WIMBOOT_H */ diff --git a/wimboot/wimboot-2.7.3/src/wimfile.c b/wimboot/wimboot-2.7.3/src/wimfile.c new file mode 100644 index 00000000..c009565a --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wimfile.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM virtual files + * + */ + +#include +#include +#include +#include +#include +#include "wimboot.h" +#include "vdisk.h" +#include "wim.h" +#include "wimfile.h" + +/** A WIM virtual file */ +struct wim_file { + /** Underlying virtual file */ + struct vdisk_file *file; + /** WIM header */ + struct wim_header header; + /** Resource */ + struct wim_resource_header resource; +}; + +/** Maximum number of WIM virtual files */ +#define WIM_MAX_FILES 8 + +/** WIM virtual files */ +static struct wim_file wim_files[WIM_MAX_FILES]; + +/** + * Read from WIM virtual file + * + * @v file Virtual file + * @v data Data buffer + * @v offset Offset + * @v len Length + */ +static void wim_read_file ( struct vdisk_file *file, void *data, + size_t offset, size_t len ) { + struct wim_file *wfile = file->opaque; + int rc; + + /* Read from resource */ + if ( ( rc = wim_read ( wfile->file, &wfile->header, &wfile->resource, + data, offset, len ) ) != 0 ) { + die ( "Could not read from WIM virtual file\n" ); + } +} + +/** + * Add WIM virtual file + * + * @v file Underlying virtual file + * @v index Image index, or 0 to use boot image + * @v path Path to file within WIM + * @v wname New virtual file name + * @ret file Virtual file, or NULL if not found + */ +struct vdisk_file * wim_add_file ( struct vdisk_file *file, unsigned int index, + const wchar_t *path, const wchar_t *wname ) { + static unsigned int wim_file_idx = 0; + struct wim_resource_header meta; + struct wim_file *wfile; + char name[ VDISK_NAME_LEN + 1 /* NUL */ ]; + unsigned int i; + int rc; + + /* Sanity check */ + if ( wim_file_idx >= WIM_MAX_FILES ) + die ( "Too many WIM files\n" ); + wfile = &wim_files[wim_file_idx]; + + /* Construct ASCII file name */ + snprintf ( name, sizeof ( name ), "%ls", wname ); + + /* Skip files already added explicitly */ + for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { + if ( strcasecmp ( name, vdisk_files[i].name ) == 0 ) + return NULL; + } + + /* Get WIM header */ + if ( ( rc = wim_header ( file, &wfile->header ) ) != 0 ) + return NULL; + + /* Get image metadata */ + if ( ( rc = wim_metadata ( file, &wfile->header, index, &meta ) ) != 0 ) + return NULL; + + /* Get file resource */ + if ( ( rc = wim_file ( file, &wfile->header, &meta, path, + &wfile->resource ) ) != 0 ) + return NULL; + + /* Add virtual file */ + wim_file_idx++; + wfile->file = file; + return vdisk_add_file ( name, wfile, wfile->resource.len, + wim_read_file ); +} + +/** + * Add WIM virtual files + * + * @v file Underlying virtual file + * @v index Image index, or 0 to use boot image + * @v paths List of paths to files within WIM + */ +void wim_add_files ( struct vdisk_file *file, unsigned int index, + const wchar_t **paths ) { + const wchar_t **path; + const wchar_t *wname; + const wchar_t *tmp; + + /* Add any existent files within the list */ + for ( path = paths ; *path ; path++ ) { + + /* Construct file name */ + wname = *path; + for ( tmp = wname ; *tmp ; tmp++ ) { + if ( *tmp == L'\\' ) + wname = ( tmp + 1 ); + } + + /* Add virtual file, if existent */ + wim_add_file ( file, index, *path, wname ); + } +} diff --git a/wimboot/wimboot-2.7.3/src/wimfile.h b/wimboot/wimboot-2.7.3/src/wimfile.h new file mode 100644 index 00000000..d91c2978 --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wimfile.h @@ -0,0 +1,41 @@ +#ifndef _WIMFILE_H +#define _WIMFILE_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM virtual files + * + */ + +#include + +struct vdisk_file; + +extern struct vdisk_file * wim_add_file ( struct vdisk_file *file, + unsigned int index, + const wchar_t *path, + const wchar_t *wname ); +extern void wim_add_files ( struct vdisk_file *file, unsigned int index, + const wchar_t **paths ); + +#endif /* _WIMFILE_H */ diff --git a/wimboot/wimboot-2.7.3/src/wimpatch.c b/wimboot/wimboot-2.7.3/src/wimpatch.c new file mode 100644 index 00000000..fd86e50e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wimpatch.c @@ -0,0 +1,811 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM dynamic patching + * + */ + +#include +#include +#include +#include +#include +#include "wimboot.h" +#include "cmdline.h" +#include "vdisk.h" +#include "sha1.h" +#include "wim.h" +#include "wimpatch.h" + +/** Directory into which files are injected */ +#define WIM_INJECT_DIR "\\Windows\\System32" + +struct wim_patch; + +/** A region of a patched WIM file */ +struct wim_patch_region { + /** Name */ + const char *name; + /** Opaque token */ + void *opaque; + /** Starting offset of region */ + size_t offset; + /** Length of region */ + size_t len; + /** Patch region + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ + int ( * patch ) ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ); +}; + +/** Regions of a patched WIM directory containing injected files */ +struct wim_patch_dir_regions { + /** Subdirectory offset within parent entry */ + struct wim_patch_region subdir; + /** Copy of original directory entries */ + struct wim_patch_region copy; + /** Injected file directory entries */ + struct wim_patch_region file[VDISK_MAX_FILES]; +} __attribute__ (( packed )); + +/** Regions of a patched WIM file */ +union wim_patch_regions { + /** Structured list of regions */ + struct { + /** WIM header */ + struct wim_patch_region header; + /** Injected file contents */ + struct wim_patch_region file[VDISK_MAX_FILES]; + /** Injected lookup table */ + struct { + /** Uncompressed copy of original lookup table */ + struct wim_patch_region copy; + /** Injected boot image metadata lookup table entry */ + struct wim_patch_region boot; + /** Injected file lookup table entries */ + struct wim_patch_region file[VDISK_MAX_FILES]; + } __attribute__ (( packed )) lookup; + /** Injected boot image metadata */ + struct { + /** Uncompressed copy of original metadata */ + struct wim_patch_region copy; + /** Patched directory containing injected files */ + struct wim_patch_dir_regions dir; + } __attribute__ (( packed )) boot; + } __attribute__ (( packed )); + /** Unstructured list of regions */ + struct wim_patch_region region[0]; +}; + +/** An injected directory entry */ +struct wim_patch_dir_entry { + /** Directory entry */ + struct wim_directory_entry dir; + /** Name */ + wchar_t name[ VDISK_NAME_LEN + 1 /* wNUL */ ]; +} __attribute__ (( packed )); + +/** A directory containing injected files */ +struct wim_patch_dir { + /** Name */ + const char *name; + /** Offset to parent directory entry */ + size_t parent; + /** Offset to original directory entries */ + size_t offset; + /** Length of original directory entries (excluding terminator) */ + size_t len; + /** Offset to modified directory entries */ + size_t subdir; +}; + +/** A patched WIM file */ +struct wim_patch { + /** Virtual file */ + struct vdisk_file *file; + /** Patched WIM header */ + struct wim_header header; + /** Original lookup table */ + struct wim_resource_header lookup; + /** Original boot image metadata */ + struct wim_resource_header boot; + /** Original boot index */ + uint32_t boot_index; + /** Directory containing injected files */ + struct wim_patch_dir dir; + /** Patched regions */ + union wim_patch_regions regions; +}; + +/** + * Align WIM offset to nearest qword + * + * @v len Length + * @ret len Aligned length + */ +static size_t wim_align ( size_t len ) { + return ( ( len + 0x07 ) & ~0x07 ); +} + +/** + * Calculate WIM hash + * + * @v vfile Virtual file + * @v hash Hash to fill in + */ +static void wim_hash ( struct vdisk_file *vfile, struct wim_hash *hash ) { + uint8_t ctx[SHA1_CTX_SIZE]; + uint8_t buf[512]; + size_t offset; + size_t len; + + /* Calculate SHA-1 digest */ + sha1_init ( ctx ); + for ( offset = 0 ; offset < vfile->len ; offset += len ) { + + /* Read block */ + len = ( vfile->len - offset ); + if ( len > sizeof ( buf ) ) + len = sizeof ( buf ); + vfile->read ( vfile, buf, offset, len ); + + /* Update digest */ + sha1_update ( ctx, buf, len ); + } + sha1_final ( ctx, hash->sha1 ); +} + +/** + * Determine whether or not to inject file + * + * @v vfile Virtual file + * @ret inject Inject this file + */ +static int wim_inject_file ( struct vdisk_file *vfile ) { + size_t name_len; + const char *ext; + + /* Ignore non-existent files */ + if ( ! vfile->read ) + return 0; + + /* Ignore wimboot itself */ + if ( strcasecmp ( vfile->name, "wimboot" ) == 0 ) + return 0; + + /* Ignore bootmgr files */ + if ( strcasecmp ( vfile->name, "bootmgr" ) == 0 ) + return 0; + if ( strcasecmp ( vfile->name, "bootmgr.exe" ) == 0 ) + return 0; + + /* Ignore BCD files */ + if ( strcasecmp ( vfile->name, "BCD" ) == 0 ) + return 0; + + /* Locate file extension */ + name_len = strlen ( vfile->name ); + ext = ( ( name_len > 4 ) ? ( vfile->name + name_len - 4 ) : "" ); + + /* Ignore .wim files */ + if ( strcasecmp ( ext, ".wim" ) == 0 ) + return 0; + + /* Ignore .sdi files */ + if ( strcasecmp ( ext, ".sdi" ) == 0 ) + return 0; + + /* Ignore .efi files */ + if ( strcasecmp ( ext, ".efi" ) == 0 ) + return 0; + + /* Ignore .ttf files */ + if ( strcasecmp ( ext, ".ttf" ) == 0 ) + return 0; + + return 1; +} + +/** + * Patch WIM header + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_header ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct wim_header *header = &patch->header; + + /* Sanity checks */ + assert ( offset < sizeof ( *header ) ); + assert ( len <= ( sizeof ( *header ) - offset ) ); + + /* Copy patched header */ + if ( patch->lookup.offset != patch->header.lookup.offset ) { + DBG2 ( "...patched WIM %s lookup table %#llx->%#llx\n", + region->name, patch->lookup.offset, + patch->header.lookup.offset ); + } + if ( patch->boot.offset != patch->header.boot.offset ) { + DBG2 ( "...patched WIM %s boot metadata %#llx->%#llx\n", + region->name, patch->boot.offset, + patch->header.boot.offset ); + } + if ( patch->boot_index != patch->header.boot_index ) { + DBG2 ( "...patched WIM %s boot index %d->%d\n", region->name, + patch->boot_index, patch->header.boot_index ); + } + memcpy ( data, ( ( ( void * ) &patch->header ) + offset ), len ); + + return 0; +} + +/** + * Patch injected file content + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_file ( struct wim_patch *patch __unused, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct vdisk_file *vfile = region->opaque; + + /* Read from file */ + vfile->read ( vfile, data, offset, len ); + + return 0; +} + +/** + * Patch uncompressed copy of original lookup table + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_lookup_copy ( struct wim_patch *patch, + struct wim_patch_region *region __unused, + void *data, size_t offset, size_t len ) { + int rc; + + /* Read original lookup table */ + if ( ( rc = wim_read ( patch->file, &patch->header, &patch->lookup, + data, offset, len ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Patch injected boot image metadata lookup table entry + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_lookup_boot ( struct wim_patch *patch, + struct wim_patch_region *region __unused, + void *data, size_t offset, size_t len ) { + struct wim_lookup_entry entry; + + /* Sanity checks */ + assert ( offset < sizeof ( entry ) ); + assert ( len <= ( sizeof ( entry ) - offset ) ); + + /* Construct lookup table entry */ + memset ( &entry, 0, sizeof ( entry ) ); + memcpy ( &entry.resource, &patch->header.boot, + sizeof ( entry.resource ) ); + + /* Copy lookup table entry */ + memcpy ( data, ( ( ( void * ) &entry ) + offset ), len ); + + return 0; +} + +/** + * Patch injected file lookup table entry + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_lookup_file ( struct wim_patch *patch __unused, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct wim_patch_region *rfile = region->opaque; + struct vdisk_file *vfile = rfile->opaque; + struct wim_lookup_entry entry; + + /* Sanity checks */ + assert ( offset < sizeof ( entry ) ); + assert ( len <= ( sizeof ( entry ) - offset ) ); + + /* Construct lookup table entry */ + memset ( &entry, 0, sizeof ( entry ) ); + entry.resource.offset = rfile->offset; + entry.resource.len = vfile->len; + entry.resource.zlen__flags = entry.resource.len; + entry.refcnt = 1; + wim_hash ( vfile, &entry.hash ); + + /* Copy lookup table entry */ + memcpy ( data, ( ( ( void * ) &entry ) + offset ), len ); + DBG2 ( "...patched WIM %s %s\n", region->name, vfile->name ); + + return 0; +} + +/** + * Patch uncompressed copy of original boot metadata + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_boot_copy ( struct wim_patch *patch, + struct wim_patch_region *region __unused, + void *data, size_t offset, size_t len ) { + int rc; + + /* Read original boot metadata */ + if ( ( rc = wim_read ( patch->file, &patch->header, &patch->boot, + data, offset, len ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Patch subdirectory offset within parent directory entry + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_dir_subdir ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct wim_patch_dir *dir = region->opaque; + uint64_t subdir = dir->subdir; + + /* Sanity checks */ + assert ( offset < sizeof ( subdir ) ); + assert ( len <= ( sizeof ( subdir ) - offset ) ); + + /* Copy subdirectory offset */ + memcpy ( data, ( ( ( void * ) &subdir ) + offset ), len ); + DBG2 ( "...patched WIM %s %s %#llx\n", region->name, dir->name, + ( patch->header.boot.offset + subdir ) ); + + return 0; +} + +/** + * Patch copy of original directory entries + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_dir_copy ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct wim_patch_dir *dir = region->opaque; + int rc; + + /* Read portion of original boot metadata */ + if ( ( rc = wim_read ( patch->file, &patch->header, &patch->boot, + data, ( dir->offset + offset ), len ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Patch injected directory entries + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_dir_file ( struct wim_patch *patch __unused, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + struct wim_patch_region *rfile = region->opaque; + struct vdisk_file *vfile = rfile->opaque; + struct wim_patch_dir_entry entry; + size_t name_len = strlen ( vfile->name ); + unsigned int i; + + /* Sanity checks */ + assert ( offset < sizeof ( entry ) ); + assert ( len <= ( sizeof ( entry ) - offset ) ); + + /* Construct directory entry */ + memset ( &entry, 0, sizeof ( entry ) ); + entry.dir.len = wim_align ( sizeof ( entry ) ); + entry.dir.attributes = WIM_ATTR_NORMAL; + entry.dir.security = WIM_NO_SECURITY; + entry.dir.created = WIM_MAGIC_TIME; + entry.dir.accessed = WIM_MAGIC_TIME; + entry.dir.written = WIM_MAGIC_TIME; + wim_hash ( vfile, &entry.dir.hash ); + entry.dir.name_len = ( name_len * sizeof ( entry.name[0] ) ); + for ( i = 0 ; i < name_len ; i++ ) + entry.name[i] = vfile->name[i]; + + /* Copy directory entry */ + memcpy ( data, ( ( ( void * ) &entry ) + offset ), len ); + DBG2 ( "...patched WIM %s %s\n", region->name, vfile->name ); + + return 0; +} + +/** + * Patch WIM region + * + * @v patch WIM patch + * @v region Patch region + * @v data Data buffer + * @v offset Relative offset + * @v len Length + * @ret rc Return status code + */ +static int wim_patch_region ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, size_t len ) { + size_t skip; + int rc; + + /* Skip unused regions */ + if ( ! region->patch ) + return 0; + + /* Skip any data before this region */ + skip = ( ( region->offset > offset ) ? + ( region->offset - offset ) : 0 ); + if ( skip >= len ) + return 0; + data += skip; + offset += skip; + len -= skip; + + /* Convert to relative offset within this region */ + offset -= region->offset; + + /* Skip any data after this region */ + if ( offset >= region->len ) + return 0; + if ( len > ( region->len - offset ) ) + len = ( region->len - offset ); + + /* Patch this region */ + if ( ( rc = region->patch ( patch, region, data, offset, len ) ) != 0 ) + return rc; + DBG2 ( "...patched WIM %s at [%#zx,%#zx)\n", region->name, + ( region->offset + offset ), ( region->offset + offset + len ) ); + + return 0; +} + +/** + * Construct patched WIM region + * + * @v region Patched region to fill in + * @v name Name + * @v opaque Opaque data + * @v offset Offset + * @v len Length + * @v patch Patch method + * @ret offset Next offset + */ +static inline __attribute__ (( always_inline )) size_t +wim_construct_region ( struct wim_patch_region *region, const char *name, + void *opaque, size_t offset, size_t len, + int ( * patch ) ( struct wim_patch *patch, + struct wim_patch_region *region, + void *data, size_t offset, + size_t len ) ) { + + DBG ( "...patching WIM %s at [%#zx,%#zx)\n", + name, offset, ( offset + len ) ); + region->name = name; + region->opaque = opaque; + region->offset = offset; + region->len = len; + region->patch = patch; + return ( offset + len ); +} + +/** + * Construct patch WIM directory regions + * + * @v patch WIM patch + * @v dir Patched directory + * @v offset Offset + * @v regions Patched directory regions to fill in + * @ret offset Next offset + */ +static size_t wim_construct_dir ( struct wim_patch *patch, + struct wim_patch_dir *dir, size_t offset, + struct wim_patch_dir_regions *regions ) { + struct wim_patch_dir_entry *entry; + struct wim_patch_region *rfile; + size_t boot_offset = patch->header.boot.offset; + unsigned int i; + + DBG ( "...patching WIM directory at %#zx from [%#zx,%#zx)\n", + ( boot_offset + dir->parent ), ( boot_offset + dir->offset ), + ( boot_offset + dir->offset + dir->len ) ); + + /* Align directory entries */ + offset = wim_align ( offset ); + dir->subdir = ( offset - patch->header.boot.offset ); + + /* Construct injected file directory entries */ + for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { + rfile = &patch->regions.file[i]; + if ( ! rfile->patch ) + continue; + offset = wim_construct_region ( ®ions->file[i], "dir.file", + rfile, offset, + sizeof ( *entry ), + wim_patch_dir_file ); + offset = wim_align ( offset ); + } + + /* Construct copy of original directory entries */ + offset = wim_construct_region ( ®ions->copy, dir->name, dir, offset, + dir->len, wim_patch_dir_copy ); + + /* Allow space for directory terminator */ + offset += sizeof ( entry->dir.len ); + + /* Construct subdirectory offset within parent directory entry */ + wim_construct_region ( ®ions->subdir, "dir.subdir", dir, + ( boot_offset + dir->parent + + offsetof ( typeof ( entry->dir ), subdir ) ), + sizeof ( entry->dir.subdir ), + wim_patch_dir_subdir ); + + return offset; +} + +/** + * Construct WIM patch + * + * @v file Virtual file + * @v boot_index New boot index (or zero) + * @v inject Inject files into WIM + * @v patch Patch to fill in + * @ret rc Return status code + */ +static int wim_construct_patch ( struct vdisk_file *file, + unsigned int boot_index, int inject, + struct wim_patch *patch ) { + union wim_patch_regions *regions = &patch->regions; + struct wim_patch_region *rfile; + struct wim_resource_header *lookup; + struct wim_resource_header *boot; + struct wim_directory_entry direntry; + struct wim_lookup_entry *entry; + struct vdisk_file *vfile; + size_t offset; + unsigned int injected = 0; + unsigned int i; + int rc; + + /* Initialise patch */ + memset ( patch, 0, sizeof ( *patch ) ); + patch->file = file; + DBG ( "...patching WIM %s\n", file->name ); + + /* Reset file length */ + file->xlen = file->len; + offset = file->len; + + /* Read WIM header */ + if ( ( rc = wim_header ( file, &patch->header ) ) != 0 ) + return rc; + lookup = &patch->header.lookup; + boot = &patch->header.boot; + + /* Patch header within original image body */ + wim_construct_region ( ®ions->header, "header", NULL, 0, + sizeof ( patch->header ), wim_patch_header ); + + /* Record original lookup table */ + memcpy ( &patch->lookup, lookup, sizeof ( patch->lookup ) ); + + /* Record original metadata for selected boot image (which may + * not be the originally selected boot image). + */ + if ( ( rc = wim_metadata ( file, &patch->header, boot_index, + &patch->boot ) ) != 0 ) + return rc; + + /* Record original boot index */ + patch->boot_index = patch->header.boot_index; + + /* Update boot index in patched header, if applicable */ + if ( boot_index ) + patch->header.boot_index = boot_index; + + /* Do nothing more if injection is disabled */ + if ( ! inject ) + return 0; + + /* Construct injected files */ + for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { + vfile = &vdisk_files[i]; + if ( ! wim_inject_file ( vfile ) ) + continue; + offset = wim_construct_region ( ®ions->file[i], vfile->name, + vfile, offset, vfile->len, + wim_patch_file ); + injected++; + } + + /* Do nothing more if no files are injected */ + if ( injected == 0 ) + return 0; + + /* Calculate boot index for injected image */ + if ( ( rc = wim_count ( file, &patch->header, &boot_index ) ) != 0 ) + return rc; + patch->header.images = ( boot_index + 1 ); + patch->header.boot_index = patch->header.images; + + /* Construct injected lookup table */ + lookup->offset = offset = wim_align ( offset ); + offset = wim_construct_region ( ®ions->lookup.copy, "lookup.copy", + NULL, offset, patch->lookup.len, + wim_patch_lookup_copy ); + offset = wim_construct_region ( ®ions->lookup.boot, "lookup.boot", + NULL, offset, sizeof ( *entry ), + wim_patch_lookup_boot ); + for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { + rfile = ®ions->file[i]; + if ( ! rfile->patch ) + continue; + offset = wim_construct_region ( ®ions->lookup.file[i], + "lookup.file", rfile, + offset, sizeof ( *entry ), + wim_patch_lookup_file ); + } + lookup->offset = regions->lookup.copy.offset; + lookup->len = ( offset - lookup->offset ); + lookup->zlen__flags = lookup->len; + + /* Locate directory containing injected files */ + patch->dir.name = WIM_INJECT_DIR; + if ( ( rc = wim_path ( file, &patch->header, &patch->boot, + L(WIM_INJECT_DIR), &patch->dir.parent, + &direntry ) ) != 0 ) + return rc; + patch->dir.offset = direntry.subdir; + if ( ( rc = wim_dir_len ( file, &patch->header, &patch->boot, + patch->dir.offset, &patch->dir.len ) ) != 0 ) + return rc; + + /* Construct injected boot image metadata */ + boot->offset = offset = wim_align ( offset ); + offset = wim_construct_region ( ®ions->boot.copy, "boot.copy", + NULL, offset, patch->boot.len, + wim_patch_boot_copy ); + offset = wim_construct_dir ( patch, &patch->dir, offset, + ®ions->boot.dir ); + boot->len = ( offset - boot->offset ); + boot->zlen__flags = ( boot->len | WIM_RESHDR_METADATA ); + + /* Record patched length */ + file->xlen = offset; + DBG ( "...patching WIM length %#zx->%#zx\n", file->len, file->xlen ); + + return 0; +} + +/** + * Patch WIM file + * + * @v file Virtual file + * @v data Data buffer + * @v offset Offset + * @v len Length + */ +void patch_wim ( struct vdisk_file *file, void *data, size_t offset, + size_t len ) { + static struct wim_patch cached_patch; + struct wim_patch *patch = &cached_patch; + struct wim_patch_region *region; + unsigned int boot_index; + unsigned int i; + int inject; + int rc; + + /* Do nothing unless patching is required */ + boot_index = cmdline_index; + inject = ( ! cmdline_rawwim ); + if ( ( boot_index == 0 ) && ( ! inject ) ) + return; + + /* Update cached patch if required */ + if ( file != patch->file ) { + if ( ( rc = wim_construct_patch ( file, boot_index, inject, + patch ) ) != 0 ) { + die ( "Could not patch WIM %s\n", file->name ); + } + } + patch = &cached_patch; + + /* Patch regions */ + for ( i = 0 ; i < ( sizeof ( patch->regions ) / + sizeof ( patch->regions.region[0] ) ) ; i++ ) { + region = &patch->regions.region[i]; + if ( ( rc = wim_patch_region ( patch, region, data, offset, + len ) ) != 0 ) { + die ( "Could not patch WIM %s %s at [%#zx,%#zx)\n", + file->name, region->name, offset, + ( offset + len ) ); + } + } +} diff --git a/wimboot/wimboot-2.7.3/src/wimpatch.h b/wimboot/wimboot-2.7.3/src/wimpatch.h new file mode 100644 index 00000000..3882ad7b --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/wimpatch.h @@ -0,0 +1,37 @@ +#ifndef _WIMPATCH_H +#define _WIMPATCH_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * 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 + * + * WIM dynamic patching + * + */ + +#include + +struct vdisk_file; + +extern void patch_wim ( struct vdisk_file *file, void *data, size_t offset, + size_t len ); + +#endif /* _WIMPATCH_H */ diff --git a/wimboot/wimboot-2.7.3/src/x86_64.i b/wimboot/wimboot-2.7.3/src/x86_64.i new file mode 100644 index 00000000..f821626a --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/x86_64.i @@ -0,0 +1 @@ + .code64 diff --git a/wimboot/wimboot-2.7.3/src/xca.c b/wimboot/wimboot-2.7.3/src/xca.c new file mode 100644 index 00000000..52a691aa --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/xca.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Xpress Compression Algorithm (MS-XCA) decompression + * + */ + +#include +#include +#include +#include +#include "wimboot.h" +#include "huffman.h" +#include "xca.h" + +/** + * Decompress XCA-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 xca_decompress ( const void *data, size_t len, void *buf ) { + const void *src = data; + const void *end = ( src + len ); + uint8_t *out = buf; + size_t out_len = 0; + size_t out_len_threshold = 0; + const struct xca_huf_len *lengths; + struct xca xca; + uint32_t accum = 0; + int extra_bits = 0; + unsigned int huf; + struct huffman_symbols *sym; + unsigned int raw; + unsigned int match_len; + unsigned int match_offset_bits; + unsigned int match_offset; + const uint8_t *copy; + int rc; + + /* Process data stream */ + while ( src < end ) { + + /* (Re)initialise decompressor if applicable */ + if ( out_len >= out_len_threshold ) { + + /* Construct symbol lengths */ + lengths = src; + src += sizeof ( *lengths ); + if ( src > end ) { + DBG ( "XCA too short to hold Huffman lengths " + "table at input offset %#zx\n", + ( src - data ) ); + return -1; + } + for ( raw = 0 ; raw < XCA_CODES ; raw++ ) + xca.lengths[raw] = xca_huf_len ( lengths, raw ); + + /* Construct Huffman alphabet */ + if ( ( rc = huffman_alphabet ( &xca.alphabet, + xca.lengths, + XCA_CODES ) ) != 0 ) + return rc; + + /* Initialise state */ + accum = XCA_GET16 ( src ); + accum <<= 16; + accum |= XCA_GET16 ( src ); + extra_bits = 16; + + /* Determine next threshold */ + out_len_threshold = ( out_len + XCA_BLOCK_SIZE ); + } + + /* Determine symbol */ + huf = ( accum >> ( 32 - HUFFMAN_BITS ) ); + sym = huffman_sym ( &xca.alphabet, huf ); + raw = huffman_raw ( sym, huf ); + accum <<= huffman_len ( sym ); + extra_bits -= huffman_len ( sym ); + if ( extra_bits < 0 ) { + accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) ); + extra_bits += 16; + } + + /* Process symbol */ + if ( raw < XCA_END_MARKER ) { + + /* Literal symbol - add to output stream */ + if ( buf ) + *(out++) = raw; + out_len++; + + } else if ( ( raw == XCA_END_MARKER ) && + ( src >= ( end - 1 ) ) ) { + + /* End marker symbol */ + return out_len; + + } else { + + /* LZ77 match symbol */ + raw -= XCA_END_MARKER; + match_offset_bits = ( raw >> 4 ); + match_len = ( raw & 0x0f ); + if ( match_len == 0x0f ) { + match_len = XCA_GET8 ( src ); + if ( match_len == 0xff ) { + match_len = XCA_GET16 ( src ); + } else { + match_len += 0x0f; + } + } + match_len += 3; + if ( match_offset_bits ) { + match_offset = + ( ( accum >> ( 32 - match_offset_bits )) + + ( 1 << match_offset_bits ) ); + } else { + match_offset = 1; + } + accum <<= match_offset_bits; + extra_bits -= match_offset_bits; + if ( extra_bits < 0 ) { + accum |= ( XCA_GET16 ( src ) << (-extra_bits) ); + extra_bits += 16; + } + + /* Copy data */ + out_len += match_len; + if ( buf ) { + copy = ( out - match_offset ); + while ( match_len-- ) + *(out++) = *(copy++); + } + } + } + + DBG ( "XCA input overrun at output length %#zx\n", out_len ); + return -1; +} diff --git a/wimboot/wimboot-2.7.3/src/xca.h b/wimboot/wimboot-2.7.3/src/xca.h new file mode 100644 index 00000000..ca1a617e --- /dev/null +++ b/wimboot/wimboot-2.7.3/src/xca.h @@ -0,0 +1,88 @@ +#ifndef _XCA_H +#define _XCA_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * 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 + * + * Xpress Compression Algorithm (MS-XCA) decompression + * + */ + +#include +#include "huffman.h" + +/** Number of XCA codes */ +#define XCA_CODES 512 + +/** XCA decompressor */ +struct xca { + /** Huffman alphabet */ + struct huffman_alphabet alphabet; + /** Raw symbols + * + * Must immediately follow the Huffman alphabet. + */ + huffman_raw_symbol_t raw[XCA_CODES]; + /** Code lengths */ + uint8_t lengths[XCA_CODES]; +}; + +/** XCA symbol Huffman lengths table */ +struct xca_huf_len { + /** Lengths of each symbol */ + uint8_t nibbles[ XCA_CODES / 2 ]; +} __attribute__ (( packed )); + +/** + * Extract Huffman-coded length of a raw symbol + * + * @v lengths Huffman lengths table + * @v symbol Raw symbol + * @ret len Huffman-coded length + */ +static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths, + unsigned int symbol ) { + return ( ( ( lengths->nibbles[ symbol / 2 ] ) >> + ( 4 * ( symbol % 2 ) ) ) & 0x0f ); +} + +/** Get word from source data stream */ +#define XCA_GET16( src ) ( { \ + const uint16_t *src16 = src; \ + src += sizeof ( *src16 ); \ + *src16; } ) + +/** Get byte from source data stream */ +#define XCA_GET8( src ) ( { \ + const uint8_t *src8 = src; \ + src += sizeof ( *src8 ); \ + *src8; } ) + +/** XCA source data stream end marker */ +#define XCA_END_MARKER 256 + +/** XCA block size */ +#define XCA_BLOCK_SIZE ( 64 * 1024 ) + +extern ssize_t xca_decompress ( const void *data, size_t len, void *buf ); + +#endif /* _XCA_H */