2. Add WIMBOOT for UEFI mode.
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;
+}
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"
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);
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);
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;
}
{ "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 },
};
cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
cur->summary, cur->description, cur->parser);
}
+
return 0;
}
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
(
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)
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;
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;
+}
+
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,
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
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
}
-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 {
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
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
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
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
+++ /dev/null
-[LaunchApps]\r
-vtoyjump.exe
\ No newline at end of file
g_64bit_system = TRUE;\r
#endif\r
\r
- Log("VentoyJumpWimboot 64bit:%u", g_64bit_system);\r
+ Log("VentoyJumpWimboot %dbit", g_64bit_system ? 64 : 32);\r
\r
sprintf_s(LunchFile, MAX_PATH, "X:\\setup.exe");\r
\r
}\r
\r
g_64bit_system = IsPe64(Buffer);\r
+ Log("VentoyJump %dbit", g_64bit_system ? 64 : 32);\r
\r
if (!IsPathExist(TRUE, "ventoy"))\r
{\r
--- /dev/null
+#!/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 ../../
--- /dev/null
+wimboot
+*.s
+*.o
+*.a
+*.elf
+*.map
+*.unsigned
+*.efi
+*.cab
+efireloc
--- /dev/null
+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
--- /dev/null
+#ifndef _ASSERT_H
+#define _ASSERT_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Assertions
+ *
+ */
+
+#include "wimboot.h"
+
+#define assert(x) do { \
+ if ( DEBUG && ! (x) ) { \
+ die ( "Assertion failed at %s line %d: %s\n", \
+ __FILE__, __LINE__, #x ); \
+ } \
+ } while ( 0 )
+
+#endif /* _ASSERT_H */
--- /dev/null
+#ifndef _BOOTAPP_H
+#define _BOOTAPP_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Boot application data structures
+ *
+ */
+
+#include <stdint.h>
+
+/** A segment:offset address */
+struct segoff {
+ /** Offset */
+ uint16_t offset;
+ /** Segment */
+ uint16_t segment;
+} __attribute__ (( packed ));
+
+/** A GUID */
+struct guid {
+ /** 8 hex digits, big-endian */
+ uint32_t a;
+ /** 2 hex digits, big-endian */
+ uint16_t b;
+ /** 2 hex digits, big-endian */
+ uint16_t c;
+ /** 2 hex digits, big-endian */
+ uint16_t d;
+ /** 12 hex digits, big-endian */
+ uint8_t e[6];
+} __attribute__ (( packed ));
+
+/** Real-mode callback parameters */
+struct bootapp_callback_params {
+ /** Vector */
+ union {
+ /** Interrupt number */
+ uint32_t interrupt;
+ /** Segment:offset address of real-mode function */
+ struct segoff function;
+ } vector;
+ /** %eax value */
+ union {
+ struct {
+ uint8_t al;
+ uint8_t ah;
+ } __attribute__ (( packed ));
+ uint16_t ax;
+ uint32_t eax;
+ };
+ /** %ebx value */
+ union {
+ struct {
+ uint8_t bl;
+ uint8_t bh;
+ } __attribute__ (( packed ));
+ uint16_t bx;
+ uint32_t ebx;
+ };
+ /** %ecx value */
+ union {
+ struct {
+ uint8_t cl;
+ uint8_t ch;
+ } __attribute__ (( packed ));
+ uint16_t cx;
+ uint32_t ecx;
+ };
+ /** %edx value */
+ union {
+ struct {
+ uint8_t dl;
+ uint8_t dh;
+ } __attribute__ (( packed ));
+ uint16_t dx;
+ uint32_t edx;
+ };
+ /** Placeholder (for %esp?) */
+ uint32_t unused_esp;
+ /** Placeholder (for %ebp?) */
+ uint32_t unused_ebp;
+ /** %esi value */
+ union {
+ uint16_t si;
+ uint32_t esi;
+ };
+ /** %edi value */
+ union {
+ uint16_t di;
+ uint32_t edi;
+ };
+ /** Placeholder (for %cs?) */
+ uint32_t unused_cs;
+ /** %ds value */
+ uint32_t ds;
+ /** Placeholder (for %ss?) */
+ uint32_t unused_ss;
+ /** %es value */
+ uint32_t es;
+ /** %fs value */
+ uint32_t fs;
+ /** %gs value */
+ uint32_t gs;
+ /** eflags value */
+ uint32_t eflags;
+} __attribute__ (( packed ));
+
+/** eflags bits */
+enum eflags {
+ CF = ( 1 << 0 ),
+ PF = ( 1 << 2 ),
+ AF = ( 1 << 4 ),
+ ZF = ( 1 << 6 ),
+ SF = ( 1 << 7 ),
+ OF = ( 1 << 11 ),
+};
+
+/** Real-mode callback function table */
+struct bootapp_callback_functions {
+ /**
+ * Call an arbitrary real-mode interrupt
+ *
+ * @v params Parameters
+ */
+ void ( * call_interrupt ) ( struct bootapp_callback_params *params );
+ /**
+ * Call an arbitrary real-mode function
+ *
+ * @v params Parameters
+ */
+ void ( * call_real ) ( struct bootapp_callback_params *params );
+} __attribute__ (( packed ));
+
+/** Real-mode callbacks */
+struct bootapp_callback {
+ /** Real-mode callback function table */
+ struct bootapp_callback_functions *fns;
+ /** Drive number for INT13 calls */
+ uint32_t drive;
+} __attribute__ (( packed ));
+
+/** Boot application descriptor */
+struct bootapp_descriptor {
+ /** Signature */
+ char signature[8];
+ /** Version */
+ uint32_t version;
+ /** Total length */
+ uint32_t len;
+ /** COFF machine type */
+ uint32_t arch;
+ /** Reserved */
+ uint32_t reserved_0x14;
+ /** Loaded PE image base address */
+ void *pe_base;
+ /** Reserved */
+ uint32_t reserved_0x1c;
+ /** Length of loaded PE image */
+ uint32_t pe_len;
+ /** Offset to memory descriptor */
+ uint32_t memory;
+ /** Offset to boot application entry descriptor */
+ uint32_t entry;
+ /** Offset to ??? */
+ uint32_t xxx;
+ /** Offset to callback descriptor */
+ uint32_t callback;
+ /** Offset to pointless descriptor */
+ uint32_t pointless;
+ /** Reserved */
+ uint32_t reserved_0x38;
+} __attribute__ (( packed ));
+
+/** "BOOT APP" magic signature */
+#define BOOTAPP_SIGNATURE "BOOT APP"
+
+/** Boot application descriptor version */
+#define BOOTAPP_VERSION 2
+
+/** i386 architecture */
+#define BOOTAPP_ARCH_I386 0x014c
+
+/** Memory region descriptor */
+struct bootapp_memory_region {
+ /** Reserved (for struct list_head?) */
+ uint8_t reserved[8];
+ /** Start page address */
+ uint64_t start_page;
+ /** Reserved */
+ uint8_t reserved_0x10[8];
+ /** Number of pages */
+ uint64_t num_pages;
+ /** Reserved */
+ uint8_t reserved_0x20[4];
+ /** Flags */
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/** Memory descriptor */
+struct bootapp_memory_descriptor {
+ /** Version */
+ uint32_t version;
+ /** Length of descriptor (excluding region descriptors) */
+ uint32_t len;
+ /** Number of regions */
+ uint32_t num_regions;
+ /** Length of each region descriptor */
+ uint32_t region_len;
+ /** Length of reserved area at start of each region descriptor */
+ uint32_t reserved_len;
+} __attribute__ (( packed ));
+
+/** Boot application memory descriptor version */
+#define BOOTAPP_MEMORY_VERSION 1
+
+/** Boot application entry descriptor */
+struct bootapp_entry_descriptor {
+ /** Signature */
+ char signature[8];
+ /** Flags */
+ uint32_t flags;
+ /** GUID */
+ struct guid guid;
+ /** Reserved */
+ uint8_t reserved[16];
+} __attribute__ (( packed ));
+
+/** ??? */
+struct bootapp_entry_wtf1_descriptor {
+ /** Flags */
+ uint32_t flags;
+ /** Length of descriptor */
+ uint32_t len;
+ /** Total length of following descriptors within BTAPENT */
+ uint32_t extra_len;
+ /** Reserved */
+ uint8_t reserved[12];
+} __attribute__ (( packed ));
+
+/** ??? */
+struct bootapp_entry_wtf2_descriptor {
+ /** GUID */
+ struct guid guid;
+} __attribute__ (( packed ));
+
+/** ??? */
+struct bootapp_entry_wtf3_descriptor {
+ /** Flags */
+ uint32_t flags;
+ /** Reserved */
+ uint32_t reserved_0x04;
+ /** Length of descriptor */
+ uint32_t len;
+ /** Reserved */
+ uint32_t reserved_0x0c;
+ /** Boot partition offset (in bytes) */
+ uint32_t boot_partition_offset;
+ /** Reserved */
+ uint8_t reserved_0x14[16];
+ /** MBR signature present? */
+ uint32_t xxx;
+ /** MBR signature */
+ uint32_t mbr_signature;
+ /** Reserved */
+ uint8_t reserved_0x2c[26];
+} __attribute__ (( packed ));
+
+/** "BTAPENT" magic signature */
+#define BOOTAPP_ENTRY_SIGNATURE "BTAPENT\0"
+
+/** Boot application entry flags
+ *
+ * pxeboot, etftboot, and fatboot all use a value of 0x21; I have no
+ * idea what it means.
+ */
+#define BOOTAPP_ENTRY_FLAGS 0x21
+
+/** Boot application callback descriptor */
+struct bootapp_callback_descriptor {
+ /** Real-mode callbacks */
+ struct bootapp_callback *callback;
+ /** Reserved */
+ uint32_t reserved;
+} __attribute__ (( packed ));
+
+/** Boot application pointless descriptor */
+struct bootapp_pointless_descriptor {
+ /** Version */
+ uint32_t version;
+ /** Reserved */
+ uint8_t reserved[24];
+} __attribute__ (( packed ));
+
+/** Boot application pointless descriptor version */
+#define BOOTAPP_POINTLESS_VERSION 1
+
+#endif /* _BOOTAPP_H */
--- /dev/null
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H
+
+/** @file
+ *
+ * Byte-order swapping functions
+ *
+ */
+
+#include <stdint.h>
+
+static inline __attribute__ (( always_inline, const )) uint16_t
+__bswap_variable_16 ( uint16_t x ) {
+ __asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_16s ( uint16_t *x ) {
+ __asm__ ( "rorw $8, %0" : "+m" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint32_t
+__bswap_variable_32 ( uint32_t x ) {
+ __asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_32s ( uint32_t *x ) {
+ __asm__ ( "bswapl %k0" : "=r" ( *x ) : "0" ( *x ) );
+}
+
+#ifdef __x86_64__
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ __asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+#else /* __x86_64__ */
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ uint32_t in_high = ( x >> 32 );
+ uint32_t in_low = ( x & 0xffffffffUL );
+ uint32_t out_high;
+ uint32_t out_low;
+
+ __asm__ ( "bswapl %0\n\t"
+ "bswapl %1\n\t"
+ "xchgl %0,%1\n\t"
+ : "=r" ( out_high ), "=r" ( out_low )
+ : "0" ( in_high ), "1" ( in_low ) );
+
+ return ( ( ( ( uint64_t ) out_high ) << 32 ) |
+ ( ( uint64_t ) out_low ) );
+}
+
+#endif /* __x86_64__ */
+
+static inline __attribute__ (( always_inline )) void
+__bswap_64s ( uint64_t *x ) {
+ *x = __bswap_variable_64 ( *x );
+}
+
+/**
+ * Byte-swap a 16-bit constant
+ *
+ * @v value Constant value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_constant_16( value ) \
+ ( ( ( (value) & 0x00ff ) << 8 ) | \
+ ( ( (value) & 0xff00 ) >> 8 ) )
+
+/**
+ * Byte-swap a 32-bit constant
+ *
+ * @v value Constant value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_constant_32( value ) \
+ ( ( ( (value) & 0x000000ffUL ) << 24 ) | \
+ ( ( (value) & 0x0000ff00UL ) << 8 ) | \
+ ( ( (value) & 0x00ff0000UL ) >> 8 ) | \
+ ( ( (value) & 0xff000000UL ) >> 24 ) )
+
+/**
+ * Byte-swap a 64-bit constant
+ *
+ * @v value Constant value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_constant_64( value ) \
+ ( ( ( (value) & 0x00000000000000ffULL ) << 56 ) | \
+ ( ( (value) & 0x000000000000ff00ULL ) << 40 ) | \
+ ( ( (value) & 0x0000000000ff0000ULL ) << 24 ) | \
+ ( ( (value) & 0x00000000ff000000ULL ) << 8 ) | \
+ ( ( (value) & 0x000000ff00000000ULL ) >> 8 ) | \
+ ( ( (value) & 0x0000ff0000000000ULL ) >> 24 ) | \
+ ( ( (value) & 0x00ff000000000000ULL ) >> 40 ) | \
+ ( ( (value) & 0xff00000000000000ULL ) >> 56 ) )
+
+/**
+ * Byte-swap a 16-bit value
+ *
+ * @v value Value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_16( value ) \
+ ( __builtin_constant_p (value) ? \
+ ( ( uint16_t ) __bswap_constant_16 ( ( uint16_t ) (value) ) ) \
+ : __bswap_variable_16 (value) )
+#define bswap_16( value ) __bswap_16 (value)
+
+/**
+ * Byte-swap a 32-bit value
+ *
+ * @v value Value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_32( value ) \
+ ( __builtin_constant_p (value) ? \
+ ( ( uint32_t ) __bswap_constant_32 ( ( uint32_t ) (value) ) ) \
+ : __bswap_variable_32 (value) )
+#define bswap_32( value ) __bswap_32 (value)
+
+/**
+ * Byte-swap a 64-bit value
+ *
+ * @v value Value
+ * @ret swapped Byte-swapped value
+ */
+#define __bswap_64( value ) \
+ ( __builtin_constant_p (value) ? \
+ ( ( uint64_t ) __bswap_constant_64 ( ( uint64_t ) (value) ) ) \
+ : __bswap_variable_64 (value) )
+#define bswap_64( value ) __bswap_64 (value)
+
+#define __cpu_to_leNN( bits, value ) (value)
+#define __cpu_to_beNN( bits, value ) __bswap_ ## bits (value)
+#define __leNN_to_cpu( bits, value ) (value)
+#define __beNN_to_cpu( bits, value ) __bswap_ ## bits (value)
+#define __cpu_to_leNNs( bits, ptr ) do { } while ( 0 )
+#define __cpu_to_beNNs( bits, ptr ) __bswap_ ## bits ## s (ptr)
+#define __leNN_to_cpus( bits, ptr ) do { } while ( 0 )
+#define __beNN_to_cpus( bits, ptr ) __bswap_ ## bits ## s (ptr)
+
+#define cpu_to_le16( value ) __cpu_to_leNN ( 16, value )
+#define cpu_to_le32( value ) __cpu_to_leNN ( 32, value )
+#define cpu_to_le64( value ) __cpu_to_leNN ( 64, value )
+#define cpu_to_be16( value ) __cpu_to_beNN ( 16, value )
+#define cpu_to_be32( value ) __cpu_to_beNN ( 32, value )
+#define cpu_to_be64( value ) __cpu_to_beNN ( 64, value )
+#define le16_to_cpu( value ) __leNN_to_cpu ( 16, value )
+#define le32_to_cpu( value ) __leNN_to_cpu ( 32, value )
+#define le64_to_cpu( value ) __leNN_to_cpu ( 64, value )
+#define be16_to_cpu( value ) __beNN_to_cpu ( 16, value )
+#define be32_to_cpu( value ) __beNN_to_cpu ( 32, value )
+#define be64_to_cpu( value ) __beNN_to_cpu ( 64, value )
+#define cpu_to_le16s( ptr ) __cpu_to_leNNs ( 16, ptr )
+#define cpu_to_le32s( ptr ) __cpu_to_leNNs ( 32, ptr )
+#define cpu_to_le64s( ptr ) __cpu_to_leNNs ( 64, ptr )
+#define cpu_to_be16s( ptr ) __cpu_to_beNNs ( 16, ptr )
+#define cpu_to_be32s( ptr ) __cpu_to_beNNs ( 32, ptr )
+#define cpu_to_be64s( ptr ) __cpu_to_beNNs ( 64, ptr )
+#define le16_to_cpus( ptr ) __leNN_to_cpus ( 16, ptr )
+#define le32_to_cpus( ptr ) __leNN_to_cpus ( 32, ptr )
+#define le64_to_cpus( ptr ) __leNN_to_cpus ( 64, ptr )
+#define be16_to_cpus( ptr ) __beNN_to_cpus ( 16, ptr )
+#define be32_to_cpus( ptr ) __beNN_to_cpus ( 32, ptr )
+#define be64_to_cpus( ptr ) __beNN_to_cpus ( 64, ptr )
+
+#define htonll( value ) cpu_to_be64 (value)
+#define ntohll( value ) be64_to_cpu (value)
+#define htonl( value ) cpu_to_be32 (value)
+#define ntohl( value ) be32_to_cpu (value)
+#define htons( value ) cpu_to_be16 (value)
+#define ntohs( value ) be16_to_cpu (value)
+
+#endif /* _BITS_BYTESWAP_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Command line
+ *
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "wimboot.h"
+#include "cmdline.h"
+
+/** Use raw (unpatched) BCD files */
+int cmdline_rawbcd;
+
+/** Use raw (unpatched) WIM files */
+int cmdline_rawwim;
+
+/** Inhibit debugging output */
+int cmdline_quiet;
+
+/** Allow graphical output from bootmgr/bootmgfw */
+int cmdline_gui;
+
+/** Pause before booting OS */
+int cmdline_pause;
+
+/** Pause without displaying any prompt */
+int cmdline_pause_quiet;
+
+/** Use linear (unpaged) memory model */
+int cmdline_linear;
+
+/** WIM boot index */
+unsigned int cmdline_index;
+
+int cmdline_vf_num;
+char cmdline_vf_path[MAX_VF][64];
+
+file_size_pf pfventoy_file_size;
+file_read_pf pfventoy_file_read;
+
+/**
+ * Process command line
+ *
+ * @v cmdline Command line
+ */
+void process_cmdline ( char *cmdline ) {
+ char *tmp = cmdline;
+ char *key;
+ char *value;
+ char *endp;
+
+ /* Do nothing if we have no command line */
+ if ( ( cmdline == NULL ) || ( cmdline[0] == '\0' ) )
+ return;
+
+ /* Parse command line */
+ while ( *tmp ) {
+
+ /* Skip whitespace */
+ while ( isspace ( *tmp ) )
+ tmp++;
+
+ /* Find value (if any) and end of this argument */
+ key = tmp;
+ value = NULL;
+ while ( *tmp ) {
+ if ( isspace ( *tmp ) ) {
+ *(tmp++) = '\0';
+ break;
+ } else if ( *tmp == '=' ) {
+ *(tmp++) = '\0';
+ value = tmp;
+ } else {
+ tmp++;
+ }
+ }
+
+ /* Process this argument */
+ if ( strcmp ( key, "rawbcd" ) == 0 ) {
+ cmdline_rawbcd = 1;
+ } else if ( strcmp ( key, "rawwim" ) == 0 ) {
+ cmdline_rawwim = 1;
+ } else if ( strcmp ( key, "gui" ) == 0 ) {
+ cmdline_gui = 1;
+ }
+
+ else if ((key[0] == 'v') && (key[1] == 'f') ) {
+ if (cmdline_vf_num >= MAX_VF)
+ die("Too many vf\n");
+ snprintf(cmdline_vf_path[cmdline_vf_num], 64, "%s", value);
+ cmdline_vf_num++;
+ }else if ( strcmp ( key, "pfsize" ) == 0 ) {
+ pfventoy_file_size = (file_size_pf)strtoul(value, &endp, 0);
+ } else if ( strcmp ( key, "pfread" ) == 0 ) {
+ pfventoy_file_read = (file_read_pf)strtoul(value, &endp, 0 );
+ }
+
+ else if ( strcmp ( key, "linear" ) == 0 ) {
+ cmdline_linear = 1;
+ } else if ( strcmp ( key, "quiet" ) == 0 ) {
+ cmdline_quiet = 1;
+ } else if ( strcmp ( key, "pause" ) == 0 ) {
+ cmdline_pause = 1;
+ if ( value && ( strcmp ( value, "quiet" ) == 0 ) )
+ cmdline_pause_quiet = 1;
+ } else if ( strcmp ( key, "index" ) == 0 ) {
+ if ( ( ! value ) || ( ! value[0] ) )
+ die ( "Argument \"index\" needs a value\n" );
+ cmdline_index = strtoul ( value, &endp, 0 );
+ if ( *endp )
+ die ( "Invalid index \"%s\"\n", value );
+ } else if ( strcmp ( key, "initrdfile" ) == 0 ) {
+ /* Ignore this keyword to allow for use with syslinux */
+ } else if ( key == cmdline ) {
+ /* Ignore unknown initial arguments, which may
+ * be the program name.
+ */
+ } else {
+ die ( "Unrecognised argument \"%s%s%s\"\n", key,
+ ( value ? "=" : "" ), ( value ? value : "" ) );
+ }
+ }
+
+ /* Show command line (after parsing "quiet" option) */
+ DBG ( "Command line: \"%s\" vf=%d pfsize=%p pfread=%p\n",
+ cmdline, cmdline_vf_num, pfventoy_file_size, pfventoy_file_read);
+}
--- /dev/null
+#ifndef _CMDLINE_H
+#define _CMDLINE_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Command line
+ *
+ */
+
+extern int cmdline_rawbcd;
+extern int cmdline_rawwim;
+extern int cmdline_quiet;
+extern int cmdline_gui;
+extern int cmdline_pause;
+extern int cmdline_pause_quiet;
+extern int cmdline_linear;
+extern unsigned int cmdline_index;
+extern void process_cmdline ( char *cmdline );
+
+typedef int (*file_size_pf)(const char *path);
+typedef int (*file_read_pf)(const char *path, int offset, int len, void *buf);
+extern file_size_pf pfventoy_file_size;
+extern file_read_pf pfventoy_file_read;
+#define MAX_VF 16
+extern char cmdline_vf_path[MAX_VF][64];
+extern int cmdline_vf_num;
+
+#endif /* _CMDLINE_H */
--- /dev/null
+#ifndef _COMPILER_H
+#define _COMPILER_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Global compiler definitions
+ *
+ */
+
+/* Force visibility of all symbols to "hidden", i.e. inform gcc that
+ * all symbol references resolve strictly within our final binary.
+ * This avoids unnecessary PLT/GOT entries on x86_64.
+ *
+ * This is a stronger claim than specifying "-fvisibility=hidden",
+ * since it also affects symbols marked with "extern".
+ */
+#ifndef ASSEMBLY
+#if __GNUC__ >= 4
+#pragma GCC visibility push(hidden)
+#endif
+#endif /* ASSEMBLY */
+
+#endif /* _COMPILER_H */
--- /dev/null
+/*
+ * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Stack cookie
+ *
+ */
+
+#include "wimboot.h"
+
+/** Stack cookie */
+unsigned long __stack_chk_guard;
+
+/**
+ * Construct stack cookie value
+ *
+ */
+static __attribute__ (( noinline )) unsigned long make_cookie ( void ) {
+ union {
+ struct {
+ uint32_t eax;
+ uint32_t edx;
+ } __attribute__ (( packed ));
+ unsigned long tsc;
+ } u;
+ unsigned long cookie;
+
+ /* We have no viable source of entropy. Use the CPU timestamp
+ * counter, which will have at least some minimal randomness
+ * in the low bits by the time we are invoked.
+ */
+ __asm__ ( "rdtsc" : "=a" ( u.eax ), "=d" ( u.edx ) );
+ cookie = u.tsc;
+
+ /* Ensure that the value contains a NUL byte, to act as a
+ * runaway string terminator. Construct the NUL using a shift
+ * rather than a mask, to avoid losing valuable entropy in the
+ * lower-order bits.
+ */
+ cookie <<= 8;
+
+ return cookie;
+}
+
+/**
+ * Initialise stack cookie
+ *
+ * This function must not itself use stack guard
+ */
+void init_cookie ( void ) {
+
+ /* Set stack cookie value
+ *
+ * This function must not itself use stack protection, since
+ * the change in the stack guard value would trigger a false
+ * positive.
+ *
+ * There is unfortunately no way to annotate a function to
+ * exclude the use of stack protection. We must therefore
+ * rely on correctly anticipating the compiler's decision on
+ * the use of stack protection.
+ */
+ __stack_chk_guard = make_cookie();
+}
+
+/**
+ * Abort on stack check failure
+ *
+ */
+void __stack_chk_fail ( void ) {
+
+ /* Abort program */
+ die ( "Stack check failed\n" );
+}
--- /dev/null
+/*
+ * 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 ) {
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * CPIO archives
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "wimboot.h"
+#include "cpio.h"
+
+/**
+ * Align CPIO length to nearest dword
+ *
+ * @v len Length
+ * @ret len Aligned length
+ */
+static size_t cpio_align ( size_t len ) {
+ return ( ( len + 0x03 ) & ~0x03 );
+}
+
+/**
+ * Parse CPIO field value
+ *
+ * @v field ASCII field
+ * @ret value Field value
+ */
+static unsigned long cpio_value ( const char *field ) {
+ char buf[9];
+
+ memcpy ( buf, field, ( sizeof ( buf ) - 1 ) );
+ buf[ sizeof ( buf ) - 1 ] = '\0';
+ return strtoul ( buf, NULL, 16 );
+}
+
+/**
+ * Extract files from CPIO archive
+ *
+ * @v data CPIO archive
+ * @v len Maximum length of CPIO archive
+ * @v file File handler
+ * @ret rc Return status code
+ */
+int cpio_extract ( void *data, size_t len,
+ int ( * file ) ( const char *name, void *data,
+ size_t len ) ) {
+ const struct cpio_header *cpio;
+ const uint32_t *pad;
+ const char *file_name;
+ void *file_data;
+ size_t file_name_len;
+ size_t file_len;
+ size_t cpio_len;
+ int rc;
+
+ while ( 1 ) {
+
+ /* Skip over any padding */
+ while ( len >= sizeof ( *pad ) ) {
+ pad = data;
+ if ( *pad )
+ break;
+ data += sizeof ( *pad );
+ len -= sizeof ( *pad );
+ }
+
+ /* Stop if we have reached the end of the archive */
+ if ( ! len )
+ return 0;
+
+ /* Sanity check */
+ if ( len < sizeof ( *cpio ) ) {
+ DBG ( "Truncated CPIO header\n" );
+ return -1;
+ }
+ cpio = data;
+
+ /* Check magic */
+ if ( memcmp ( cpio->c_magic, CPIO_MAGIC,
+ sizeof ( cpio->c_magic ) ) != 0 ) {
+ DBG ( "Bad CPIO magic\n" );
+ return -1;
+ }
+
+ /* Extract file parameters */
+ file_name = ( ( void * ) ( cpio + 1 ) );
+ file_name_len = cpio_value ( cpio->c_namesize );
+ file_data = ( data + cpio_align ( sizeof ( *cpio ) +
+ file_name_len ) );
+ file_len = cpio_value ( cpio->c_filesize );
+ cpio_len = ( file_data + file_len - data );
+ if ( cpio_len < len )
+ cpio_len = cpio_align ( cpio_len );
+ if ( cpio_len > len ) {
+ DBG ( "Truncated CPIO file\n" );
+ return -1;
+ }
+
+ /* If we reach the trailer, we're done */
+ if ( strcmp ( file_name, CPIO_TRAILER ) == 0 )
+ return 0;
+
+ /* Process file */
+ if ( ( rc = file ( file_name, file_data, file_len ) ) != 0 )
+ return rc;
+
+ /* Move to next file */
+ data += cpio_len;
+ len -= cpio_len;
+ }
+}
--- /dev/null
+#ifndef _CPIO_H
+#define _CPIO_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * CPIO archives
+ *
+ */
+
+#include <stdint.h>
+
+/** A CPIO archive header
+ *
+ * All field are hexadecimal ASCII numbers padded with '0' on the
+ * left to the full width of the field.
+ */
+struct cpio_header {
+ /** The string "070701" or "070702" */
+ char c_magic[6];
+ /** File inode number */
+ char c_ino[8];
+ /** File mode and permissions */
+ char c_mode[8];
+ /** File uid */
+ char c_uid[8];
+ /** File gid */
+ char c_gid[8];
+ /** Number of links */
+ char c_nlink[8];
+ /** Modification time */
+ char c_mtime[8];
+ /** Size of data field */
+ char c_filesize[8];
+ /** Major part of file device number */
+ char c_maj[8];
+ /** Minor part of file device number */
+ char c_min[8];
+ /** Major part of device node reference */
+ char c_rmaj[8];
+ /** Minor part of device node reference */
+ char c_rmin[8];
+ /** Length of filename, including final NUL */
+ char c_namesize[8];
+ /** Checksum of data field if c_magic is 070702, othersize zero */
+ char c_chksum[8];
+} __attribute__ (( packed ));
+
+/** CPIO magic */
+#define CPIO_MAGIC "070701"
+
+/** CPIO trailer */
+#define CPIO_TRAILER "TRAILER!!!"
+
+extern int cpio_extract ( void *data, size_t len,
+ int ( * file ) ( const char *name, void *data,
+ size_t len ) );
+
+#endif /* _CPIO_H */
--- /dev/null
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Character types
+ *
+ */
+
+static inline int islower ( int c ) {
+ return ( ( c >= 'a' ) && ( c <= 'z' ) );
+}
+
+static inline int isupper ( int c ) {
+ return ( ( c >= 'A' ) && ( c <= 'Z' ) );
+}
+
+static inline int toupper ( int c ) {
+
+ if ( islower ( c ) )
+ c -= ( 'a' - 'A' );
+ return c;
+}
+
+extern int isspace ( int c );
+
+#endif /* _CTYPE_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Fatal errors
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "wimboot.h"
+#include "efi.h"
+
+/**
+ * Handle fatal errors
+ *
+ * @v fmt Error message format string
+ * @v ... Arguments
+ */
+void die ( const char *fmt, ... ) {
+ EFI_BOOT_SERVICES *bs;
+ EFI_RUNTIME_SERVICES *rs;
+ va_list args;
+
+ /* Print message */
+ va_start ( args, fmt );
+ vprintf ( fmt, args );
+ va_end ( args );
+
+ /* Reboot or exit as applicable */
+ if ( efi_systab ) {
+
+ /* Exit */
+ bs = efi_systab->BootServices;
+ bs->Exit ( efi_image_handle, EFI_LOAD_ERROR, 0, NULL );
+ printf ( "Failed to exit\n" );
+ rs = efi_systab->RuntimeServices;
+ rs->ResetSystem ( EfiResetWarm, 0, 0, NULL );
+ printf ( "Failed to reboot\n" );
+
+ } else {
+
+ /* Wait for keypress */
+ printf ( "Press a key to reboot..." );
+ getchar();
+ printf ( "\n" );
+
+ /* Reboot system */
+ reboot();
+ }
+
+ /* Should be impossible to reach this */
+ __builtin_unreachable();
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI interface
+ *
+ */
+
+#include "wimboot.h"
+#include "efi.h"
+
+/** EFI system table */
+EFI_SYSTEM_TABLE *efi_systab;
+
+/** EFI image handle */
+EFI_HANDLE efi_image_handle;
--- /dev/null
+#ifndef _EFI_H
+#define _EFI_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI definitions
+ *
+ */
+
+/* EFIAPI definition */
+#if __x86_64__
+#define EFIAPI __attribute__ (( ms_abi ))
+#else
+#define EFIAPI
+#endif
+
+/* EFI headers rudely redefine NULL */
+#undef NULL
+
+#include "efi/Uefi.h"
+#include "efi/Protocol/LoadedImage.h"
+
+extern EFI_SYSTEM_TABLE *efi_systab;
+extern EFI_HANDLE efi_image_handle;
+
+extern EFI_GUID efi_block_io_protocol_guid;
+extern EFI_GUID efi_device_path_protocol_guid;
+extern EFI_GUID efi_graphics_output_protocol_guid;
+extern EFI_GUID efi_loaded_image_protocol_guid;
+extern EFI_GUID efi_simple_file_system_protocol_guid;
+
+#endif /* _EFI_H */
--- /dev/null
+/** @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.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __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
+
--- /dev/null
+/** @file
+ Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.SetInfo()
+ and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information.
+ This GUID is defined in UEFI specification.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __FILE_INFO_H__
+#define __FILE_INFO_H__
+
+#define EFI_FILE_INFO_ID \
+ { \
+ 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+typedef struct {
+ ///
+ /// The size of the EFI_FILE_INFO structure, including the Null-terminated FileName string.
+ ///
+ UINT64 Size;
+ ///
+ /// The size of the file in bytes.
+ ///
+ UINT64 FileSize;
+ ///
+ /// PhysicalSize The amount of physical space the file consumes on the file system volume.
+ ///
+ UINT64 PhysicalSize;
+ ///
+ /// The time the file was created.
+ ///
+ EFI_TIME CreateTime;
+ ///
+ /// The time when the file was last accessed.
+ ///
+ EFI_TIME LastAccessTime;
+ ///
+ /// The time when the file's contents were last modified.
+ ///
+ EFI_TIME ModificationTime;
+ ///
+ /// The attribute bits for the file.
+ ///
+ UINT64 Attribute;
+ ///
+ /// The Null-terminated name of the file.
+ ///
+ CHAR16 FileName[1];
+} EFI_FILE_INFO;
+
+///
+/// The FileName field of the EFI_FILE_INFO data structure is variable length.
+/// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to
+/// be the size of the data structure without the FileName field. The following macro
+/// computes this size correctly no matter how big the FileName array is declared.
+/// This is required to make the EFI_FILE_INFO data structure ANSI compilant.
+///
+#define SIZE_OF_EFI_FILE_INFO OFFSET_OF (EFI_FILE_INFO, FileName)
+
+extern EFI_GUID gEfiFileInfoGuid;
+
+#endif
--- /dev/null
+/** @file
+ Guid used to identify HII FormMap configuration method.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.2 spec.
+**/
+
+#ifndef __EFI_HII_FORMMAP_GUID_H__
+#define __EFI_HII_FORMMAP_GUID_H__
+
+#define EFI_HII_STANDARD_FORM_GUID \
+ { 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } }
+
+extern EFI_GUID gEfiHiiStandardFormGuid;
+
+#endif
--- /dev/null
+/** @file
+ Terminal Device Path Vendor Guid.
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUIDs defined in UEFI 2.0 spec.
+
+**/
+
+#ifndef __PC_ANSI_H__
+#define __PC_ANSI_H__
+
+#define EFI_PC_ANSI_GUID \
+ { \
+ 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+#define EFI_VT_100_GUID \
+ { \
+ 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+#define EFI_VT_100_PLUS_GUID \
+ { \
+ 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \
+ }
+
+#define EFI_VT_UTF8_GUID \
+ { \
+ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \
+ }
+
+#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \
+ { \
+ 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \
+ }
+
+#define EFI_SAS_DEVICE_PATH_GUID \
+ { \
+ 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \
+ }
+
+extern EFI_GUID gEfiPcAnsiGuid;
+extern EFI_GUID gEfiVT100Guid;
+extern EFI_GUID gEfiVT100PlusGuid;
+extern EFI_GUID gEfiVTUTF8Guid;
+extern EFI_GUID gEfiUartDevicePathGuid;
+extern EFI_GUID gEfiSasDevicePathGuid;
+
+#endif
--- /dev/null
+/** @file
+ GUID for UEFI WIN_CERTIFICATE structure.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.0 spec.
+**/
+
+#ifndef __EFI_WIN_CERTIFICATE_H__
+#define __EFI_WIN_CERTIFICATE_H__
+
+//
+// _WIN_CERTIFICATE.wCertificateType
+//
+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
+#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0
+#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
+
+///
+/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
+///
+typedef struct {
+ ///
+ /// The length of the entire certificate,
+ /// including the length of the header, in bytes.
+ ///
+ UINT32 dwLength;
+ ///
+ /// The revision level of the WIN_CERTIFICATE
+ /// structure. The current revision level is 0x0200.
+ ///
+ UINT16 wRevision;
+ ///
+ /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
+ /// certificate types. The UEFI specification reserves the range of
+ /// certificate type values from 0x0EF0 to 0x0EFF.
+ ///
+ UINT16 wCertificateType;
+ ///
+ /// The following is the actual certificate. The format of
+ /// the certificate depends on wCertificateType.
+ ///
+ /// UINT8 bCertificate[ANYSIZE_ARRAY];
+ ///
+} WIN_CERTIFICATE;
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertType
+///
+#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \
+ {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertData
+///
+typedef struct {
+ EFI_GUID HashType;
+ UINT8 PublicKey[256];
+ UINT8 Signature[256];
+} EFI_CERT_BLOCK_RSA_2048_SHA256;
+
+
+///
+/// Certificate which encapsulates a GUID-specific digital signature
+///
+typedef struct {
+ ///
+ /// This is the standard WIN_CERTIFICATE header, where
+ /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.
+ ///
+ WIN_CERTIFICATE Hdr;
+ ///
+ /// This is the unique id which determines the
+ /// format of the CertData. .
+ ///
+ EFI_GUID CertType;
+ ///
+ /// The following is the certificate data. The format of
+ /// the data is determined by the CertType.
+ /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
+ /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
+ ///
+ UINT8 CertData[1];
+} WIN_CERTIFICATE_UEFI_GUID;
+
+
+///
+/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
+///
+/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
+/// WIN_CERTIFICATE and encapsulate the information needed to
+/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as
+/// specified in RFC2437.
+///
+typedef struct {
+ ///
+ /// This is the standard WIN_CERTIFICATE header, where
+ /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.
+ ///
+ WIN_CERTIFICATE Hdr;
+ ///
+ /// This is the hashing algorithm which was performed on the
+ /// UEFI executable when creating the digital signature.
+ ///
+ EFI_GUID HashAlgorithm;
+ ///
+ /// The following is the actual digital signature. The
+ /// size of the signature is the same size as the key
+ /// (1024-bit key is 128 bytes) and can be determined by
+ /// subtracting the length of the other parts of this header
+ /// from the total length of the certificate as found in
+ /// Hdr.dwLength.
+ ///
+ /// UINT8 Signature[];
+ ///
+} WIN_CERTIFICATE_EFI_PKCS1_15;
+
+extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid;
+
+#endif
--- /dev/null
+/** @file
+ Processor or Compiler specific defines and types for IA-32 architecture.
+
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+///
+/// Define the processor type so other code can make processor based choices.
+///
+#define MDE_CPU_IA32
+
+//
+// Make sure we are using the correct packing rules per EFI specification
+//
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#if defined(__INTEL_COMPILER)
+//
+// Disable ICC's remark #869: "Parameter" was never referenced warning.
+// This is legal ANSI C code so we disable the remark that is turned on with -Wall
+//
+#pragma warning ( disable : 869 )
+
+//
+// Disable ICC's remark #1418: external function definition with no prior declaration.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1418 )
+
+//
+// Disable ICC's remark #1419: external declaration in primary source file
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1419 )
+
+//
+// Disable ICC's remark #593: "Variable" was set but never used.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 593 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+//
+// This warning is caused by functions defined but not used. For precompiled header only.
+//
+#pragma warning ( disable : 4505 )
+
+//
+// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
+//
+#pragma warning ( disable : 4206 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+ //
+ // use Microsoft C complier dependent integer width types
+ //
+
+ ///
+ /// 8-byte unsigned value.
+ ///
+ typedef unsigned __int64 UINT64;
+ ///
+ /// 8-byte signed value.
+ ///
+ typedef __int64 INT64;
+ ///
+ /// 4-byte unsigned value.
+ ///
+ typedef unsigned __int32 UINT32;
+ ///
+ /// 4-byte signed value.
+ ///
+ typedef __int32 INT32;
+ ///
+ /// 2-byte unsigned value.
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value.
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value.
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character.
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value.
+ ///
+ typedef signed char INT8;
+#else
+ ///
+ /// 8-byte unsigned value.
+ ///
+ typedef unsigned long long UINT64;
+ ///
+ /// 8-byte signed value.
+ ///
+ typedef long long INT64;
+ ///
+ /// 4-byte unsigned value.
+ ///
+ typedef unsigned int UINT32;
+ ///
+ /// 4-byte signed value.
+ ///
+ typedef int INT32;
+ ///
+ /// 2-byte unsigned value.
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value.
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value.
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef signed char INT8;
+#endif
+
+///
+/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;
+/// 8 bytes on supported 64-bit processor instructions.)
+///
+typedef UINT32 UINTN;
+///
+/// Signed value of native width. (4 bytes on supported 32-bit processor instructions;
+/// 8 bytes on supported 64-bit processor instructions.)
+///
+typedef INT32 INTN;
+
+//
+// Processor specific defines
+//
+
+///
+/// A value of native width with the highest bit set.
+///
+#define MAX_BIT 0x80000000
+///
+/// A value of native width with the two highest bits set.
+///
+#define MAX_2_BITS 0xC0000000
+
+///
+/// Maximum legal IA-32 address.
+///
+#define MAX_ADDRESS 0xFFFFFFFF
+
+///
+/// Maximum legal IA-32 INTN and UINTN values.
+///
+#define MAX_INTN ((INTN)0x7FFFFFFF)
+#define MAX_UINTN ((UINTN)0xFFFFFFFF)
+
+///
+/// The stack alignment required for IA-32.
+///
+#define CPU_STACK_ALIGNMENT sizeof(UINTN)
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify their member functions with EFIAPI.
+//
+#ifdef EFIAPI
+ ///
+ /// If EFIAPI is already defined, then we use that definition.
+ ///
+#elif defined(_MSC_EXTENSIONS)
+ ///
+ /// Microsoft* compiler specific method for EFIAPI calling convention.
+ ///
+ #define EFIAPI __cdecl
+#elif defined(__GNUC__)
+ ///
+ /// GCC specific method for EFIAPI calling convention.
+ ///
+ #define EFIAPI __attribute__((cdecl))
+#else
+ ///
+ /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI
+ /// is the standard.
+ ///
+ #define EFIAPI
+#endif
+
+#if defined(__GNUC__)
+ ///
+ /// For GNU assembly code, .global or .globl can declare global symbols.
+ /// Define this macro to unify the usage.
+ ///
+ #define ASM_GLOBAL .globl
+#endif
+
+/**
+ Return the pointer to the first instruction of a function given a function pointer.
+ On IA-32 CPU architectures, these two pointer values are the same,
+ so the implementation of this macro is very simple.
+
+ @param FunctionPointer A pointer to a function.
+
+ @return The pointer to the first instruction of a function given a function pointer.
+
+**/
+#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
+
+#endif
+
--- /dev/null
+/** @file
+ EFI image format for PE32, PE32+ and TE. Please note some data structures are
+ different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
+ EFI_IMAGE_NT_HEADERS64 is for PE32+.
+
+ This file is coded to the Visual Studio, Microsoft Portable Executable and
+ Common Object File Format Specification, Revision 8.3 - February 6, 2013.
+ This file also includes some definitions in PI Specification, Revision 1.0.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PE_IMAGE_H__
+#define __PE_IMAGE_H__
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0
+
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+#define IMAGE_FILE_MACHINE_EBC 0x0EBC
+#define IMAGE_FILE_MACHINE_X64 0x8664
+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
+#define IMAGE_FILE_MACHINE_ARM64 0xAA64
+
+//
+// EXE file formats
+//
+#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
+#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E')
+#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E')
+#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+ UINT16 e_magic; ///< Magic number.
+ UINT16 e_cblp; ///< Bytes on last page of file.
+ UINT16 e_cp; ///< Pages in file.
+ UINT16 e_crlc; ///< Relocations.
+ UINT16 e_cparhdr; ///< Size of header in paragraphs.
+ UINT16 e_minalloc; ///< Minimum extra paragraphs needed.
+ UINT16 e_maxalloc; ///< Maximum extra paragraphs needed.
+ UINT16 e_ss; ///< Initial (relative) SS value.
+ UINT16 e_sp; ///< Initial SP value.
+ UINT16 e_csum; ///< Checksum.
+ UINT16 e_ip; ///< Initial IP value.
+ UINT16 e_cs; ///< Initial (relative) CS value.
+ UINT16 e_lfarlc; ///< File address of relocation table.
+ UINT16 e_ovno; ///< Overlay number.
+ UINT16 e_res[4]; ///< Reserved words.
+ UINT16 e_oemid; ///< OEM identifier (for e_oeminfo).
+ UINT16 e_oeminfo; ///< OEM information; e_oemid specific.
+ UINT16 e_res2[10]; ///< Reserved words.
+ UINT32 e_lfanew; ///< File address of new exe header.
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// COFF File Header (Object and Image).
+///
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+///
+/// Size of EFI_IMAGE_FILE_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+//
+// Characteristics
+//
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED BIT0 ///< 0x0001 Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file.
+#define EFI_IMAGE_FILE_SYSTEM BIT12 ///< 0x1000 System File.
+#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed.
+
+///
+/// Header Data Directories.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+///
+/// Optional Header Standard Fields for PE32.
+///
+typedef struct {
+ ///
+ /// Standard fields.
+ ///
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+.
+ ///
+ /// Optional Header Windows-Specific Fields.
+ ///
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+///
+/// Optional Header Standard Fields for PE32+.
+///
+typedef struct {
+ ///
+ /// Standard fields.
+ ///
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ ///
+ /// Optional Header Windows-Specific Fields.
+ ///
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+///
+/// @attention
+/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Other Windows Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+///
+/// Length of ShortName.
+///
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+///
+/// Section Table. This table immediately follows the optional header.
+///
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+///
+/// Size of EFI_IMAGE_SECTION_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+//
+// Section Flags Values
+//
+#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000
+
+///
+/// Size of a Symbol Table Record.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item.
+
+//
+// Symbol Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type.
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Symbol Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1)
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+//
+// the following values only be referred in PeCoff, not defined in PECOFF.
+//
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+///
+/// Relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_RELOCATION
+///
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary.
+#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included.
+#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
+#define EFI_IMAGE_REL_I386_SECTION 0x000A
+#define EFI_IMAGE_REL_I386_SECREL 0x000B
+#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address.
+
+//
+// x64 processor relocation types.
+//
+#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
+#define IMAGE_REL_AMD64_ADDR64 0x0001
+#define IMAGE_REL_AMD64_ADDR32 0x0002
+#define IMAGE_REL_AMD64_ADDR32NB 0x0003
+#define IMAGE_REL_AMD64_REL32 0x0004
+#define IMAGE_REL_AMD64_REL32_1 0x0005
+#define IMAGE_REL_AMD64_REL32_2 0x0006
+#define IMAGE_REL_AMD64_REL32_3 0x0007
+#define IMAGE_REL_AMD64_REL32_4 0x0008
+#define IMAGE_REL_AMD64_REL32_5 0x0009
+#define IMAGE_REL_AMD64_SECTION 0x000A
+#define IMAGE_REL_AMD64_SECREL 0x000B
+#define IMAGE_REL_AMD64_SECREL7 0x000C
+#define IMAGE_REL_AMD64_TOKEN 0x000D
+#define IMAGE_REL_AMD64_SREL32 0x000E
+#define IMAGE_REL_AMD64_PAIR 0x000F
+#define IMAGE_REL_AMD64_SSPAN32 0x0010
+
+///
+/// Based relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_BASE_RELOCATION.
+///
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+///
+/// Line number format.
+///
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; ///< Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; ///< Line number.
+} EFI_IMAGE_LINENUMBER;
+
+///
+/// Size of EFI_IMAGE_LINENUMBER.
+///
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+///
+/// Archive Member Headers
+///
+typedef struct {
+ UINT8 Name[16]; ///< File member name - `/' terminated.
+ UINT8 Date[12]; ///< File member date - decimal.
+ UINT8 UserID[6]; ///< File member user id - decimal.
+ UINT8 GroupID[6]; ///< File member group id - decimal.
+ UINT8 Mode[8]; ///< File member mode - octal.
+ UINT8 Size[10]; ///< File member size - decimal.
+ UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+///
+/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+
+//
+// DLL Support
+//
+
+///
+/// Export Directory Table.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// Hint/Name Table.
+///
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+///
+/// Import Address Table RVA (Thunk Table).
+///
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32.
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+///
+/// Import Directory Table
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+
+///
+/// Debug Directory Format.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base.
+ UINT32 FileOffset; ///< The file pointer to the debug data.
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0')
+typedef struct {
+ UINT32 Signature; ///< "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S')
+typedef struct {
+ UINT32 Signature; ///< "RSDS".
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+
+///
+/// Debug Data Structure defined by Apple Mach-O to Coff utility.
+///
+#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C')
+typedef struct {
+ UINT32 Signature; ///< "MTOC".
+ GUID MachOUuid;
+ //
+ // Filename of .DLL (Mach-O with debug info) goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
+
+///
+/// Resource format.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT16 NumberOfNamedEntries;
+ UINT16 NumberOfIdEntries;
+ //
+ // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
+ //
+} EFI_IMAGE_RESOURCE_DIRECTORY;
+
+///
+/// Resource directory entry format.
+///
+typedef struct {
+ union {
+ struct {
+ UINT32 NameOffset:31;
+ UINT32 NameIsString:1;
+ } s;
+ UINT32 Id;
+ } u1;
+ union {
+ UINT32 OffsetToData;
+ struct {
+ UINT32 OffsetToDirectory:31;
+ UINT32 DataIsDirectory:1;
+ } s;
+ } u2;
+} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+///
+/// Resource directory entry for string.
+///
+typedef struct {
+ UINT16 Length;
+ CHAR16 String[1];
+} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
+
+///
+/// Resource directory entry for data array.
+///
+typedef struct {
+ UINT32 OffsetToData;
+ UINT32 Size;
+ UINT32 CodePage;
+ UINT32 Reserved;
+} EFI_IMAGE_RESOURCE_DATA_ENTRY;
+
+///
+/// Header format for TE images, defined in the PI Specification, 1.0.
+///
+typedef struct {
+ UINT16 Signature; ///< The signature for TE format = "VZ".
+ UINT16 Machine; ///< From the original file header.
+ UINT8 NumberOfSections; ///< From the original file header.
+ UINT8 Subsystem; ///< From original optional header.
+ UINT16 StrippedSize; ///< Number of bytes we removed from the header.
+ UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header.
+ UINT32 BaseOfCode; ///< From original image -- required for ITP debug.
+ UINT64 ImageBase; ///< From original file header.
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory.
+} EFI_TE_IMAGE_HEADER;
+
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z')
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+
+///
+/// Union of PE32, PE32+, and TE headers.
+///
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 Pe32;
+ EFI_IMAGE_NT_HEADERS64 Pe32Plus;
+ EFI_TE_IMAGE_HEADER Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 *Pe32;
+ EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
+ EFI_TE_IMAGE_HEADER *Te;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
+#endif
--- /dev/null
+#ifndef _WIMBOOT_EFI_PROCESSOR_BIND_H
+#define _WIMBOOT_EFI_PROCESSOR_BIND_H
+
+/*
+ * EFI header files rely on having the CPU architecture directory
+ * present in the search path in order to pick up ProcessorBind.h. We
+ * use this header file as a quick indirection layer.
+ *
+ */
+
+#if __i386__
+#include <efi/Ia32/ProcessorBind.h>
+#endif
+
+#if __x86_64__
+#include <efi/X64/ProcessorBind.h>
+#endif
+
+#endif /* _WIMBOOT_EFI_PROCESSOR_BIND_H */
--- /dev/null
+/** @file
+ Block IO protocol as defined in the UEFI 2.0 specification.
+
+ The Block IO protocol is used to abstract block devices like hard drives,
+ DVD-ROMs and floppy drives.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __BLOCK_IO_H__
+#define __BLOCK_IO_H__
+
+#define EFI_BLOCK_IO_PROTOCOL_GUID \
+ { \
+ 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL;
+
+///
+/// Protocol GUID name defined in EFI1.1.
+///
+#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID
+
+///
+/// Protocol defined in EFI1.1.
+///
+typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO;
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BLOCK_RESET)(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BLOCK_READ)(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BLOCK_WRITE)(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BLOCK_FLUSH)(
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+/**
+ Block IO read only mode data and updated only via members of BlockIO
+**/
+typedef struct {
+ ///
+ /// The curent media Id. If the media changes, this value is changed.
+ ///
+ UINT32 MediaId;
+
+ ///
+ /// TRUE if the media is removable; otherwise, FALSE.
+ ///
+ BOOLEAN RemovableMedia;
+
+ ///
+ /// TRUE if there is a media currently present in the device;
+ /// othersise, FALSE. THis field shows the media present status
+ /// as of the most recent ReadBlocks() or WriteBlocks() call.
+ ///
+ BOOLEAN MediaPresent;
+
+ ///
+ /// TRUE if LBA 0 is the first block of a partition; otherwise
+ /// FALSE. For media with only one partition this would be TRUE.
+ ///
+ BOOLEAN LogicalPartition;
+
+ ///
+ /// TRUE if the media is marked read-only otherwise, FALSE.
+ /// This field shows the read-only status as of the most recent WriteBlocks () call.
+ ///
+ BOOLEAN ReadOnly;
+
+ ///
+ /// TRUE if the WriteBlock () function caches write data.
+ ///
+ BOOLEAN WriteCaching;
+
+ ///
+ /// The intrinsic block size of the device. If the media changes, then
+ /// this field is updated.
+ ///
+ UINT32 BlockSize;
+
+ ///
+ /// Supplies the alignment requirement for any buffer to read or write block(s).
+ ///
+ UINT32 IoAlign;
+
+ ///
+ /// The last logical block address on the device.
+ /// If the media changes, then this field is updated.
+ ///
+ EFI_LBA LastBlock;
+
+ ///
+ /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
+ /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to
+ /// a physical block boundary.
+ ///
+ EFI_LBA LowestAlignedLba;
+
+ ///
+ /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
+ /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks
+ /// per physical block.
+ ///
+ UINT32 LogicalBlocksPerPhysicalBlock;
+
+ ///
+ /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
+ /// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length
+ /// granularity as a number of logical blocks.
+ ///
+ UINT32 OptimalTransferLengthGranularity;
+} EFI_BLOCK_IO_MEDIA;
+
+#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
+#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
+
+///
+/// Revision defined in EFI1.1.
+///
+#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION
+
+///
+/// This protocol provides control over block devices.
+///
+struct _EFI_BLOCK_IO_PROTOCOL {
+ ///
+ /// The revision to which the block IO interface adheres. All future
+ /// revisions must be backwards compatible. If a future version is not
+ /// back wards compatible, it is not the same GUID.
+ ///
+ UINT64 Revision;
+ ///
+ /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
+ ///
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ EFI_BLOCK_RESET Reset;
+ EFI_BLOCK_READ ReadBlocks;
+ EFI_BLOCK_WRITE WriteBlocks;
+ EFI_BLOCK_FLUSH FlushBlocks;
+
+};
+
+extern EFI_GUID gEfiBlockIoProtocolGuid;
+
+#endif
--- /dev/null
+/** @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.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __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
--- /dev/null
+/** @file
+ Graphics Output Protocol from the UEFI 2.0 specification.
+
+ Abstraction of a very simple graphics device.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GRAPHICS_OUTPUT_H__
+#define __GRAPHICS_OUTPUT_H__
+
+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
+ { \
+ 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \
+ }
+
+typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL;
+
+typedef struct {
+ UINT32 RedMask;
+ UINT32 GreenMask;
+ UINT32 BlueMask;
+ UINT32 ReservedMask;
+} EFI_PIXEL_BITMASK;
+
+typedef enum {
+ ///
+ /// A pixel is 32-bits and byte zero represents red, byte one represents green,
+ /// byte two represents blue, and byte three is reserved. This is the definition
+ /// for the physical frame buffer. The byte values for the red, green, and blue
+ /// components represent the color intensity. This color intensity value range
+ /// from a minimum intensity of 0 to maximum intensity of 255.
+ ///
+ PixelRedGreenBlueReserved8BitPerColor,
+ ///
+ /// A pixel is 32-bits and byte zero represents blue, byte one represents green,
+ /// byte two represents red, and byte three is reserved. This is the definition
+ /// for the physical frame buffer. The byte values for the red, green, and blue
+ /// components represent the color intensity. This color intensity value range
+ /// from a minimum intensity of 0 to maximum intensity of 255.
+ ///
+ PixelBlueGreenRedReserved8BitPerColor,
+ ///
+ /// The Pixel definition of the physical frame buffer.
+ ///
+ PixelBitMask,
+ ///
+ /// This mode does not support a physical frame buffer.
+ ///
+ PixelBltOnly,
+ ///
+ /// Valid EFI_GRAPHICS_PIXEL_FORMAT enum values are less than this value.
+ ///
+ PixelFormatMax
+} EFI_GRAPHICS_PIXEL_FORMAT;
+
+typedef struct {
+ ///
+ /// The version of this data structure. A value of zero represents the
+ /// EFI_GRAPHICS_OUTPUT_MODE_INFORMATION structure as defined in this specification.
+ ///
+ UINT32 Version;
+ ///
+ /// The size of video screen in pixels in the X dimension.
+ ///
+ UINT32 HorizontalResolution;
+ ///
+ /// The size of video screen in pixels in the Y dimension.
+ ///
+ UINT32 VerticalResolution;
+ ///
+ /// Enumeration that defines the physical format of the pixel. A value of PixelBltOnly
+ /// implies that a linear frame buffer is not available for this mode.
+ ///
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+ ///
+ /// This bit-mask is only valid if PixelFormat is set to PixelPixelBitMask.
+ /// A bit being set defines what bits are used for what purpose such as Red, Green, Blue, or Reserved.
+ ///
+ EFI_PIXEL_BITMASK PixelInformation;
+ ///
+ /// Defines the number of pixel elements per video memory line.
+ ///
+ UINT32 PixelsPerScanLine;
+} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
+
+/**
+ Returns information for an available graphics mode that the graphics device
+ and the set of active video output devices supports.
+
+ @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+ @param ModeNumber The mode number to return information on.
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
+ @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
+
+ @retval EFI_SUCCESS Valid mode information was returned.
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
+ @retval EFI_INVALID_PARAMETER ModeNumber is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+/**
+ Set the video device into the specified mode and clears the visible portions of
+ the output display to black.
+
+ @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+ @param ModeNumber Abstraction that defines the current video mode.
+
+ @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ );
+
+typedef struct {
+ UINT8 Blue;
+ UINT8 Green;
+ UINT8 Red;
+ UINT8 Reserved;
+} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
+
+typedef union {
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel;
+ UINT32 Raw;
+} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION;
+
+///
+/// actions for BltOperations
+///
+typedef enum {
+ ///
+ /// Write data from the BltBuffer pixel (0, 0)
+ /// directly to every pixel of the video display rectangle
+ /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
+ /// Only one pixel will be used from the BltBuffer. Delta is NOT used.
+ ///
+ EfiBltVideoFill,
+
+ ///
+ /// Read data from the video display rectangle
+ /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
+ /// the BltBuffer rectangle (DestinationX, DestinationY )
+ /// (DestinationX + Width, DestinationY + Height). If DestinationX or
+ /// DestinationY is not zero then Delta must be set to the length in bytes
+ /// of a row in the BltBuffer.
+ ///
+ EfiBltVideoToBltBuffer,
+
+ ///
+ /// Write data from the BltBuffer rectangle
+ /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
+ /// video display rectangle (DestinationX, DestinationY)
+ /// (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
+ /// not zero then Delta must be set to the length in bytes of a row in the
+ /// BltBuffer.
+ ///
+ EfiBltBufferToVideo,
+
+ ///
+ /// Copy from the video display rectangle (SourceX, SourceY)
+ /// (SourceX + Width, SourceY + Height) to the video display rectangle
+ /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
+ /// The BltBuffer and Delta are not used in this mode.
+ ///
+ EfiBltVideoToVideo,
+
+ EfiGraphicsOutputBltOperationMax
+} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
+
+/**
+ Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
+
+ @param This Protocol instance pointer.
+ @param BltBuffer The data to transfer to the graphics screen.
+ Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
+ @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen.
+ @param SourceX The X coordinate of source for the BltOperation.
+ @param SourceY The Y coordinate of source for the BltOperation.
+ @param DestinationX The X coordinate of destination for the BltOperation.
+ @param DestinationY The Y coordinate of destination for the BltOperation.
+ @param Width The width of a rectangle in the blt rectangle in pixels.
+ @param Height The height of a rectangle in the blt rectangle in pixels.
+ @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation.
+ If a Delta of zero is used, the entire BltBuffer is being operated on.
+ If a subrectangle of the BltBuffer is being used then Delta
+ represents the number of bytes in a row of the BltBuffer.
+
+ @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen.
+ @retval EFI_INVALID_PARAMETER BltOperation is not valid.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ );
+
+typedef struct {
+ ///
+ /// The number of modes supported by QueryMode() and SetMode().
+ ///
+ UINT32 MaxMode;
+ ///
+ /// Current Mode of the graphics device. Valid mode numbers are 0 to MaxMode -1.
+ ///
+ UINT32 Mode;
+ ///
+ /// Pointer to read-only EFI_GRAPHICS_OUTPUT_MODE_INFORMATION data.
+ ///
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ ///
+ /// Size of Info structure in bytes.
+ ///
+ UINTN SizeOfInfo;
+ ///
+ /// Base address of graphics linear frame buffer.
+ /// Offset zero in FrameBufferBase represents the upper left pixel of the display.
+ ///
+ EFI_PHYSICAL_ADDRESS FrameBufferBase;
+ ///
+ /// Amount of frame buffer needed to support the active mode as defined by
+ /// PixelsPerScanLine xVerticalResolution x PixelElementSize.
+ ///
+ UINTN FrameBufferSize;
+} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
+
+///
+/// Provides a basic abstraction to set video modes and copy pixels to and from
+/// the graphics controller's frame buffer. The linear address of the hardware
+/// frame buffer is also exposed so software can write directly to the video hardware.
+///
+struct _EFI_GRAPHICS_OUTPUT_PROTOCOL {
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
+ ///
+ /// Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data.
+ ///
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
+};
+
+extern EFI_GUID gEfiGraphicsOutputProtocolGuid;
+
+#endif
--- /dev/null
+/** @file
+ UEFI 2.0 Loaded image protocol definition.
+
+ Every EFI driver and application is passed an image handle when it is loaded.
+ This image handle will contain a Loaded Image Protocol.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __LOADED_IMAGE_PROTOCOL_H__
+#define __LOADED_IMAGE_PROTOCOL_H__
+
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
+ { \
+ 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \
+ }
+
+#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \
+ { \
+ 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \
+ }
+
+///
+/// Protocol GUID defined in EFI1.1.
+///
+#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
+
+///
+/// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h
+///
+#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
+
+///
+/// Revision defined in EFI1.1.
+///
+#define EFI_LOADED_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION
+
+///
+/// Can be used on any image handle to obtain information about the loaded image.
+///
+typedef struct {
+ UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure.
+ ///< All future revisions will be backward compatible to the current revision.
+ EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from
+ ///< the firmware's boot manager.
+ EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer.
+
+ //
+ // Source location of image
+ //
+ EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from.
+ EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle
+ ///< that the EFI Image was loaded from.
+ VOID *Reserved; ///< Reserved. DO NOT USE.
+
+ //
+ // Images load options
+ //
+ UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions.
+ VOID *LoadOptions; ///< A pointer to the image's binary load options.
+
+ //
+ // Location of where image was loaded
+ //
+ VOID *ImageBase; ///< The base address at which the image was loaded.
+ UINT64 ImageSize; ///< The size in bytes of the loaded image.
+ EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as.
+ EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as.
+ EFI_IMAGE_UNLOAD Unload;
+} EFI_LOADED_IMAGE_PROTOCOL;
+
+//
+// For backward-compatible with EFI1.1.
+//
+typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE;
+
+extern EFI_GUID gEfiLoadedImageProtocolGuid;
+extern EFI_GUID gEfiLoadedImageDevicePathProtocolGuid;
+
+#endif
--- /dev/null
+/** @file
+ SimpleFileSystem protocol as defined in the UEFI 2.0 specification.
+
+ The SimpleFileSystem protocol is the programmatic access to the FAT (12,16,32)
+ file system specified in UEFI 2.0. It can also be used to abstract a file
+ system other than FAT.
+
+ UEFI 2.0 can boot from any valid EFI image contained in a SimpleFileSystem.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_FILE_SYSTEM_H__
+#define __SIMPLE_FILE_SYSTEM_H__
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+ { \
+ 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
+
+typedef struct _EFI_FILE_PROTOCOL EFI_FILE_PROTOCOL;
+typedef struct _EFI_FILE_PROTOCOL *EFI_FILE_HANDLE;
+
+///
+/// Protocol GUID name defined in EFI1.1.
+///
+#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID
+
+///
+/// Protocol name defined in EFI1.1.
+///
+typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE;
+typedef EFI_FILE_PROTOCOL EFI_FILE;
+
+/**
+ Open the root directory on a volume.
+
+ @param This A pointer to the volume to open the root directory.
+ @param Root A pointer to the location to return the opened file handle for the
+ root directory.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_UNSUPPORTED This volume does not support the requested file system type.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported. Any existing file handles for this volume are
+ no longer valid. To access the files on the new medium, the
+ volume must be reopened with OpenVolume().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)(
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ );
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000
+
+///
+/// Revision defined in EFI1.1
+///
+#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
+
+struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
+ ///
+ /// The version of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. The version
+ /// specified by this specification is 0x00010000. All future revisions
+ /// must be backwards compatible.
+ ///
+ UINT64 Revision;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
+};
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to the source location. This would typically be an open
+ handle to a directory.
+ @param NewHandle A pointer to the location to return the opened handle for the new
+ file.
+ @param FileName The Null-terminated string of the name of the file to be opened.
+ The file name may contain the following path modifiers: "\", ".",
+ and "..".
+ @param OpenMode The mode to open the file. The only valid combinations that the
+ file may be opened with are: Read, Read/Write, or Create/Read/Write.
+ @param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
+ attribute bits for the newly created file.
+
+ @retval EFI_SUCCESS The file was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_OPEN)(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+//
+// Open modes
+//
+#define EFI_FILE_MODE_READ 0x0000000000000001ULL
+#define EFI_FILE_MODE_WRITE 0x0000000000000002ULL
+#define EFI_FILE_MODE_CREATE 0x8000000000000000ULL
+
+//
+// File attributes
+//
+#define EFI_FILE_READ_ONLY 0x0000000000000001ULL
+#define EFI_FILE_HIDDEN 0x0000000000000002ULL
+#define EFI_FILE_SYSTEM 0x0000000000000004ULL
+#define EFI_FILE_RESERVED 0x0000000000000008ULL
+#define EFI_FILE_DIRECTORY 0x0000000000000010ULL
+#define EFI_FILE_ARCHIVE 0x0000000000000020ULL
+#define EFI_FILE_VALID_ATTR 0x0000000000000037ULL
+
+/**
+ Closes a specified file handle.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to close.
+
+ @retval EFI_SUCCESS The file was closed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_CLOSE)(
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+/**
+ Close and delete the file handle.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ handle to the file to delete.
+
+ @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_DELETE)(
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+/**
+ Reads data from a file.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to read data from.
+ @param BufferSize On input, the size of the Buffer. On output, the amount of data
+ returned in Buffer. In both cases, the size is measured in bytes.
+ @param Buffer The buffer into which the data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
+ @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
+ entry. BufferSize has been updated with the size
+ needed to complete the request.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_READ)(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes data to a file.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to write data to.
+ @param BufferSize On input, the size of the Buffer. On output, the amount of data
+ actually written. In both cases, the size is measured in bytes.
+ @param Buffer The buffer of data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to open directory files are not supported.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_WRITE)(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Sets a file's current position.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ file handle to set the requested position on.
+ @param Position The byte position from the start of the file to set.
+
+ @retval EFI_SUCCESS The position was set.
+ @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open
+ directories.
+ @retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_SET_POSITION)(
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ );
+
+/**
+ Returns a file's current position.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to get the current position on.
+ @param Position The address to return the file's current position value.
+
+ @retval EFI_SUCCESS The position was returned.
+ @retval EFI_UNSUPPORTED The request is not valid on open directories.
+ @retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_GET_POSITION)(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ );
+
+/**
+ Returns information about a file.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle the requested information is for.
+ @param InformationType The type identifier for the information being requested.
+ @param BufferSize On input, the size of Buffer. On output, the amount of data
+ returned in Buffer. In both cases, the size is measured in bytes.
+ @param Buffer A pointer to the data buffer to return. The buffer's type is
+ indicated by InformationType.
+
+ @retval EFI_SUCCESS The information was returned.
+ @retval EFI_UNSUPPORTED The InformationType is not known.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
+ BufferSize has been updated with the size needed to complete
+ the request.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_GET_INFO)(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Sets information about a file.
+
+ @param File A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle the information is for.
+ @param InformationType The type identifier for the information being set.
+ @param BufferSize The size, in bytes, of Buffer.
+ @param Buffer A pointer to the data buffer to write. The buffer's type is
+ indicated by InformationType.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_UNSUPPORTED The InformationType is not known.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the media is
+ read-only.
+ @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_PROTOCOL_SYSTEM_INFO_ID
+ and the media is read only.
+ @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_SYSTEM_VOLUME_LABEL_ID
+ and the media is read-only.
+ @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a
+ file that is already present.
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the EFI_FILE_DIRECTORY
+ Attribute.
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the size of a directory.
+ @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the file was opened
+ read-only and an attempt is being made to modify a field
+ other than Attribute.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type indicated
+ by InformationType.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_SET_INFO)(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flushes all modified data associated with a file to a device.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to flush.
+
+ @retval EFI_SUCCESS The data was flushed.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read-only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_FLUSH)(
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+typedef struct {
+ //
+ // If Event is NULL, then blocking I/O is performed.
+ // If Event is not NULL and non-blocking I/O is supported, then non-blocking I/O is performed,
+ // and Event will be signaled when the read request is completed.
+ // The caller must be prepared to handle the case where the callback associated with Event
+ // occurs before the original asynchronous I/O request call returns.
+ //
+ EFI_EVENT Event;
+
+ //
+ // Defines whether or not the signaled event encountered an error.
+ //
+ EFI_STATUS Status;
+
+ //
+ // For OpenEx(): Not Used, ignored.
+ // For ReadEx(): On input, the size of the Buffer. On output, the amount of data returned in Buffer.
+ // In both cases, the size is measured in bytes.
+ // For WriteEx(): On input, the size of the Buffer. On output, the amount of data actually written.
+ // In both cases, the size is measured in bytes.
+ // For FlushEx(): Not used, ignored.
+ //
+ UINTN BufferSize;
+
+ //
+ // For OpenEx(): Not Used, ignored.
+ // For ReadEx(): The buffer into which the data is read.
+ // For WriteEx(): The buffer of data to write.
+ // For FlushEx(): Not Used, ignored.
+ //
+ VOID *Buffer;
+} EFI_FILE_IO_TOKEN;
+
+/**
+ Opens a new file relative to the source directory's location.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to the source location.
+ @param NewHandle A pointer to the location to return the opened handle for the new
+ file.
+ @param FileName The Null-terminated string of the name of the file to be opened.
+ The file name may contain the following path modifiers: "\", ".",
+ and "..".
+ @param OpenMode The mode to open the file. The only valid combinations that the
+ file may be opened with are: Read, Read/Write, or Create/Read/Write.
+ @param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
+ attribute bits for the newly created file.
+ @param Token A pointer to the token associated with the transaction.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
+ If Event is not NULL (asynchronous I/O): The request was successfully
+ queued for processing.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_OPEN_EX)(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes,
+ IN OUT EFI_FILE_IO_TOKEN *Token
+ );
+
+
+/**
+ Reads data from a file.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to read data from.
+ @param Token A pointer to the token associated with the transaction.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
+ If Event is not NULL (asynchronous I/O): The request was successfully
+ queued for processing.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
+ @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_READ_EX) (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT EFI_FILE_IO_TOKEN *Token
+);
+
+
+/**
+ Writes data to a file.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to write data to.
+ @param Token A pointer to the token associated with the transaction.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
+ If Event is not NULL (asynchronous I/O): The request was successfully
+ queued for processing.
+ @retval EFI_UNSUPPORTED Writes to open directory files are not supported.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_WRITE_EX) (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT EFI_FILE_IO_TOKEN *Token
+);
+
+/**
+ Flushes all modified data associated with a file to a device.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to flush.
+ @param Token A pointer to the token associated with the transaction.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully.
+ If Event is not NULL (asynchronous I/O): The request was successfully
+ queued for processing.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read-only.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FILE_FLUSH_EX) (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT EFI_FILE_IO_TOKEN *Token
+ );
+
+#define EFI_FILE_PROTOCOL_REVISION 0x00010000
+#define EFI_FILE_PROTOCOL_REVISION2 0x00020000
+#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2
+
+//
+// Revision defined in EFI1.1.
+//
+#define EFI_FILE_REVISION EFI_FILE_PROTOCOL_REVISION
+
+///
+/// The EFI_FILE_PROTOCOL provides file IO access to supported file systems.
+/// An EFI_FILE_PROTOCOL provides access to a file's or directory's contents,
+/// and is also a reference to a location in the directory tree of the file system
+/// in which the file resides. With any given file handle, other files may be opened
+/// relative to this file's location, yielding new file handles.
+///
+struct _EFI_FILE_PROTOCOL {
+ ///
+ /// The version of the EFI_FILE_PROTOCOL interface. The version specified
+ /// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
+ /// Future versions are required to be backward compatible to version 1.0.
+ ///
+ UINT64 Revision;
+ EFI_FILE_OPEN Open;
+ EFI_FILE_CLOSE Close;
+ EFI_FILE_DELETE Delete;
+ EFI_FILE_READ Read;
+ EFI_FILE_WRITE Write;
+ EFI_FILE_GET_POSITION GetPosition;
+ EFI_FILE_SET_POSITION SetPosition;
+ EFI_FILE_GET_INFO GetInfo;
+ EFI_FILE_SET_INFO SetInfo;
+ EFI_FILE_FLUSH Flush;
+ EFI_FILE_OPEN_EX OpenEx;
+ EFI_FILE_READ_EX ReadEx;
+ EFI_FILE_WRITE_EX WriteEx;
+ EFI_FILE_FLUSH_EX FlushEx;
+};
+
+
+extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;
+
+#endif
--- /dev/null
+/** @file
+ Simple Text Input protocol from the UEFI 2.0 specification.
+
+ Abstraction of a very simple input device like a keyboard or serial
+ terminal.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__
+#define __SIMPLE_TEXT_IN_PROTOCOL_H__
+
+#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
+ { \
+ 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+
+///
+/// Protocol GUID name defined in EFI1.1.
+///
+#define SIMPLE_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID
+
+///
+/// Protocol name in EFI1.1 for backward-compatible.
+///
+typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE;
+
+///
+/// The keystroke information for the key that was pressed.
+///
+typedef struct {
+ UINT16 ScanCode;
+ CHAR16 UnicodeChar;
+} EFI_INPUT_KEY;
+
+//
+// Required unicode control chars
+//
+#define CHAR_NULL 0x0000
+#define CHAR_BACKSPACE 0x0008
+#define CHAR_TAB 0x0009
+#define CHAR_LINEFEED 0x000A
+#define CHAR_CARRIAGE_RETURN 0x000D
+
+//
+// EFI Scan codes
+//
+#define SCAN_NULL 0x0000
+#define SCAN_UP 0x0001
+#define SCAN_DOWN 0x0002
+#define SCAN_RIGHT 0x0003
+#define SCAN_LEFT 0x0004
+#define SCAN_HOME 0x0005
+#define SCAN_END 0x0006
+#define SCAN_INSERT 0x0007
+#define SCAN_DELETE 0x0008
+#define SCAN_PAGE_UP 0x0009
+#define SCAN_PAGE_DOWN 0x000A
+#define SCAN_F1 0x000B
+#define SCAN_F2 0x000C
+#define SCAN_F3 0x000D
+#define SCAN_F4 0x000E
+#define SCAN_F5 0x000F
+#define SCAN_F6 0x0010
+#define SCAN_F7 0x0011
+#define SCAN_F8 0x0012
+#define SCAN_F9 0x0013
+#define SCAN_F10 0x0014
+#define SCAN_ESC 0x0017
+
+/**
+ Reset the input device and optionally run diagnostics
+
+ @param This Protocol instance pointer.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_RESET)(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existence of a keystroke via WaitForEvent () call.
+
+ @param This Protocol instance pointer.
+ @param Key A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data available.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_READ_KEY)(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+///
+/// The EFI_SIMPLE_TEXT_INPUT_PROTOCOL is used on the ConsoleIn device.
+/// It is the minimum required protocol for ConsoleIn.
+///
+struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
+ EFI_INPUT_RESET Reset;
+ EFI_INPUT_READ_KEY ReadKeyStroke;
+ ///
+ /// Event to use with WaitForEvent() to wait for a key to be available
+ ///
+ EFI_EVENT WaitForKey;
+};
+
+extern EFI_GUID gEfiSimpleTextInProtocolGuid;
+
+#endif
--- /dev/null
+/** @file
+ Simple Text Input Ex protocol from the UEFI 2.0 specification.
+
+ This protocol defines an extension to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ which exposes much more state and modifier information from the input device,
+ also allows one to register a notification for a particular keystroke.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_TEXT_IN_EX_H__
+#define __SIMPLE_TEXT_IN_EX_H__
+
+#include "efi/Protocol/SimpleTextIn.h"
+
+#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+ {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
+
+
+typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
+
+/**
+ The Reset() function resets the input device hardware. As part
+ of initialization process, the firmware/device will make a quick
+ but reasonable attempt to verify that the device is functioning.
+ If the ExtendedVerification flag is TRUE the firmware may take
+ an extended amount of time to verify the device is operating on
+ reset. Otherwise the reset operation is to occur as quickly as
+ possible. The hardware verification process is not defined by
+ this specification and is left up to the platform firmware or
+ driver to implement.
+
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param ExtendedVerification Indicates that the driver may
+ perform a more exhaustive
+ verification operation of the
+ device during reset.
+
+
+ @retval EFI_SUCCESS The device was reset.
+
+ @retval EFI_DEVICE_ERROR The device is not functioning
+ correctly and could not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_RESET_EX)(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+);
+
+
+///
+/// EFI_KEY_TOGGLE_STATE. The toggle states are defined.
+/// They are: EFI_TOGGLE_STATE_VALID, EFI_SCROLL_LOCK_ACTIVE
+/// EFI_NUM_LOCK_ACTIVE, EFI_CAPS_LOCK_ACTIVE
+///
+typedef UINT8 EFI_KEY_TOGGLE_STATE;
+
+typedef struct _EFI_KEY_STATE {
+ ///
+ /// Reflects the currently pressed shift
+ /// modifiers for the input device. The
+ /// returned value is valid only if the high
+ /// order bit has been set.
+ ///
+ UINT32 KeyShiftState;
+ ///
+ /// Reflects the current internal state of
+ /// various toggled attributes. The returned
+ /// value is valid only if the high order
+ /// bit has been set.
+ ///
+ EFI_KEY_TOGGLE_STATE KeyToggleState;
+} EFI_KEY_STATE;
+
+typedef struct {
+ ///
+ /// The EFI scan code and Unicode value returned from the input device.
+ ///
+ EFI_INPUT_KEY Key;
+ ///
+ /// The current state of various toggled attributes as well as input modifier values.
+ ///
+ EFI_KEY_STATE KeyState;
+} EFI_KEY_DATA;
+
+//
+// Any Shift or Toggle State that is valid should have
+// high order bit set.
+//
+// Shift state
+//
+#define EFI_SHIFT_STATE_VALID 0x80000000
+#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
+#define EFI_LEFT_SHIFT_PRESSED 0x00000002
+#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
+#define EFI_LEFT_CONTROL_PRESSED 0x00000008
+#define EFI_RIGHT_ALT_PRESSED 0x00000010
+#define EFI_LEFT_ALT_PRESSED 0x00000020
+#define EFI_RIGHT_LOGO_PRESSED 0x00000040
+#define EFI_LEFT_LOGO_PRESSED 0x00000080
+#define EFI_MENU_KEY_PRESSED 0x00000100
+#define EFI_SYS_REQ_PRESSED 0x00000200
+
+//
+// Toggle state
+//
+#define EFI_TOGGLE_STATE_VALID 0x80
+#define EFI_KEY_STATE_EXPOSED 0x40
+#define EFI_SCROLL_LOCK_ACTIVE 0x01
+#define EFI_NUM_LOCK_ACTIVE 0x02
+#define EFI_CAPS_LOCK_ACTIVE 0x04
+
+//
+// EFI Scan codes
+//
+#define SCAN_F11 0x0015
+#define SCAN_F12 0x0016
+#define SCAN_PAUSE 0x0048
+#define SCAN_F13 0x0068
+#define SCAN_F14 0x0069
+#define SCAN_F15 0x006A
+#define SCAN_F16 0x006B
+#define SCAN_F17 0x006C
+#define SCAN_F18 0x006D
+#define SCAN_F19 0x006E
+#define SCAN_F20 0x006F
+#define SCAN_F21 0x0070
+#define SCAN_F22 0x0071
+#define SCAN_F23 0x0072
+#define SCAN_F24 0x0073
+#define SCAN_MUTE 0x007F
+#define SCAN_VOLUME_UP 0x0080
+#define SCAN_VOLUME_DOWN 0x0081
+#define SCAN_BRIGHTNESS_UP 0x0100
+#define SCAN_BRIGHTNESS_DOWN 0x0101
+#define SCAN_SUSPEND 0x0102
+#define SCAN_HIBERNATE 0x0103
+#define SCAN_TOGGLE_DISPLAY 0x0104
+#define SCAN_RECOVERY 0x0105
+#define SCAN_EJECT 0x0106
+
+/**
+ The function reads the next keystroke from the input device. If
+ there is no pending keystroke the function returns
+ EFI_NOT_READY. If there is a pending keystroke, then
+ KeyData.Key.ScanCode is the EFI scan code defined in Error!
+ Reference source not found. The KeyData.Key.UnicodeChar is the
+ actual printable character or is zero if the key does not
+ represent a printable character (control key, function key,
+ etc.). The KeyData.KeyState is shift state for the character
+ reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode .
+ When interpreting the data from this function, it should be
+ noted that if a class of printable characters that are
+ normally adjusted by shift modifiers (e.g. Shift Key + "f"
+ key) would be presented solely as a KeyData.Key.UnicodeChar
+ without the associated shift state. So in the previous example
+ of a Shift Key + "f" key being pressed, the only pertinent
+ data returned would be KeyData.Key.UnicodeChar with the value
+ of "F". This of course would not typically be the case for
+ non-printable characters such as the pressing of the Right
+ Shift Key + F10 key since the corresponding returned data
+ would be reflected both in the KeyData.KeyState.KeyShiftState
+ and KeyData.Key.ScanCode values. UEFI drivers which implement
+ the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return
+ KeyData.Key and KeyData.KeyState values. These drivers must
+ always return the most current state of
+ KeyData.KeyState.KeyShiftState and
+ KeyData.KeyState.KeyToggleState. It should also be noted that
+ certain input devices may not be able to produce shift or toggle
+ state information, and in those cases the high order bit in the
+ respective Toggle and Shift state fields should not be active.
+
+
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param KeyData A pointer to a buffer that is filled in with
+ the keystroke state data for the key that was
+ pressed.
+
+
+ @retval EFI_SUCCESS The keystroke information was
+ returned.
+
+ @retval EFI_NOT_READY There was no keystroke data available.
+ EFI_DEVICE_ERROR The keystroke
+ information was not returned due to
+ hardware errors.
+
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_READ_KEY_EX)(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+);
+
+/**
+ The SetState() function allows the input device hardware to
+ have state settings adjusted.
+
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to
+ set the state for the input device.
+
+
+ @retval EFI_SUCCESS The device state was set appropriately.
+
+ @retval EFI_DEVICE_ERROR The device is not functioning
+ correctly and could not have the
+ setting adjusted.
+
+ @retval EFI_UNSUPPORTED The device does not support the
+ ability to have its state set.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_STATE)(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+);
+
+///
+/// The function will be called when the key sequence is typed specified by KeyData.
+///
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
+ IN EFI_KEY_DATA *KeyData
+);
+
+/**
+ The RegisterKeystrokeNotify() function registers a function
+ which will be called when a specified keystroke will occur.
+
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param KeyData A pointer to a buffer that is filled in with
+ the keystroke information for the key that was
+ pressed.
+
+ @param KeyNotificationFunction Points to the function to be
+ called when the key sequence
+ is typed specified by KeyData.
+
+
+ @param NotifyHandle Points to the unique handle assigned to
+ the registered notification.
+
+ @retval EFI_SUCCESS The device state was set
+ appropriately.
+
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
+ data structures.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT VOID **NotifyHandle
+);
+
+/**
+ The UnregisterKeystrokeNotify() function removes the
+ notification which was previously registered.
+
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param NotificationHandle The handle of the notification
+ function being unregistered.
+
+ @retval EFI_SUCCESS The device state was set appropriately.
+
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is
+ invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN VOID *NotificationHandle
+);
+
+
+///
+/// The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is used on the ConsoleIn
+/// device. It is an extension to the Simple Text Input protocol
+/// which allows a variety of extended shift state information to be
+/// returned.
+///
+struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{
+ EFI_INPUT_RESET_EX Reset;
+ EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
+ ///
+ /// Event to use with WaitForEvent() to wait for a key to be available.
+ ///
+ EFI_EVENT WaitForKeyEx;
+ EFI_SET_STATE SetState;
+ EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
+ EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
+};
+
+
+extern EFI_GUID gEfiSimpleTextInputExProtocolGuid;
+
+#endif
+
--- /dev/null
+/** @file
+ Simple Text Out protocol from the UEFI 2.0 specification.
+
+ Abstraction of a very simple text based output device like VGA text mode or
+ a serial terminal. The Simple Text Out protocol instance can represent
+ a single hardware device or a virtual device that is an aggregation
+ of multiple physical devices.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_TEXT_OUT_H__
+#define __SIMPLE_TEXT_OUT_H__
+
+#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
+ { \
+ 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+///
+/// Protocol GUID defined in EFI1.1.
+///
+#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID
+
+typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+
+///
+/// Backward-compatible with EFI1.1.
+///
+typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
+
+//
+// Define's for required EFI Unicode Box Draw characters
+//
+#define BOXDRAW_HORIZONTAL 0x2500
+#define BOXDRAW_VERTICAL 0x2502
+#define BOXDRAW_DOWN_RIGHT 0x250c
+#define BOXDRAW_DOWN_LEFT 0x2510
+#define BOXDRAW_UP_RIGHT 0x2514
+#define BOXDRAW_UP_LEFT 0x2518
+#define BOXDRAW_VERTICAL_RIGHT 0x251c
+#define BOXDRAW_VERTICAL_LEFT 0x2524
+#define BOXDRAW_DOWN_HORIZONTAL 0x252c
+#define BOXDRAW_UP_HORIZONTAL 0x2534
+#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c
+#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
+#define BOXDRAW_DOUBLE_VERTICAL 0x2551
+#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
+#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
+#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
+#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
+#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
+#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
+#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
+#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
+#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a
+#define BOXDRAW_UP_LEFT_DOUBLE 0x255b
+#define BOXDRAW_UP_DOUBLE_LEFT 0x255c
+#define BOXDRAW_DOUBLE_UP_LEFT 0x255d
+#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e
+#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f
+#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
+#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
+#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
+#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
+#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
+#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
+#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
+#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
+#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
+#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
+#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a
+#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b
+#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c
+
+//
+// EFI Required Block Elements Code Chart
+//
+#define BLOCKELEMENT_FULL_BLOCK 0x2588
+#define BLOCKELEMENT_LIGHT_SHADE 0x2591
+
+//
+// EFI Required Geometric Shapes Code Chart
+//
+#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2
+#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba
+#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc
+#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4
+
+//
+// EFI Required Arrow shapes
+//
+#define ARROW_LEFT 0x2190
+#define ARROW_UP 0x2191
+#define ARROW_RIGHT 0x2192
+#define ARROW_DOWN 0x2193
+
+//
+// EFI Console Colours
+//
+#define EFI_BLACK 0x00
+#define EFI_BLUE 0x01
+#define EFI_GREEN 0x02
+#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
+#define EFI_RED 0x04
+#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
+#define EFI_BROWN (EFI_GREEN | EFI_RED)
+#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
+#define EFI_BRIGHT 0x08
+#define EFI_DARKGRAY (EFI_BRIGHT)
+#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
+#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
+#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
+#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
+#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
+#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
+#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
+
+#define EFI_TEXT_ATTR(f, b) ((f) | ((b) << 4))
+
+#define EFI_BACKGROUND_BLACK 0x00
+#define EFI_BACKGROUND_BLUE 0x10
+#define EFI_BACKGROUND_GREEN 0x20
+#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
+#define EFI_BACKGROUND_RED 0x40
+#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+
+//
+// We currently define attributes from 0 - 7F for color manipulations
+// To internally handle the local display characteristics for a particular character,
+// Bit 7 signifies the local glyph representation for a character. If turned on, glyphs will be
+// pulled from the wide glyph database and will display locally as a wide character (16 X 19 versus 8 X 19)
+// If bit 7 is off, the narrow glyph database will be used. This does NOT affect information that is sent to
+// non-local displays, such as serial or LAN consoles.
+//
+#define EFI_WIDE_ATTRIBUTE 0x80
+
+/**
+ Reset the text output device hardware and optionaly run diagnostics
+
+ @param This The protocol instance pointer.
+ @param ExtendedVerification Driver may perform more exhaustive verfication
+ operation of the device during reset.
+
+ @retval EFI_SUCCESS The text output device was reset.
+ @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
+ could not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_RESET)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Write a string to the output device.
+
+ @param This The protocol instance pointer.
+ @param String The NULL-terminated string to be displayed on the output
+ device(s). All output devices must also support the Unicode
+ drawing character codes defined in this file.
+
+ @retval EFI_SUCCESS The string was output to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the string could not be
+ rendered and were skipped.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_STRING)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+/**
+ Verifies that all characters in a string can be output to the
+ target device.
+
+ @param This The protocol instance pointer.
+ @param String The NULL-terminated string to be examined for the output
+ device(s).
+
+ @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
+ @retval EFI_UNSUPPORTED Some of the characters in the string cannot be
+ rendered by one or more of the output devices mapped
+ by the EFI handle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_TEST_STRING)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+/**
+ Returns information for an available text mode that the output device(s)
+ supports.
+
+ @param This The protocol instance pointer.
+ @param ModeNumber The mode number to return information on.
+ @param Columns Returns the geometry of the text output device for the
+ requested ModeNumber.
+ @param Rows Returns the geometry of the text output device for the
+ requested ModeNumber.
+
+ @retval EFI_SUCCESS The requested mode information was returned.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_QUERY_MODE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ );
+
+/**
+ Sets the output device(s) to a specified mode.
+
+ @param This The protocol instance pointer.
+ @param ModeNumber The mode number to set.
+
+ @retval EFI_SUCCESS The requested text mode was set.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_MODE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ );
+
+/**
+ Sets the background and foreground colors for the OutputString () and
+ ClearScreen () functions.
+
+ @param This The protocol instance pointer.
+ @param Attribute The attribute to set. Bits 0..3 are the foreground color, and
+ bits 4..6 are the background color. All other bits are undefined
+ and must be zero. The valid Attributes are defined in this file.
+
+ @retval EFI_SUCCESS The attribute was set.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The attribute requested is not defined.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_ATTRIBUTE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ );
+
+/**
+ Clears the output device(s) display to the currently selected background
+ color.
+
+ @param This The protocol instance pointer.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_CLEAR_SCREEN)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ );
+
+/**
+ Sets the current coordinates of the cursor position
+
+ @param This The protocol instance pointer.
+ @param Column The position to set the cursor to. Must be greater than or
+ equal to zero and less than the number of columns and rows
+ by QueryMode ().
+ @param Row The position to set the cursor to. Must be greater than or
+ equal to zero and less than the number of columns and rows
+ by QueryMode ().
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
+ cursor position is invalid for the current mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ );
+
+/**
+ Makes the cursor visible or invisible
+
+ @param This The protocol instance pointer.
+ @param Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+ set to be invisible.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request, or the device does not support changing
+ the cursor mode.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_ENABLE_CURSOR)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ );
+
+/**
+ @par Data Structure Description:
+ Mode Structure pointed to by Simple Text Out protocol.
+**/
+typedef struct {
+ ///
+ /// The number of modes supported by QueryMode () and SetMode ().
+ ///
+ INT32 MaxMode;
+
+ //
+ // current settings
+ //
+
+ ///
+ /// The text mode of the output device(s).
+ ///
+ INT32 Mode;
+ ///
+ /// The current character output attribute.
+ ///
+ INT32 Attribute;
+ ///
+ /// The cursor's column.
+ ///
+ INT32 CursorColumn;
+ ///
+ /// The cursor's row.
+ ///
+ INT32 CursorRow;
+ ///
+ /// The cursor is currently visbile or not.
+ ///
+ BOOLEAN CursorVisible;
+} EFI_SIMPLE_TEXT_OUTPUT_MODE;
+
+///
+/// The SIMPLE_TEXT_OUTPUT protocol is used to control text-based output devices.
+/// It is the minimum required protocol for any handle supplied as the ConsoleOut
+/// or StandardError device. In addition, the minimum supported text mode of such
+/// devices is at least 80 x 25 characters.
+///
+struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
+ EFI_TEXT_RESET Reset;
+
+ EFI_TEXT_STRING OutputString;
+ EFI_TEXT_TEST_STRING TestString;
+
+ EFI_TEXT_QUERY_MODE QueryMode;
+ EFI_TEXT_SET_MODE SetMode;
+ EFI_TEXT_SET_ATTRIBUTE SetAttribute;
+
+ EFI_TEXT_CLEAR_SCREEN ClearScreen;
+ EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
+ EFI_TEXT_ENABLE_CURSOR EnableCursor;
+
+ ///
+ /// Pointer to SIMPLE_TEXT_OUTPUT_MODE data.
+ ///
+ EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
+};
+
+extern EFI_GUID gEfiSimpleTextOutProtocolGuid;
+
+#endif
--- /dev/null
+/** @file
+
+ Root include file for Mde Package UEFI, UEFI_APPLICATION type modules.
+
+ This is the include file for any module of type UEFI and UEFI_APPLICATION. Uefi modules only use
+ types defined via this include file and can be ported easily to any
+ environment.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PI_UEFI_H__
+#define __PI_UEFI_H__
+
+#include "efi/Uefi/UefiBaseType.h"
+#include "efi/Uefi/UefiSpec.h"
+
+#endif
+
--- /dev/null
+/** @file
+ Defines data types and constants introduced in UEFI.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_BASETYPE_H__
+#define __UEFI_BASETYPE_H__
+
+#include "efi/Base.h"
+
+//
+// Basic data type definitions introduced in UEFI.
+//
+
+///
+/// 128-bit buffer containing a unique identifier value.
+///
+typedef GUID EFI_GUID;
+///
+/// Function return status for EFI API.
+///
+typedef RETURN_STATUS EFI_STATUS;
+///
+/// A collection of related interfaces.
+///
+typedef VOID *EFI_HANDLE;
+///
+/// Handle to an event structure.
+///
+typedef VOID *EFI_EVENT;
+///
+/// Task priority level.
+///
+typedef UINTN EFI_TPL;
+///
+/// Logical block address.
+///
+typedef UINT64 EFI_LBA;
+
+///
+/// 64-bit physical memory address.
+///
+typedef UINT64 EFI_PHYSICAL_ADDRESS;
+
+///
+/// 64-bit virtual memory address.
+///
+typedef UINT64 EFI_VIRTUAL_ADDRESS;
+
+///
+/// EFI Time Abstraction:
+/// Year: 1900 - 9999
+/// Month: 1 - 12
+/// Day: 1 - 31
+/// Hour: 0 - 23
+/// Minute: 0 - 59
+/// Second: 0 - 59
+/// Nanosecond: 0 - 999,999,999
+/// TimeZone: -1440 to 1440 or 2047
+///
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Pad1;
+ UINT32 Nanosecond;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINT8 Pad2;
+} EFI_TIME;
+
+
+///
+/// 4-byte buffer. An IPv4 internet protocol address.
+///
+typedef struct {
+ UINT8 Addr[4];
+} EFI_IPv4_ADDRESS;
+
+///
+/// 16-byte buffer. An IPv6 internet protocol address.
+///
+typedef struct {
+ UINT8 Addr[16];
+} EFI_IPv6_ADDRESS;
+
+///
+/// 32-byte buffer containing a network Media Access Control address.
+///
+typedef struct {
+ UINT8 Addr[32];
+} EFI_MAC_ADDRESS;
+
+///
+/// 16-byte buffer aligned on a 4-byte boundary.
+/// An IPv4 or IPv6 internet protocol address.
+///
+typedef union {
+ UINT32 Addr[4];
+ EFI_IPv4_ADDRESS v4;
+ EFI_IPv6_ADDRESS v6;
+} EFI_IP_ADDRESS;
+
+
+///
+/// Enumeration of EFI_STATUS.
+///@{
+#define EFI_SUCCESS RETURN_SUCCESS
+#define EFI_LOAD_ERROR RETURN_LOAD_ERROR
+#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER
+#define EFI_UNSUPPORTED RETURN_UNSUPPORTED
+#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE
+#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL
+#define EFI_NOT_READY RETURN_NOT_READY
+#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR
+#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED
+#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES
+#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED
+#define EFI_VOLUME_FULL RETURN_VOLUME_FULL
+#define EFI_NO_MEDIA RETURN_NO_MEDIA
+#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED
+#define EFI_NOT_FOUND RETURN_NOT_FOUND
+#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED
+#define EFI_NO_RESPONSE RETURN_NO_RESPONSE
+#define EFI_NO_MAPPING RETURN_NO_MAPPING
+#define EFI_TIMEOUT RETURN_TIMEOUT
+#define EFI_NOT_STARTED RETURN_NOT_STARTED
+#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED
+#define EFI_ABORTED RETURN_ABORTED
+#define EFI_ICMP_ERROR RETURN_ICMP_ERROR
+#define EFI_TFTP_ERROR RETURN_TFTP_ERROR
+#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR
+#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION
+#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION
+#define EFI_CRC_ERROR RETURN_CRC_ERROR
+#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA
+#define EFI_END_OF_FILE RETURN_END_OF_FILE
+#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE
+#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA
+
+#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH
+#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE
+#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE
+#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL
+#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA
+///@}
+
+///
+/// Define macro to encode the status code.
+///
+#define EFIERR(_a) ENCODE_ERROR(_a)
+
+#define EFI_ERROR(A) RETURN_ERROR(A)
+
+///
+/// ICMP error definitions
+///@{
+#define EFI_NETWORK_UNREACHABLE EFIERR(100)
+#define EFI_HOST_UNREACHABLE EFIERR(101)
+#define EFI_PROTOCOL_UNREACHABLE EFIERR(102)
+#define EFI_PORT_UNREACHABLE EFIERR(103)
+///@}
+
+///
+/// Tcp connection status definitions
+///@{
+#define EFI_CONNECTION_FIN EFIERR(104)
+#define EFI_CONNECTION_RESET EFIERR(105)
+#define EFI_CONNECTION_REFUSED EFIERR(106)
+///@}
+
+//
+// The EFI memory allocation functions work in units of EFI_PAGEs that are
+// 4KB. This should in no way be confused with the page size of the processor.
+// An EFI_PAGE is just the quanta of memory in EFI.
+//
+#define EFI_PAGE_SIZE SIZE_4KB
+#define EFI_PAGE_MASK 0xFFF
+#define EFI_PAGE_SHIFT 12
+
+/**
+ Macro that converts a size, in bytes, to a number of EFI_PAGESs.
+
+ @param Size A size in bytes. This parameter is assumed to be type UINTN.
+ Passing in a parameter that is larger than UINTN may produce
+ unexpected results.
+
+ @return The number of EFI_PAGESs associated with the number of bytes specified
+ by Size.
+
+**/
+#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0))
+
+/**
+ Macro that converts a number of EFI_PAGEs to a size in bytes.
+
+ @param Pages The number of EFI_PAGES. This parameter is assumed to be
+ type UINTN. Passing in a parameter that is larger than
+ UINTN may produce unexpected results.
+
+ @return The number of bytes associated with the number of EFI_PAGEs specified
+ by Pages.
+
+**/
+#define EFI_PAGES_TO_SIZE(Pages) ((Pages) << EFI_PAGE_SHIFT)
+
+///
+/// PE32+ Machine type for IA32 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_IA32 0x014C
+
+///
+/// PE32+ Machine type for IA64 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_IA64 0x0200
+
+///
+/// PE32+ Machine type for EBC UEFI images.
+///
+#define EFI_IMAGE_MACHINE_EBC 0x0EBC
+
+///
+/// PE32+ Machine type for X64 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_X64 0x8664
+
+///
+/// PE32+ Machine type for ARM mixed ARM and Thumb/Thumb2 images.
+///
+#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
+
+///
+/// PE32+ Machine type for AARCH64 A64 images.
+///
+#define EFI_IMAGE_MACHINE_AARCH64 0xAA64
+
+
+#if defined (MDE_CPU_IA32)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
+
+#elif defined (MDE_CPU_IPF)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#elif defined (MDE_CPU_X64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
+
+#elif defined (MDE_CPU_ARM)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)
+
+#elif defined (MDE_CPU_AARCH64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_AARCH64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#elif defined (MDE_CPU_EBC)
+
+///
+/// This is just to make sure you can cross compile with the EBC compiler.
+/// It does not make sense to have a PE loader coded in EBC.
+///
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#else
+#error Unknown Processor Type
+#endif
+
+#endif
--- /dev/null
+/** @file
+ EFI Guid Partition Table Format Definition.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_GPT_H__
+#define __UEFI_GPT_H__
+
+///
+/// The primary GUID Partition Table Header must be
+/// located in LBA 1 (i.e., the second logical block).
+///
+#define PRIMARY_PART_HEADER_LBA 1
+///
+/// EFI Partition Table Signature: "EFI PART".
+///
+#define EFI_PTAB_HEADER_ID SIGNATURE_64 ('E','F','I',' ','P','A','R','T')
+
+#pragma pack(1)
+
+///
+/// GPT Partition Table Header.
+///
+typedef struct {
+ ///
+ /// The table header for the GPT partition Table.
+ /// This header contains EFI_PTAB_HEADER_ID.
+ ///
+ EFI_TABLE_HEADER Header;
+ ///
+ /// The LBA that contains this data structure.
+ ///
+ EFI_LBA MyLBA;
+ ///
+ /// LBA address of the alternate GUID Partition Table Header.
+ ///
+ EFI_LBA AlternateLBA;
+ ///
+ /// The first usable logical block that may be used
+ /// by a partition described by a GUID Partition Entry.
+ ///
+ EFI_LBA FirstUsableLBA;
+ ///
+ /// The last usable logical block that may be used
+ /// by a partition described by a GUID Partition Entry.
+ ///
+ EFI_LBA LastUsableLBA;
+ ///
+ /// GUID that can be used to uniquely identify the disk.
+ ///
+ EFI_GUID DiskGUID;
+ ///
+ /// The starting LBA of the GUID Partition Entry array.
+ ///
+ EFI_LBA PartitionEntryLBA;
+ ///
+ /// The number of Partition Entries in the GUID Partition Entry array.
+ ///
+ UINT32 NumberOfPartitionEntries;
+ ///
+ /// The size, in bytes, of each the GUID Partition
+ /// Entry structures in the GUID Partition Entry
+ /// array. This field shall be set to a value of 128 x 2^n where n is
+ /// an integer greater than or equal to zero (e.g., 128, 256, 512, etc.).
+ ///
+ UINT32 SizeOfPartitionEntry;
+ ///
+ /// The CRC32 of the GUID Partition Entry array.
+ /// Starts at PartitionEntryLBA and is
+ /// computed over a byte length of
+ /// NumberOfPartitionEntries * SizeOfPartitionEntry.
+ ///
+ UINT32 PartitionEntryArrayCRC32;
+} EFI_PARTITION_TABLE_HEADER;
+
+///
+/// GPT Partition Entry.
+///
+typedef struct {
+ ///
+ /// Unique ID that defines the purpose and type of this Partition. A value of
+ /// zero defines that this partition entry is not being used.
+ ///
+ EFI_GUID PartitionTypeGUID;
+ ///
+ /// GUID that is unique for every partition entry. Every partition ever
+ /// created will have a unique GUID.
+ /// This GUID must be assigned when the GUID Partition Entry is created.
+ ///
+ EFI_GUID UniquePartitionGUID;
+ ///
+ /// Starting LBA of the partition defined by this entry
+ ///
+ EFI_LBA StartingLBA;
+ ///
+ /// Ending LBA of the partition defined by this entry.
+ ///
+ EFI_LBA EndingLBA;
+ ///
+ /// Attribute bits, all bits reserved by UEFI
+ /// Bit 0: If this bit is set, the partition is required for the platform to function. The owner/creator of the
+ /// partition indicates that deletion or modification of the contents can result in loss of platform
+ /// features or failure for the platform to boot or operate. The system cannot function normally if
+ /// this partition is removed, and it should be considered part of the hardware of the system.
+ /// Actions such as running diagnostics, system recovery, or even OS install or boot, could
+ /// potentially stop working if this partition is removed. Unless OS software or firmware
+ /// recognizes this partition, it should never be removed or modified as the UEFI firmware or
+ /// platform hardware may become non-functional.
+ /// Bit 1: If this bit is set, then firmware must not produce an EFI_BLOCK_IO_PROTOCOL device for
+ /// this partition. By not producing an EFI_BLOCK_IO_PROTOCOL partition, file system
+ /// mappings will not be created for this partition in UEFI.
+ /// Bit 2: This bit is set aside to let systems with traditional PC-AT BIOS firmware implementations
+ /// inform certain limited, special-purpose software running on these systems that a GPT
+ /// partition may be bootable. The UEFI boot manager must ignore this bit when selecting
+ /// a UEFI-compliant application, e.g., an OS loader.
+ /// Bits 3-47: Undefined and must be zero. Reserved for expansion by future versions of the UEFI
+ /// specification.
+ /// Bits 48-63: Reserved for GUID specific use. The use of these bits will vary depending on the
+ /// PartitionTypeGUID. Only the owner of the PartitionTypeGUID is allowed
+ /// to modify these bits. They must be preserved if Bits 0-47 are modified..
+ ///
+ UINT64 Attributes;
+ ///
+ /// Null-terminated name of the partition.
+ ///
+ CHAR16 PartitionName[36];
+} EFI_PARTITION_ENTRY;
+
+#pragma pack()
+#endif
+
+
--- /dev/null
+/** @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.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @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
--- /dev/null
+/** @file
+ This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_MULTIPHASE_H__
+#define __UEFI_MULTIPHASE_H__
+
+#include "efi/Guid/WinCertificate.h"
+///
+/// Enumeration of memory types introduced in UEFI.
+///
+typedef enum {
+ ///
+ /// Not used.
+ ///
+ EfiReservedMemoryType,
+ ///
+ /// The code portions of a loaded application.
+ /// (Note that UEFI OS loaders are UEFI applications.)
+ ///
+ EfiLoaderCode,
+ ///
+ /// The data portions of a loaded application and the default data allocation
+ /// type used by an application to allocate pool memory.
+ ///
+ EfiLoaderData,
+ ///
+ /// The code portions of a loaded Boot Services Driver.
+ ///
+ EfiBootServicesCode,
+ ///
+ /// The data portions of a loaded Boot Serves Driver, and the default data
+ /// allocation type used by a Boot Services Driver to allocate pool memory.
+ ///
+ EfiBootServicesData,
+ ///
+ /// The code portions of a loaded Runtime Services Driver.
+ ///
+ EfiRuntimeServicesCode,
+ ///
+ /// The data portions of a loaded Runtime Services Driver and the default
+ /// data allocation type used by a Runtime Services Driver to allocate pool memory.
+ ///
+ EfiRuntimeServicesData,
+ ///
+ /// Free (unallocated) memory.
+ ///
+ EfiConventionalMemory,
+ ///
+ /// Memory in which errors have been detected.
+ ///
+ EfiUnusableMemory,
+ ///
+ /// Memory that holds the ACPI tables.
+ ///
+ EfiACPIReclaimMemory,
+ ///
+ /// Address space reserved for use by the firmware.
+ ///
+ EfiACPIMemoryNVS,
+ ///
+ /// Used by system firmware to request that a memory-mapped IO region
+ /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.
+ ///
+ EfiMemoryMappedIO,
+ ///
+ /// System memory-mapped IO region that is used to translate memory
+ /// cycles to IO cycles by the processor.
+ ///
+ EfiMemoryMappedIOPortSpace,
+ ///
+ /// Address space reserved by the firmware for code that is part of the processor.
+ ///
+ EfiPalCode,
+ EfiMaxMemoryType
+} EFI_MEMORY_TYPE;
+
+///
+/// Data structure that precedes all of the standard EFI table types.
+///
+typedef struct {
+ ///
+ /// A 64-bit signature that identifies the type of table that follows.
+ /// Unique signatures have been generated for the EFI System Table,
+ /// the EFI Boot Services Table, and the EFI Runtime Services Table.
+ ///
+ UINT64 Signature;
+ ///
+ /// The revision of the EFI Specification to which this table
+ /// conforms. The upper 16 bits of this field contain the major
+ /// revision value, and the lower 16 bits contain the minor revision
+ /// value. The minor revision values are limited to the range of 00..99.
+ ///
+ UINT32 Revision;
+ ///
+ /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER.
+ ///
+ UINT32 HeaderSize;
+ ///
+ /// The 32-bit CRC for the entire table. This value is computed by
+ /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes.
+ ///
+ UINT32 CRC32;
+ ///
+ /// Reserved field that must be set to 0.
+ ///
+ UINT32 Reserved;
+} EFI_TABLE_HEADER;
+
+///
+/// Attributes of variable.
+///
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+///
+/// This attribute is identified by the mnemonic 'HR'
+/// elsewhere in this specification.
+///
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
+///
+/// Attributes of Authenticated Variable
+///
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
+#define EFI_VARIABLE_APPEND_WRITE 0x00000040
+
+
+///
+/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
+/// WIN_CERTIFICATE_UEFI_GUID and the CertType
+/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies
+/// authenticated access, then the Data buffer should begin with an
+/// authentication descriptor prior to the data payload and DataSize
+/// should reflect the the data.and descriptor size. The caller
+/// shall digest the Monotonic Count value and the associated data
+/// for the variable update using the SHA-256 1-way hash algorithm.
+/// The ensuing the 32-byte digest will be signed using the private
+/// key associated w/ the public/private 2048-bit RSA key-pair. The
+/// WIN_CERTIFICATE shall be used to describe the signature of the
+/// Variable data *Data. In addition, the signature will also
+/// include the MonotonicCount value to guard against replay attacks.
+///
+typedef struct {
+ ///
+ /// Included in the signature of
+ /// AuthInfo.Used to ensure freshness/no
+ /// replay. Incremented during each
+ /// "Write" access.
+ ///
+ UINT64 MonotonicCount;
+ ///
+ /// Provides the authorization for the variable
+ /// access. It is a signature across the
+ /// variable data and the Monotonic Count
+ /// value. Caller uses Private key that is
+ /// associated with a public key that has been
+ /// provisioned via the key exchange.
+ ///
+ WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+} EFI_VARIABLE_AUTHENTICATION;
+
+///
+/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
+/// set, then the Data buffer shall begin with an instance of a complete (and serialized)
+/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
+/// variable value and DataSize shall reflect the combined size of the descriptor and the new
+/// variable value. The authentication descriptor is not part of the variable data and is not
+/// returned by subsequent calls to GetVariable().
+///
+typedef struct {
+ ///
+ /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and
+ /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT.
+ ///
+ EFI_TIME TimeStamp;
+ ///
+ /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted.
+ ///
+ WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+ } EFI_VARIABLE_AUTHENTICATION_2;
+
+#endif
--- /dev/null
+/** @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.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @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
--- /dev/null
+/** @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.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_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
--- /dev/null
+/** @file
+ Processor or Compiler specific defines and types x64 (Intel 64, AMD64).
+
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+///
+/// Define the processor type so other code can make processor based choices
+///
+#define MDE_CPU_X64
+
+//
+// Make sure we are using the correct packing rules per EFI specification
+//
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+
+#if defined(__INTEL_COMPILER)
+//
+// Disable ICC's remark #869: "Parameter" was never referenced warning.
+// This is legal ANSI C code so we disable the remark that is turned on with -Wall
+//
+#pragma warning ( disable : 869 )
+
+//
+// Disable ICC's remark #1418: external function definition with no prior declaration.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1418 )
+
+//
+// Disable ICC's remark #1419: external declaration in primary source file
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1419 )
+
+//
+// Disable ICC's remark #593: "Variable" was set but never used.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 593 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+//
+// This warning is caused by functions defined but not used. For precompiled header only.
+//
+#pragma warning ( disable : 4505 )
+
+//
+// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
+//
+#pragma warning ( disable : 4206 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+ //
+ // use Microsoft C complier dependent integer width types
+ //
+
+ ///
+ /// 8-byte unsigned value
+ ///
+ typedef unsigned __int64 UINT64;
+ ///
+ /// 8-byte signed value
+ ///
+ typedef __int64 INT64;
+ ///
+ /// 4-byte unsigned value
+ ///
+ typedef unsigned __int32 UINT32;
+ ///
+ /// 4-byte signed value
+ ///
+ typedef __int32 INT32;
+ ///
+ /// 2-byte unsigned value
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef signed char INT8;
+#else
+ ///
+ /// 8-byte unsigned value
+ ///
+ typedef unsigned long long UINT64;
+ ///
+ /// 8-byte signed value
+ ///
+ typedef long long INT64;
+ ///
+ /// 4-byte unsigned value
+ ///
+ typedef unsigned int UINT32;
+ ///
+ /// 4-byte signed value
+ ///
+ typedef int INT32;
+ ///
+ /// 2-byte unsigned value
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef signed char INT8;
+#endif
+
+///
+/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
+/// 8 bytes on supported 64-bit processor instructions)
+///
+typedef UINT64 UINTN;
+///
+/// Signed value of native width. (4 bytes on supported 32-bit processor instructions,
+/// 8 bytes on supported 64-bit processor instructions)
+///
+typedef INT64 INTN;
+
+
+//
+// Processor specific defines
+//
+
+///
+/// A value of native width with the highest bit set.
+///
+#define MAX_BIT 0x8000000000000000ULL
+///
+/// A value of native width with the two highest bits set.
+///
+#define MAX_2_BITS 0xC000000000000000ULL
+
+///
+/// Maximum legal x64 address
+///
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
+
+///
+/// Maximum legal x64 INTN and UINTN values.
+///
+#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
+#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
+
+///
+/// The stack alignment required for x64
+///
+#define CPU_STACK_ALIGNMENT 16
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify their member functions with EFIAPI.
+//
+#ifdef EFIAPI
+ ///
+ /// If EFIAPI is already defined, then we use that definition.
+ ///
+#elif defined(_MSC_EXTENSIONS)
+ ///
+ /// Microsoft* compiler specific method for EFIAPI calling convension
+ ///
+ #define EFIAPI __cdecl
+#elif defined(__GNUC__)
+ ///
+ /// Define the standard calling convention reguardless of optimization level.
+ /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI
+ /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64)
+ /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for
+ /// x64. Warning the assembly code in the MDE x64 does not follow the correct
+ /// ABI for the standard x64 (x86-64) GCC.
+ ///
+ #define EFIAPI
+#else
+ ///
+ /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI
+ /// is the standard.
+ ///
+ #define EFIAPI
+#endif
+
+#if defined(__GNUC__)
+ ///
+ /// For GNU assembly code, .global or .globl can declare global symbols.
+ /// Define this macro to unify the usage.
+ ///
+ #define ASM_GLOBAL .globl
+#endif
+
+/**
+ Return the pointer to the first instruction of a function given a function pointer.
+ On x64 CPU architectures, these two pointer values are the same,
+ so the implementation of this macro is very simple.
+
+ @param FunctionPointer A pointer to a function.
+
+ @return The pointer to the first instruction of a function given a function pointer.
+
+**/
+#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
+
+#endif
+
--- /dev/null
+#!/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 );
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI block device
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "wimboot.h"
+#include "vdisk.h"
+#include "efi.h"
+#include "efipath.h"
+#include "efiblock.h"
+
+/** A block I/O device */
+struct efi_block {
+ /** EFI block I/O protocol */
+ EFI_BLOCK_IO_PROTOCOL block;
+ /** Device path */
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ /** Starting LBA */
+ uint64_t lba;
+ /** Name */
+ const char *name;
+};
+
+/**
+ * Reset block I/O protocol
+ *
+ * @v this Block I/O protocol
+ * @v extended Perform extended verification
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_reset_blocks ( EFI_BLOCK_IO_PROTOCOL *this, BOOLEAN extended ) {
+ struct efi_block *block =
+ container_of ( this, struct efi_block, block );
+ void *retaddr = __builtin_return_address ( 0 );
+
+ DBG2 ( "EFI %s %sreset -> %p\n",
+ block->name, ( extended ? "extended " : "" ), retaddr );
+ return 0;
+}
+
+/**
+ * Read blocks
+ *
+ * @v this Block I/O protocol
+ * @v media Media ID
+ * @v lba Starting LBA
+ * @v len Length of data
+ * @v data Data buffer
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this, UINT32 media, EFI_LBA lba,
+ UINTN len, VOID *data ) {
+ struct efi_block *block =
+ container_of ( this, struct efi_block, block );
+ void *retaddr = __builtin_return_address ( 0 );
+
+ DBG2 ( "EFI %s read media %08x LBA %#llx to %p+%zx -> %p\n",
+ block->name, media, lba, data, ( ( size_t ) len ), retaddr );
+ vdisk_read ( ( lba + block->lba ), ( len / VDISK_SECTOR_SIZE ), data );
+ return 0;
+}
+
+/**
+ * Write blocks
+ *
+ * @v this Block I/O protocol
+ * @v media Media ID
+ * @v lba Starting LBA
+ * @v len Length of data
+ * @v data Data buffer
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
+ UINT32 media __unused, EFI_LBA lba __unused,
+ UINTN len __unused, VOID *data __unused ) {
+ struct efi_block *block =
+ container_of ( this, struct efi_block, block );
+ void *retaddr = __builtin_return_address ( 0 );
+
+ DBG2 ( "EFI %s write media %08x LBA %#llx from %p+%zx -> %p\n",
+ block->name, media, lba, data, ( ( size_t ) len ), retaddr );
+ return EFI_WRITE_PROTECTED;
+}
+
+/**
+ * Flush block operations
+ *
+ * @v this Block I/O protocol
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_flush_blocks ( EFI_BLOCK_IO_PROTOCOL *this ) {
+ struct efi_block *block =
+ container_of ( this, struct efi_block, block );
+ void *retaddr = __builtin_return_address ( 0 );
+
+ DBG2 ( "EFI %s flush -> %p\n", block->name, retaddr );
+ return 0;
+}
+
+/** GUID used in vendor device path */
+#define EFIBLOCK_GUID { \
+ 0x1322d197, 0x15dc, 0x4a45, \
+ { 0xa6, 0xa4, 0xfa, 0x57, 0x05, 0x4e, 0xa6, 0x14 } \
+ }
+
+/**
+ * Initialise vendor device path
+ *
+ * @v name Variable name
+ */
+#define EFIBLOCK_DEVPATH_VENDOR_INIT( name ) { \
+ .Header = EFI_DEVPATH_INIT ( name, HARDWARE_DEVICE_PATH, \
+ HW_VENDOR_DP ), \
+ .Guid = EFIBLOCK_GUID, \
+ }
+
+/**
+ * Initialise ATA device path
+ *
+ * @v name Variable name
+ */
+#define EFIBLOCK_DEVPATH_ATA_INIT( name ) { \
+ .Header = EFI_DEVPATH_INIT ( name, MESSAGING_DEVICE_PATH, \
+ MSG_ATAPI_DP ), \
+ .PrimarySecondary = 0, \
+ .SlaveMaster = 0, \
+ .Lun = 0, \
+ }
+
+/**
+ * Initialise hard disk device path
+ *
+ * @v name Variable name
+ */
+#define EFIBLOCK_DEVPATH_HD_INIT( name ) { \
+ .Header = EFI_DEVPATH_INIT ( name, MEDIA_DEVICE_PATH, \
+ MEDIA_HARDDRIVE_DP ), \
+ .PartitionNumber = 1, \
+ .PartitionStart = VDISK_PARTITION_LBA, \
+ .PartitionSize = VDISK_PARTITION_COUNT, \
+ .Signature[0] = ( ( VDISK_MBR_SIGNATURE >> 0 ) & 0xff ), \
+ .Signature[1] = ( ( VDISK_MBR_SIGNATURE >> 8 ) & 0xff ), \
+ .Signature[2] = ( ( VDISK_MBR_SIGNATURE >> 16 ) & 0xff ), \
+ .Signature[3] = ( ( VDISK_MBR_SIGNATURE >> 24 ) & 0xff ), \
+ .MBRType = MBR_TYPE_PCAT, \
+ .SignatureType = SIGNATURE_TYPE_MBR, \
+ }
+
+/** Virtual disk media */
+static EFI_BLOCK_IO_MEDIA efi_vdisk_media = {
+ .MediaId = VDISK_MBR_SIGNATURE,
+ .MediaPresent = TRUE,
+ .LogicalPartition = FALSE,
+ .ReadOnly = TRUE,
+ .BlockSize = VDISK_SECTOR_SIZE,
+ .LastBlock = ( VDISK_COUNT - 1 ),
+};
+
+/** Virtual disk device path */
+static struct {
+ VENDOR_DEVICE_PATH vendor;
+ ATAPI_DEVICE_PATH ata;
+ EFI_DEVICE_PATH_PROTOCOL end;
+} __attribute__ (( packed )) efi_vdisk_path = {
+ .vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_vdisk_path.vendor ),
+ .ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_vdisk_path.ata ),
+ .end = EFI_DEVPATH_END_INIT ( efi_vdisk_path.end ),
+};
+
+/** Virtual disk device */
+static struct efi_block efi_vdisk = {
+ .block = {
+ .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION,
+ .Media = &efi_vdisk_media,
+ .Reset = efi_reset_blocks,
+ .ReadBlocks = efi_read_blocks,
+ .WriteBlocks = efi_write_blocks,
+ .FlushBlocks = efi_flush_blocks,
+ },
+ .path = &efi_vdisk_path.vendor.Header,
+ .lba = 0,
+ .name = "vdisk",
+};
+
+/** Virtual partition media */
+static EFI_BLOCK_IO_MEDIA efi_vpartition_media = {
+ .MediaId = VDISK_MBR_SIGNATURE,
+ .MediaPresent = TRUE,
+ .LogicalPartition = TRUE,
+ .ReadOnly = TRUE,
+ .BlockSize = VDISK_SECTOR_SIZE,
+ .LastBlock = ( VDISK_PARTITION_COUNT - 1 ),
+};
+
+/** Virtual partition device path */
+static struct {
+ VENDOR_DEVICE_PATH vendor;
+ ATAPI_DEVICE_PATH ata;
+ HARDDRIVE_DEVICE_PATH hd;
+ EFI_DEVICE_PATH_PROTOCOL end;
+} __attribute__ (( packed )) efi_vpartition_path = {
+ .vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_vpartition_path.vendor ),
+ .ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_vpartition_path.ata ),
+ .hd = EFIBLOCK_DEVPATH_HD_INIT ( efi_vpartition_path.hd ),
+ .end = EFI_DEVPATH_END_INIT ( efi_vpartition_path.end ),
+};
+
+/** Virtual partition device */
+static struct efi_block efi_vpartition = {
+ .block = {
+ .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION,
+ .Media = &efi_vpartition_media,
+ .Reset = efi_reset_blocks,
+ .ReadBlocks = efi_read_blocks,
+ .WriteBlocks = efi_write_blocks,
+ .FlushBlocks = efi_flush_blocks,
+ },
+ .path = &efi_vpartition_path.vendor.Header,
+ .lba = VDISK_PARTITION_LBA,
+ .name = "vpartition",
+};
+
+/**
+ * Install block I/O protocols
+ *
+ * @ret vdisk New virtual disk handle
+ * @ret vpartition New virtual partition handle
+ */
+void efi_install ( EFI_HANDLE *vdisk, EFI_HANDLE *vpartition ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+
+ /* Install virtual disk */
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
+ vdisk,
+ &efi_block_io_protocol_guid, &efi_vdisk.block,
+ &efi_device_path_protocol_guid, efi_vdisk.path,
+ NULL ) ) != 0 ) {
+ die ( "Could not install disk block I/O protocols: %#lx\n",
+ ( ( unsigned long ) efirc ) );
+ }
+
+ /* Install virtual partition */
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
+ vpartition,
+ &efi_block_io_protocol_guid, &efi_vpartition.block,
+ &efi_device_path_protocol_guid, efi_vpartition.path,
+ NULL ) ) != 0 ) {
+ die ( "Could not install partition block I/O protocols: %#lx\n",
+ ( ( unsigned long ) efirc ) );
+ }
+}
+
+/** Boot image path */
+static struct {
+ VENDOR_DEVICE_PATH vendor;
+ ATAPI_DEVICE_PATH ata;
+ HARDDRIVE_DEVICE_PATH hd;
+ struct {
+ EFI_DEVICE_PATH header;
+ CHAR16 name[ sizeof ( EFI_REMOVABLE_MEDIA_FILE_NAME ) /
+ sizeof ( CHAR16 ) ];
+ } __attribute__ (( packed )) file;
+ EFI_DEVICE_PATH_PROTOCOL end;
+} __attribute__ (( packed )) efi_bootmgfw_path = {
+ .vendor = EFIBLOCK_DEVPATH_VENDOR_INIT ( efi_bootmgfw_path.vendor ),
+ .ata = EFIBLOCK_DEVPATH_ATA_INIT ( efi_bootmgfw_path.ata ),
+ .hd = EFIBLOCK_DEVPATH_HD_INIT ( efi_bootmgfw_path.hd ),
+ .file = {
+ .header = EFI_DEVPATH_INIT ( efi_bootmgfw_path.file,
+ MEDIA_DEVICE_PATH,
+ MEDIA_FILEPATH_DP ),
+ .name = EFI_REMOVABLE_MEDIA_FILE_NAME,
+ },
+ .end = EFI_DEVPATH_END_INIT ( efi_bootmgfw_path.end ),
+};
+
+/** Boot image path */
+EFI_DEVICE_PATH_PROTOCOL *bootmgfw_path = &efi_bootmgfw_path.vendor.Header;
--- /dev/null
+#ifndef _EFIBLOCK_H
+#define _EFIBLOCK_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI block device
+ *
+ */
+
+#include "efi.h"
+#include "efi/Protocol/BlockIo.h"
+#include "efi/Protocol/DevicePath.h"
+
+extern void efi_install ( EFI_HANDLE *vdisk, EFI_HANDLE *vpartition );
+
+extern EFI_DEVICE_PATH_PROTOCOL *bootmgfw_path;
+
+#endif /* _EFIBLOCK_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI boot manager invocation
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "wimboot.h"
+#include "cmdline.h"
+#include "vdisk.h"
+#include "pause.h"
+#include "efi.h"
+#include "efi/Protocol/GraphicsOutput.h"
+#include "efipath.h"
+#include "efiboot.h"
+
+/** Original OpenProtocol() method */
+static EFI_OPEN_PROTOCOL orig_open_protocol;
+
+/**
+ * Intercept OpenProtocol()
+ *
+ * @v handle EFI handle
+ * @v protocol Protocol GUID
+ * @v interface Opened interface
+ * @v agent_handle Agent handle
+ * @v controller_handle Controller handle
+ * @v attributes Attributes
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_open_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
+ VOID **interface, EFI_HANDLE agent_handle,
+ EFI_HANDLE controller_handle, UINT32 attributes ) {
+ static unsigned int count;
+ EFI_STATUS efirc;
+
+ /* Open the protocol */
+ if ( ( efirc = orig_open_protocol ( handle, protocol, interface,
+ agent_handle, controller_handle,
+ attributes ) ) != 0 ) {
+ return efirc;
+ }
+
+ /* Block first attempt by bootmgfw.efi to open
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL. This forces error messages
+ * to be displayed in text mode (thereby avoiding the totally
+ * blank error screen if the fonts are missing). We must
+ * allow subsequent attempts to succeed, otherwise the OS will
+ * fail to boot.
+ */
+ if ( ( memcmp ( protocol, &efi_graphics_output_protocol_guid,
+ sizeof ( *protocol ) ) == 0 ) &&
+ ( count++ == 0 ) && ( ! cmdline_gui ) ) {
+ DBG ( "Forcing text mode output\n" );
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return 0;
+}
+
+/**
+ * Boot from EFI device
+ *
+ * @v file Virtual file
+ * @v path Device path
+ * @v device Device handle
+ */
+void efi_boot ( struct vdisk_file *file, EFI_DEVICE_PATH_PROTOCOL *path,
+ EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ EFI_LOADED_IMAGE_PROTOCOL *image;
+ void *intf;
+ } loaded;
+ EFI_PHYSICAL_ADDRESS phys;
+ void *data;
+ unsigned int pages;
+ EFI_HANDLE handle;
+ EFI_STATUS efirc;
+
+ /* Allocate memory */
+ pages = ( ( file->len + PAGE_SIZE - 1 ) / PAGE_SIZE );
+ if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
+ EfiBootServicesData, pages,
+ &phys ) ) != 0 ) {
+ die ( "Could not allocate %d pages: %#lx\n",
+ pages, ( ( unsigned long ) efirc ) );
+ }
+ data = ( ( void * ) ( intptr_t ) phys );
+
+
+ /* Read image */
+ file->read ( file, data, 0, file->len );
+ DBG ( "Read %s\n", file->name );
+
+ /* Load image */
+ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path, data,
+ file->len, &handle ) ) != 0 ) {
+ die ( "Could not load %s: %#lx\n",
+ file->name, ( ( unsigned long ) efirc ) );
+ }
+ DBG ( "Loaded %s\n", file->name );
+
+ /* Get loaded image protocol */
+ if ( ( efirc = bs->OpenProtocol ( handle,
+ &efi_loaded_image_protocol_guid,
+ &loaded.intf, efi_image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+ die ( "Could not get loaded image protocol for %s: %#lx\n",
+ file->name, ( ( unsigned long ) efirc ) );
+ }
+
+ /* Force correct device handle */
+ if ( loaded.image->DeviceHandle != device ) {
+ DBG ( "Forcing correct DeviceHandle (%p->%p)\n",
+ loaded.image->DeviceHandle, device );
+ loaded.image->DeviceHandle = device;
+ }
+
+ /* Intercept calls to OpenProtocol() */
+ orig_open_protocol =
+ loaded.image->SystemTable->BootServices->OpenProtocol;
+ loaded.image->SystemTable->BootServices->OpenProtocol =
+ efi_open_protocol_wrapper;
+
+ /* Start image */
+ if ( cmdline_pause )
+ pause();
+ if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
+ die ( "Could not start %s: %#lx\n",
+ file->name, ( ( unsigned long ) efirc ) );
+ }
+
+ die ( "%s returned\n", file->name );
+}
--- /dev/null
+#ifndef _EFIBOOT_H
+#define _EFIBOOT_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI boot manager invocation
+ *
+ */
+
+#include "efi.h"
+#include "efi/Protocol/DevicePath.h"
+
+struct vdisk_file;
+
+extern void efi_boot ( struct vdisk_file *file, EFI_DEVICE_PATH_PROTOCOL *path,
+ EFI_HANDLE device );
+
+#endif /* _EFIBOOT_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI file system access
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <wchar.h>
+#include "wimboot.h"
+#include "vdisk.h"
+#include "cmdline.h"
+#include "wimpatch.h"
+#include "wimfile.h"
+#include "efi.h"
+#include "efifile.h"
+
+/** bootmgfw.efi path within WIM */
+static const wchar_t bootmgfw_path[] = L"\\Windows\\Boot\\EFI\\bootmgfw.efi";
+
+/** Other paths within WIM */
+static const wchar_t *efi_wim_paths[] = {
+ L"\\Windows\\Boot\\DVD\\EFI\\boot.sdi",
+ L"\\Windows\\Boot\\DVD\\EFI\\BCD",
+ L"\\Windows\\Boot\\Fonts\\segmono_boot.ttf",
+ L"\\Windows\\Boot\\Fonts\\segoen_slboot.ttf",
+ L"\\Windows\\Boot\\Fonts\\segoe_slboot.ttf",
+ L"\\Windows\\Boot\\Fonts\\wgl4_boot.ttf",
+ L"\\sms\\boot\\boot.sdi",
+ NULL
+};
+
+/** bootmgfw.efi file */
+struct vdisk_file *bootmgfw;
+
+/**
+ * Get architecture-specific boot filename
+ *
+ * @ret bootarch Architecture-specific boot filename
+ */
+static const CHAR16 * efi_bootarch ( void ) {
+ static const CHAR16 bootarch_full[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
+ const CHAR16 *tmp;
+ const CHAR16 *bootarch = bootarch_full;
+
+ for ( tmp = bootarch_full ; *tmp ; tmp++ ) {
+ if ( *tmp == L'\\' )
+ bootarch = ( tmp + 1 );
+ }
+ return bootarch;
+}
+
+/**
+ * Read from EFI file
+ *
+ * @v vfile Virtual file
+ * @v data Data buffer
+ * @v offset Offset
+ * @v len Length
+ */
+static void efi_read_file ( struct vdisk_file *vfile, void *data,
+ size_t offset, size_t len ) {
+#if 0
+ EFI_FILE_PROTOCOL *file = vfile->opaque;
+ UINTN size = len;
+ EFI_STATUS efirc;
+
+ /* Set file position */
+ if ( ( efirc = file->SetPosition ( file, offset ) ) != 0 ) {
+ die ( "Could not set file position: %#lx\n",
+ ( ( unsigned long ) efirc ) );
+ }
+
+ /* Read from file */
+ if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
+ die ( "Could not read from file: %#lx\n",
+ ( ( unsigned long ) efirc ) );
+ }
+#endif /* #if 0 */
+
+ (void)vfile;
+
+ pfventoy_file_read((const char *)vfile->opaque, (int)offset, (int)len, data);
+}
+
+/**
+ * Patch BCD file
+ *
+ * @v vfile Virtual file
+ * @v data Data buffer
+ * @v offset Offset
+ * @v len Length
+ */
+static void efi_patch_bcd ( struct vdisk_file *vfile __unused, void *data,
+ size_t offset, size_t len ) {
+ static const wchar_t search[] = L".exe";
+ static const wchar_t replace[] = L".efi";
+ size_t i;
+
+ /* Do nothing if BCD patching is disabled */
+ if ( cmdline_rawbcd )
+ return;
+
+ /* Patch any occurrences of ".exe" to ".efi". In the common
+ * simple cases, this allows the same BCD file to be used for
+ * both BIOS and UEFI systems.
+ */
+ for ( i = 0 ; ( i + sizeof ( search ) ) < len ; i++ ) {
+ if ( wcscasecmp ( ( data + i ), search ) == 0 ) {
+ memcpy ( ( data + i ), replace, sizeof ( replace ) );
+ DBG ( "...patched BCD at %#zx: \"%ls\" to \"%ls\"\n",
+ ( offset + i ), search, replace );
+ }
+ }
+}
+
+/**
+ * Extract files from EFI file system
+ *
+ * @v handle Device handle
+ */
+void efi_extract ( EFI_HANDLE handle ) {
+ struct vdisk_file *wim = NULL;
+ struct vdisk_file *vfile;
+ CHAR16 wname[64];
+ int i, j, k;
+ char *pos;
+ size_t len = 0;
+
+ (void)handle;
+
+ /* Read root directory */
+ for (i = 0; i < cmdline_vf_num; i++) {
+ pos = strchr(cmdline_vf_path[i], ':');
+
+ *pos = 0;
+ k = (int)strlen(cmdline_vf_path[i]);
+
+ memset(wname, 0, sizeof(wname));
+ for (j = 0; j < k; j++)
+ {
+ wname[j] = cmdline_vf_path[i][j];
+ }
+
+ len = pfventoy_file_size(pos + 1);
+ vfile = vdisk_add_file (cmdline_vf_path[i], pos + 1, len, efi_read_file);
+
+ /* Check for special-case files */
+ if ( ( wcscasecmp ( wname, efi_bootarch() ) == 0 ) ||
+ ( wcscasecmp ( wname, L"bootmgfw.efi" ) == 0 ) ) {
+ DBG ( "...found bootmgfw.efi file %ls\n", wname );
+ bootmgfw = vfile;
+ } else if ( wcscasecmp ( wname, L"BCD" ) == 0 ) {
+ DBG ( "...found BCD\n" );
+ vdisk_patch_file ( vfile, efi_patch_bcd );
+ } else if ( wcscasecmp ( ( wname + ( wcslen ( wname ) - 4 ) ),
+ L".wim" ) == 0 ) {
+ DBG ( "...found WIM file %ls\n", wname );
+ wim = vfile;
+ }
+ }
+
+ /* Process WIM image */
+ if ( wim ) {
+ vdisk_patch_file ( wim, patch_wim );
+ if ( ( ! bootmgfw ) &&
+ ( bootmgfw = wim_add_file ( wim, cmdline_index,
+ bootmgfw_path,
+ efi_bootarch() ) ) ) {
+ DBG ( "...extracted %ls\n", bootmgfw_path );
+ }
+ wim_add_files ( wim, cmdline_index, efi_wim_paths );
+ }
+
+ /* Check that we have a boot file */
+ if ( ! bootmgfw ) {
+ die ( "FATAL: no %ls or bootmgfw.efi found\n",
+ efi_bootarch() );
+ }
+}
--- /dev/null
+#ifndef _EFIFILE_H
+#define _EFIFILE_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI file system access
+ *
+ */
+
+#include "efi.h"
+#include "efi/Protocol/SimpleFileSystem.h"
+#include "efi/Guid/FileInfo.h"
+
+struct vdisk_file;
+
+extern struct vdisk_file *bootmgfw;
+extern void efi_extract ( EFI_HANDLE handle );
+
+#endif /* _EFIFILE_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI GUIDs
+ *
+ */
+
+#include "wimboot.h"
+#include "efi.h"
+#include "efi/Protocol/BlockIo.h"
+#include "efi/Protocol/DevicePath.h"
+#include "efi/Protocol/GraphicsOutput.h"
+#include "efi/Protocol/LoadedImage.h"
+#include "efi/Protocol/SimpleFileSystem.h"
+
+/** Block I/O protocol GUID */
+EFI_GUID efi_block_io_protocol_guid
+ = EFI_BLOCK_IO_PROTOCOL_GUID;
+
+/** Device path protocol GUID */
+EFI_GUID efi_device_path_protocol_guid
+ = EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+/** Graphics output protocol GUID */
+EFI_GUID efi_graphics_output_protocol_guid
+ = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+
+/** Loaded image protocol GUID */
+EFI_GUID efi_loaded_image_protocol_guid
+ = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+/** Simple file system protocol GUID */
+EFI_GUID efi_simple_file_system_protocol_guid
+ = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI entry point
+ *
+ */
+
+#include <stdio.h>
+#include "wimboot.h"
+#include "cmdline.h"
+#include "efi.h"
+#include "efifile.h"
+#include "efiblock.h"
+#include "efiboot.h"
+
+/**
+ * Process command line
+ *
+ * @v loaded Loaded image protocol
+ */
+static void efi_cmdline ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
+ size_t cmdline_len = ( loaded->LoadOptionsSize / sizeof ( wchar_t ) );
+ char cmdline[ cmdline_len + 1 /* NUL */ ];
+ const wchar_t *wcmdline = loaded->LoadOptions;
+
+ /* Convert command line to ASCII */
+ snprintf ( cmdline, sizeof ( cmdline ), "%ls", wcmdline );
+
+ /* Process command line */
+ process_cmdline ( cmdline );
+}
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab EFI system table
+ * @ret efirc EFI status code
+ */
+EFI_STATUS EFIAPI efi_main ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_BOOT_SERVICES *bs;
+ union {
+ EFI_LOADED_IMAGE_PROTOCOL *image;
+ void *interface;
+ } loaded;
+ EFI_HANDLE vdisk = NULL;
+ EFI_HANDLE vpartition = NULL;
+ EFI_STATUS efirc;
+
+ /* Record EFI handle and system table */
+ efi_image_handle = image_handle;
+ efi_systab = systab;
+ bs = systab->BootServices;
+
+ /* Initialise stack cookie */
+ init_cookie();
+
+ /* Print welcome banner */
+ printf ( "\n\nBooting wim file...... (This may take a few minutes, please wait)\n\n");
+// printf ( "\n\nwimboot " VERSION " -- Windows Imaging Format "
+// "bootloader -- https://ipxe.org/wimboot\n\n" );
+
+ /* Get loaded image protocol */
+ if ( ( efirc = bs->OpenProtocol ( image_handle,
+ &efi_loaded_image_protocol_guid,
+ &loaded.interface, image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+ die ( "Could not open loaded image protocol: %#lx\n",
+ ( ( unsigned long ) efirc ) );
+ }
+
+ /* Process command line */
+ efi_cmdline ( loaded.image );
+
+ /* Extract files from file system */
+ efi_extract ( loaded.image->DeviceHandle );
+
+ /* Install virtual disk */
+ efi_install ( &vdisk, &vpartition );
+
+ /* Invoke boot manager */
+ efi_boot ( bootmgfw, bootmgfw_path, vpartition );
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI device paths
+ *
+ */
+
+#include "wimboot.h"
+#include "efi.h"
+#include "efipath.h"
+
+/**
+ * Find end of device path
+ *
+ * @v path Path to device
+ * @ret path_end End of device path
+ */
+EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
+
+ while ( path->Type != END_DEVICE_PATH_TYPE ) {
+ path = ( ( ( void * ) path ) +
+ /* There's this amazing new-fangled thing known as
+ * a UINT16, but who wants to use one of those? */
+ ( ( path->Length[1] << 8 ) | path->Length[0] ) );
+ }
+ return path;
+}
--- /dev/null
+#ifndef _EFIPATH_H
+#define _EFIPATH_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI device paths
+ *
+ */
+
+#include "efi.h"
+#include "efi/Protocol/DevicePath.h"
+
+/**
+ * Initialise device path
+ *
+ * @v name Variable name
+ * @v type Type
+ * @v subtype Subtype
+ */
+#define EFI_DEVPATH_INIT( name, type, subtype ) { \
+ .Type = (type), \
+ .SubType = (subtype), \
+ .Length[0] = ( sizeof (name) & 0xff ), \
+ .Length[1] = ( sizeof (name) >> 8 ), \
+ }
+
+/**
+ * Initialise device path
+ *
+ * @v path Device path
+ * @v type Type
+ * @v subtype Subtype
+ * @v len Length
+ */
+static inline __attribute__ (( always_inline )) void
+efi_devpath_init ( EFI_DEVICE_PATH_PROTOCOL *path, unsigned int type,
+ unsigned int subtype, size_t len ) {
+
+ path->Type = type;
+ path->SubType = subtype;
+ path->Length[0] = ( len & 0xff );
+ path->Length[1] = ( len >> 8 );
+}
+
+/**
+ * Initialise device path end
+ *
+ * @v name Variable name
+ */
+#define EFI_DEVPATH_END_INIT( name ) \
+ EFI_DEVPATH_INIT ( name, END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE )
+
+/**
+ * Initialise device path end
+ *
+ * @v path Device path
+ */
+static inline __attribute__ (( always_inline )) void
+efi_devpath_end_init ( EFI_DEVICE_PATH_PROTOCOL *path ) {
+
+ efi_devpath_init ( path, END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof ( *path ) );
+}
+
+extern EFI_DEVICE_PATH_PROTOCOL *
+efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
+
+#endif /* _EFIPATH_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * EFI relocations
+ *
+ * Derived from iPXE's elf2efi.c
+ *
+ */
+
+#define PACKAGE "wimboot"
+#define PACKAGE_VERSION VERSION
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <bfd.h>
+#include "efi.h"
+#include "efi/IndustryStandard/PeImage.h"
+#include "wimboot.h"
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+/* Maintain compatibility with binutils 2.34 */
+#ifndef bfd_get_section_vma
+#define bfd_get_section_vma(bfd, ptr) bfd_section_vma(ptr)
+#endif
+#ifndef bfd_get_section_flags
+#define bfd_get_section_flags(bfd, ptr) bfd_section_flags(ptr)
+#endif
+
+/** PE header maximum length
+ *
+ * This maximum length is guaranteed by the fact that the PE headers
+ * have to fit entirely before the start of the bzImage header.
+ */
+#define PE_HEADER_LEN 512
+
+/** .reloc section index */
+#define RELOC_SECTION_INDEX 3
+
+/** PE relocations */
+struct pe_relocs {
+ struct pe_relocs *next;
+ unsigned long start_rva;
+ unsigned int used_relocs;
+ unsigned int total_relocs;
+ uint16_t *relocs;
+};
+
+/** Command-line options */
+struct options {
+ /** Verbosity */
+ int verbosity;
+};
+
+/**
+ * Allocate memory
+ *
+ * @v len Length of memory to allocate
+ * @ret ptr Pointer to allocated memory
+ */
+static void * xmalloc ( size_t len ) {
+ void *ptr;
+
+ ptr = malloc ( len );
+ if ( ! ptr ) {
+ eprintf ( "Could not allocate %zd bytes\n", len );
+ exit ( 1 );
+ }
+
+ return ptr;
+}
+
+/**
+ * Write to file
+ *
+ * @v fd File descriptor
+ * @v data Data
+ * @v len Length of data
+ */
+static void xwrite ( int fd, const void *data, size_t len ) {
+ ssize_t written;
+
+ written = write ( fd, data, len );
+ if ( written < 0 ) {
+ eprintf ( "Could not write %zd bytes: %s\n",
+ len, strerror ( errno ) );
+ exit ( 1 );
+ }
+ if ( ( size_t ) written != len ) {
+ eprintf ( "Wrote only %zd of %zd bytes\n", written, len );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Seek to file position
+ *
+ * @v fd File descriptor
+ * @v offset Offset
+ * @v whence Origin
+ */
+static void xlseek ( int fd, off_t offset, int whence ) {
+ off_t pos;
+
+ pos = lseek ( fd, offset, whence );
+ if ( pos < 0 ) {
+ eprintf ( "Could not seek: %s\n", strerror ( errno ) );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Close file
+ *
+ * @v fd File descriptor
+ */
+static void xclose ( int fd ) {
+
+ if ( close ( fd ) < 0 ) {
+ eprintf ( "Could not close: %s\n", strerror ( errno ) );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Open input BFD file
+ *
+ * @v filename File name
+ * @ret ibfd BFD file
+ */
+static bfd * open_input_bfd ( const char *filename ) {
+ bfd *bfd;
+
+ /* Open the file */
+ bfd = bfd_openr ( filename, NULL );
+ if ( ! bfd ) {
+ eprintf ( "Cannot open %s: ", filename );
+ bfd_perror ( NULL );
+ exit ( 1 );
+ }
+
+ /* The call to bfd_check_format() must be present, otherwise
+ * we get a segfault from later BFD calls.
+ */
+ if ( ! bfd_check_format ( bfd, bfd_object ) ) {
+ eprintf ( "%s is not an object file: ", filename );
+ bfd_perror ( NULL );
+ exit ( 1 );
+ }
+
+ return bfd;
+}
+
+/**
+ * Read symbol table
+ *
+ * @v bfd BFD file
+ */
+static asymbol ** read_symtab ( bfd *bfd ) {
+ long symtab_size;
+ asymbol **symtab;
+ long symcount;
+
+ /* Get symbol table size */
+ symtab_size = bfd_get_symtab_upper_bound ( bfd );
+ if ( symtab_size < 0 ) {
+ bfd_perror ( "Could not get symbol table upper bound" );
+ exit ( 1 );
+ }
+
+ /* Allocate and read symbol table */
+ symtab = xmalloc ( symtab_size );
+ symcount = bfd_canonicalize_symtab ( bfd, symtab );
+ if ( symcount < 0 ) {
+ bfd_perror ( "Cannot read symbol table" );
+ exit ( 1 );
+ }
+
+ return symtab;
+}
+
+/**
+ * Read relocation table
+ *
+ * @v bfd BFD file
+ * @v symtab Symbol table
+ * @v section Section
+ * @v symtab Symbol table
+ * @ret reltab Relocation table
+ */
+static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
+ asection *section ) {
+ long reltab_size;
+ arelent **reltab;
+ long numrels;
+
+ /* Get relocation table size */
+ reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
+ if ( reltab_size < 0 ) {
+ bfd_perror ( "Could not get relocation table upper bound" );
+ exit ( 1 );
+ }
+
+ /* Allocate and read relocation table */
+ reltab = xmalloc ( reltab_size );
+ numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
+ if ( numrels < 0 ) {
+ bfd_perror ( "Cannot read relocation table" );
+ exit ( 1 );
+ }
+
+ return reltab;
+}
+
+/**
+ * Generate entry in PE relocation table
+ *
+ * @v pe_reltab PE relocation table
+ * @v rva RVA
+ * @v size Size of relocation entry
+ */
+static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
+ unsigned long rva, size_t size ) {
+ unsigned long start_rva;
+ uint16_t reloc;
+ struct pe_relocs *pe_rel;
+ uint16_t *relocs;
+
+ /* Construct */
+ start_rva = ( rva & ~0xfff );
+ reloc = ( rva & 0xfff );
+ switch ( size ) {
+ case 8:
+ reloc |= 0xa000;
+ break;
+ case 4:
+ reloc |= 0x3000;
+ break;
+ case 2:
+ reloc |= 0x2000;
+ break;
+ default:
+ eprintf ( "Unsupported relocation size %zd\n", size );
+ exit ( 1 );
+ }
+
+ /* Locate or create PE relocation table */
+ for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
+ if ( pe_rel->start_rva == start_rva )
+ break;
+ }
+ if ( ! pe_rel ) {
+ pe_rel = xmalloc ( sizeof ( *pe_rel ) );
+ memset ( pe_rel, 0, sizeof ( *pe_rel ) );
+ pe_rel->next = *pe_reltab;
+ *pe_reltab = pe_rel;
+ pe_rel->start_rva = start_rva;
+ }
+
+ /* Expand relocation list if necessary */
+ if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
+ relocs = pe_rel->relocs;
+ } else {
+ pe_rel->total_relocs = ( pe_rel->total_relocs ?
+ ( pe_rel->total_relocs * 2 ) : 256 );
+ relocs = xmalloc ( pe_rel->total_relocs *
+ sizeof ( pe_rel->relocs[0] ) );
+ memset ( relocs, 0,
+ pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
+ memcpy ( relocs, pe_rel->relocs,
+ pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
+ free ( pe_rel->relocs );
+ pe_rel->relocs = relocs;
+ }
+
+ /* Store relocation */
+ pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
+}
+
+/**
+ * Process relocation record
+ *
+ * @v bfd BFD file
+ * @v section Section
+ * @v rel Relocation entry
+ * @v pe_reltab PE relocation table to fill in
+ */
+static void process_reloc ( bfd *bfd __unused, asection *section, arelent *rel,
+ struct pe_relocs **pe_reltab ) {
+ reloc_howto_type *howto = rel->howto;
+ asymbol *sym = *(rel->sym_ptr_ptr);
+ unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
+ rel->address - BASE_ADDRESS );
+
+ if ( bfd_is_abs_section ( sym->section ) ) {
+ /* Skip absolute symbols; the symbol value won't
+ * change when the object is loaded.
+ */
+ } else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
+ /* Generate an 8-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 8 );
+ } else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_32S" ) == 0 ) ) {
+ /* Generate a 4-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 4 );
+ } else if ( ( strcmp ( howto->name, "R_386_16" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_16" ) == 0 ) ) {
+ /* Generate a 2-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 2 );
+ } else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_PLT32" ) == 0 ) ) {
+ /* Skip PC-relative relocations; all relative offsets
+ * remain unaltered when the object is loaded.
+ */
+ } else {
+ eprintf ( "Unrecognised relocation type %s\n", howto->name );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Calculate size of binary PE relocation table
+ *
+ * @v fh File handle
+ * @v pe_reltab PE relocation table
+ * @ret size Size of binary table
+ */
+static size_t output_pe_reltab ( int fd, struct pe_relocs *pe_reltab ) {
+ EFI_IMAGE_BASE_RELOCATION header;
+ struct pe_relocs *pe_rel;
+ static uint8_t pad[16];
+ unsigned int num_relocs;
+ size_t size;
+ size_t pad_size;
+ size_t total_size = 0;
+
+ for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
+ num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
+ size = ( sizeof ( header ) +
+ ( num_relocs * sizeof ( uint16_t ) ) );
+ pad_size = ( ( -size ) & ( sizeof ( pad ) - 1 ) );
+ size += pad_size;
+ header.VirtualAddress = pe_rel->start_rva;
+ header.SizeOfBlock = size;
+ xwrite ( fd, &header, sizeof ( header ) );
+ xwrite ( fd, pe_rel->relocs,
+ ( num_relocs * sizeof ( uint16_t ) ) );
+ xwrite ( fd, pad, pad_size );
+ total_size += size;
+ }
+
+ return total_size;
+}
+
+/**
+ * Add relocation information
+ *
+ * @v elf_name ELF file name
+ * @v pe_name PE file name
+ */
+static void efireloc ( const char *elf_name, const char *pe_name ) {
+ struct pe_relocs *pe_reltab = NULL;
+ int fd;
+ EFI_IMAGE_DOS_HEADER *dos;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *nt;
+ EFI_IMAGE_DATA_DIRECTORY *data_dir;
+ EFI_IMAGE_SECTION_HEADER *pe_sections;
+ UINT32 *image_size;
+ bfd *bfd;
+ asymbol **symtab;
+ asection *section;
+ arelent **reltab;
+ arelent **rel;
+ size_t reloc_len;
+
+ /* Open the output file */
+ fd = open ( pe_name, O_RDWR );
+ if ( fd < 0 ) {
+ eprintf ( "Could not open %s: %s\n",
+ pe_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Map the output file header */
+ dos = mmap ( NULL, PE_HEADER_LEN, ( PROT_READ | PROT_WRITE ),
+ MAP_SHARED, fd, 0 );
+ if ( ! dos ) {
+ eprintf ( "Could not mmap %s: %s\n",
+ pe_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Locate the modifiable fields within the output file header */
+ nt = ( ( ( void * ) dos ) + dos->e_lfanew );
+ if ( nt->Pe32.FileHeader.Machine == EFI_IMAGE_MACHINE_IA32 ) {
+ image_size = &nt->Pe32.OptionalHeader.SizeOfImage;
+ data_dir = nt->Pe32.OptionalHeader.DataDirectory;
+ pe_sections = ( ( ( void * ) nt ) + sizeof ( nt->Pe32 ) );
+ } else if ( nt->Pe32Plus.FileHeader.Machine == EFI_IMAGE_MACHINE_X64 ) {
+ image_size = &nt->Pe32Plus.OptionalHeader.SizeOfImage;
+ data_dir = nt->Pe32Plus.OptionalHeader.DataDirectory;
+ pe_sections = ( ( ( void * ) nt ) + sizeof ( nt->Pe32Plus ) );
+ } else {
+ eprintf ( "Unrecognised machine type\n" );
+ exit ( 1 );
+ }
+
+ /* Open the input file */
+ bfd = open_input_bfd ( elf_name );
+ symtab = read_symtab ( bfd );
+
+ /* For each input section, create the appropriate relocation records */
+ for ( section = bfd->sections ; section ; section = section->next ) {
+ /* Discard non-allocatable sections */
+ if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
+ continue;
+ /* Add relocations from this section */
+ reltab = read_reltab ( bfd, symtab, section );
+ for ( rel = reltab ; *rel ; rel++ )
+ process_reloc ( bfd, section, *rel, &pe_reltab );
+ free ( reltab );
+ }
+
+ /* Close input file */
+ bfd_close ( bfd );
+
+ /* Generate relocation section */
+ xlseek ( fd, 0, SEEK_END );
+ reloc_len = output_pe_reltab ( fd, pe_reltab );
+
+ /* Modify image header */
+ *image_size += reloc_len;
+ data_dir[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = reloc_len;
+ pe_sections[RELOC_SECTION_INDEX].Misc.VirtualSize = reloc_len;
+ pe_sections[RELOC_SECTION_INDEX].SizeOfRawData = reloc_len;
+
+ /* Unmap output file header */
+ munmap ( dos, PE_HEADER_LEN );
+
+ /* Close output file */
+ xclose ( fd );
+}
+
+/**
+ * Print help
+ *
+ * @v program_name Program name
+ */
+static void print_help ( const char *program_name ) {
+ eprintf ( "Syntax: %s [-v|-q] infile outfile\n", program_name );
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opts Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+ struct options *opts ) {
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "verbose", 0, NULL, 'v' },
+ { "quiet", 0, NULL, 'q' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( ( c = getopt_long ( argc, argv, "hvq",
+ long_options,
+ &option_index ) ) == -1 ) {
+ break;
+ }
+
+ switch ( c ) {
+ case 'v':
+ opts->verbosity++;
+ break;
+ case 'q':
+ if ( opts->verbosity )
+ opts->verbosity--;
+ break;
+ case 'h':
+ print_help ( argv[0] );
+ exit ( 0 );
+ case '?':
+ default:
+ exit ( 2 );
+ }
+ }
+ return optind;
+}
+
+/**
+ * Main program
+ *
+ * @v argc Number of arguments
+ * @v argv Command-line arguments
+ * @ret rc Return status code
+ */
+int main ( int argc, char **argv ) {
+ struct options opts = {
+ .verbosity = 0,
+ };
+ int infile_index;
+ const char *infile;
+ const char *outfile;
+
+ /* Initialise libbfd */
+ bfd_init();
+
+ /* Parse command-line arguments */
+ infile_index = parse_options ( argc, argv, &opts );
+ if ( argc != ( infile_index + 2 ) ) {
+ print_help ( argv[0] );
+ exit ( 2 );
+ }
+ infile = argv[infile_index];
+ outfile = argv[infile_index + 1];
+
+ /* Add relocation information */
+ efireloc ( infile, outfile );
+
+ return 0;
+}
--- /dev/null
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Error numbers
+ *
+ */
+
+#endif /* _ERRNO_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Huffman alphabets
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include "wimboot.h"
+#include "huffman.h"
+
+/**
+ * Transcribe binary value (for debugging)
+ *
+ * @v value Value
+ * @v bits Length of value (in bits)
+ * @ret string Transcribed value
+ */
+static const char * huffman_bin ( unsigned long value, unsigned int bits ) {
+ static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ];
+ char *out = buf;
+
+ /* Sanity check */
+ assert ( bits < sizeof ( buf ) );
+
+ /* Transcribe value */
+ while ( bits-- )
+ *(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' );
+ *out = '\0';
+
+ return buf;
+}
+
+/**
+ * Dump Huffman alphabet (for debugging)
+ *
+ * @v alphabet Huffman alphabet
+ */
+static void __attribute__ (( unused ))
+huffman_dump_alphabet ( struct huffman_alphabet *alphabet ) {
+ struct huffman_symbols *sym;
+ unsigned int bits;
+ unsigned int huf;
+ unsigned int i;
+
+ /* Dump symbol table for each utilised length */
+ for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
+ sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
+ sym = &alphabet->huf[ bits - 1 ];
+ if ( sym->freq == 0 )
+ continue;
+ huf = ( sym->start >> sym->shift );
+ DBG ( "Huffman length %d start \"%s\" freq %d:", bits,
+ huffman_bin ( huf, sym->bits ), sym->freq );
+ for ( i = 0 ; i < sym->freq ; i++ ) {
+ DBG ( " %03x", sym->raw[ huf + i ] );
+ }
+ DBG ( "\n" );
+ }
+
+ /* Dump quick lookup table */
+ DBG ( "Huffman quick lookup:" );
+ for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) /
+ sizeof ( alphabet->lookup[0] ) ) ; i++ ) {
+ DBG ( " %d", ( alphabet->lookup[i] + 1 ) );
+ }
+ DBG ( "\n" );
+}
+
+/**
+ * Construct Huffman alphabet
+ *
+ * @v alphabet Huffman alphabet
+ * @v lengths Symbol length table
+ * @v count Number of symbols
+ * @ret rc Return status code
+ */
+int huffman_alphabet ( struct huffman_alphabet *alphabet,
+ uint8_t *lengths, unsigned int count ) {
+ struct huffman_symbols *sym;
+ unsigned int huf;
+ unsigned int cum_freq;
+ unsigned int bits;
+ unsigned int raw;
+ unsigned int adjustment;
+ unsigned int prefix;
+ int empty;
+ int complete;
+
+ /* Clear symbol table */
+ memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) );
+
+ /* Count number of symbols with each Huffman-coded length */
+ empty = 1;
+ for ( raw = 0 ; raw < count ; raw++ ) {
+ bits = lengths[raw];
+ if ( bits ) {
+ alphabet->huf[ bits - 1 ].freq++;
+ empty = 0;
+ }
+ }
+
+ /* In the degenerate case of having no symbols (i.e. an unused
+ * alphabet), generate a trivial alphabet with exactly two
+ * single-bit codes. This allows callers to avoid having to
+ * check for this special case.
+ */
+ if ( empty )
+ alphabet->huf[0].freq = 2;
+
+ /* Populate Huffman-coded symbol table */
+ huf = 0;
+ cum_freq = 0;
+ for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
+ sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
+ sym = &alphabet->huf[ bits - 1 ];
+ sym->bits = bits;
+ sym->shift = ( HUFFMAN_BITS - bits );
+ sym->start = ( huf << sym->shift );
+ sym->raw = &alphabet->raw[cum_freq];
+ huf += sym->freq;
+ if ( huf > ( 1U << bits ) ) {
+ DBG ( "Huffman alphabet has too many symbols with "
+ "lengths <=%d\n", bits );
+ return -1;
+ }
+ huf <<= 1;
+ cum_freq += sym->freq;
+ }
+ complete = ( huf == ( 1U << bits ) );
+
+ /* Populate raw symbol table */
+ for ( raw = 0 ; raw < count ; raw++ ) {
+ bits = lengths[raw];
+ if ( bits ) {
+ sym = &alphabet->huf[ bits - 1 ];
+ *(sym->raw++) = raw;
+ }
+ }
+
+ /* Adjust Huffman-coded symbol table raw pointers and populate
+ * quick lookup table.
+ */
+ for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) /
+ sizeof ( alphabet->huf[0] ) ) ; bits++ ) {
+ sym = &alphabet->huf[ bits - 1 ];
+
+ /* Adjust raw pointer */
+ sym->raw -= sym->freq; /* Reset to first symbol */
+ adjustment = ( sym->start >> sym->shift );
+ sym->raw -= adjustment; /* Adjust for quick indexing */
+
+ /* Populate quick lookup table */
+ for ( prefix = ( sym->start >> HUFFMAN_QL_SHIFT ) ;
+ prefix < ( 1 << HUFFMAN_QL_BITS ) ; prefix++ ) {
+ alphabet->lookup[prefix] = ( bits - 1 );
+ }
+ }
+
+ /* Check that there are no invalid codes */
+ if ( ! complete ) {
+ DBG ( "Huffman alphabet is incomplete\n" );
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Get Huffman symbol set
+ *
+ * @v alphabet Huffman alphabet
+ * @v huf Raw input value (normalised to HUFFMAN_BITS bits)
+ * @ret sym Huffman symbol set
+ */
+struct huffman_symbols * huffman_sym ( struct huffman_alphabet *alphabet,
+ unsigned int huf ) {
+ struct huffman_symbols *sym;
+ unsigned int lookup_index;
+
+ /* Find symbol set for this length */
+ lookup_index = ( huf >> HUFFMAN_QL_SHIFT );
+ sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ];
+ while ( huf < sym->start )
+ sym--;
+ return sym;
+}
--- /dev/null
+#ifndef _HUFFMAN_H
+#define _HUFFMAN_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Huffman alphabets
+ *
+ */
+
+#include <stdint.h>
+
+/** Maximum length of a Huffman symbol (in bits) */
+#define HUFFMAN_BITS 16
+
+/** Raw huffman symbol */
+typedef uint16_t huffman_raw_symbol_t;
+
+/** Quick lookup length for a Huffman symbol (in bits)
+ *
+ * This is a policy decision.
+ */
+#define HUFFMAN_QL_BITS 7
+
+/** Quick lookup shift */
+#define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS )
+
+/** A Huffman-coded set of symbols of a given length */
+struct huffman_symbols {
+ /** Length of Huffman-coded symbols (in bits) */
+ uint8_t bits;
+ /** Shift to normalise symbols of this length to HUFFMAN_BITS bits */
+ uint8_t shift;
+ /** Number of Huffman-coded symbols having this length */
+ uint16_t freq;
+ /** First symbol of this length (normalised to HUFFMAN_BITS bits)
+ *
+ * Stored as a 32-bit value to allow the value
+ * (1<<HUFFMAN_BITS ) to be used for empty sets of symbols
+ * longer than the maximum utilised length.
+ */
+ uint32_t start;
+ /** Raw symbols having this length */
+ huffman_raw_symbol_t *raw;
+};
+
+/** A Huffman-coded alphabet */
+struct huffman_alphabet {
+ /** Huffman-coded symbol set for each length */
+ struct huffman_symbols huf[HUFFMAN_BITS];
+ /** Quick lookup table */
+ uint8_t lookup[ 1 << HUFFMAN_QL_BITS ];
+ /** Raw symbols
+ *
+ * Ordered by Huffman-coded symbol length, then by symbol
+ * value. This field has a variable length.
+ */
+ huffman_raw_symbol_t raw[0];
+};
+
+/**
+ * Get Huffman symbol length
+ *
+ * @v sym Huffman symbol set
+ * @ret len Length (in bits)
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+huffman_len ( struct huffman_symbols *sym ) {
+
+ return sym->bits;
+}
+
+/**
+ * Get Huffman symbol value
+ *
+ * @v sym Huffman symbol set
+ * @v huf Raw input value (normalised to HUFFMAN_BITS bits)
+ * @ret raw Raw symbol value
+ */
+static inline __attribute__ (( always_inline )) huffman_raw_symbol_t
+huffman_raw ( struct huffman_symbols *sym, unsigned int huf ) {
+
+ return sym->raw[ huf >> sym->shift ];
+}
+
+extern int huffman_alphabet ( struct huffman_alphabet *alphabet,
+ uint8_t *lengths, unsigned int count );
+extern struct huffman_symbols *
+huffman_sym ( struct huffman_alphabet *alphabet, unsigned int huf );
+
+#endif /* _HUFFMAN_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * INT 13 emulation
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "wimboot.h"
+#include "int13.h"
+#include "vdisk.h"
+
+/** Emulated drive number */
+static int vdisk_drive;
+
+/**
+ * Initialise emulation
+ *
+ * @ret drive Emulated drive number
+ */
+int initialise_int13 ( void ) {
+
+ /* Determine drive number */
+ vdisk_drive = ( 0x80 | INT13_DRIVE_COUNT++ );
+ DBG ( "Emulating drive %#02x\n", vdisk_drive );
+
+ return vdisk_drive;
+}
+
+/**
+ * INT 13, 08 - Get drive parameters
+ *
+ * @ret ch Low bits of maximum cylinder number
+ * @ret cl (bits 7:6) High bits of maximum cylinder number
+ * @ret cl (bits 5:0) Maximum sector number
+ * @ret dh Maximum head number
+ * @ret dl Number of drives
+ * @ret ah Status code
+ */
+static void int13_get_parameters ( struct bootapp_callback_params *params ) {
+ unsigned int max_cylinder = ( VDISK_CYLINDERS - 1 );
+ unsigned int max_head = ( VDISK_HEADS - 1 );
+ unsigned int max_sector = ( VDISK_SECTORS_PER_TRACK - 0 /* sic */ );
+ unsigned int num_drives;
+ unsigned int min_num_drives;
+
+ /* Calculate number of drives to report */
+ num_drives = INT13_DRIVE_COUNT;
+ min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
+ if ( num_drives < min_num_drives )
+ num_drives = min_num_drives;
+
+ /* Fill in drive parameters */
+ params->ch = ( max_cylinder & 0xff );
+ params->cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
+ params->dh = max_head;
+ params->dl = num_drives;
+ DBG2 ( "Get parameters: C/H/S = %d/%d/%d, drives = %d\n",
+ ( max_cylinder + 1 ), ( max_head + 1 ), max_sector, num_drives );
+
+ /* Success */
+ params->ah = 0;
+}
+
+/**
+ * INT 13, 15 - Get disk type
+ *
+ * @ret cx:dx Sector count
+ * @ret ah Type code
+ */
+static void int13_get_disk_type ( struct bootapp_callback_params *params ) {
+ uint32_t sector_count = VDISK_COUNT;
+ uint8_t drive_type = INT13_DISK_TYPE_HDD;
+
+ /* Fill in disk type */
+ params->cx = ( sector_count >> 16 );
+ params->dx = ( sector_count & 0xffff );
+ params->ah = drive_type;
+ DBG2 ( "Get disk type: sectors = %#08x, type = %d\n",
+ sector_count, drive_type );
+}
+
+/**
+ * INT 13, 41 - Extensions installation check
+ *
+ * @v bx 0x55aa
+ * @ret bx 0xaa55
+ * @ret cx Extensions API support bitmap
+ * @ret ah API version
+ */
+static void int13_extension_check ( struct bootapp_callback_params *params ) {
+
+ /* Fill in extension information */
+ params->bx = 0xaa55;
+ params->cx = INT13_EXTENSION_LINEAR;
+ params->ah = INT13_EXTENSION_VER_1_X;
+ DBG2 ( "Extensions installation check\n" );
+}
+
+/**
+ * INT 13, 48 - Get extended parameters
+ *
+ * @v ds:si Drive parameter table
+ * @ret ah Status code
+ */
+static void
+int13_get_extended_parameters ( struct bootapp_callback_params *params ) {
+ struct int13_disk_parameters *disk_params;
+
+ /* Fill in extended parameters */
+ disk_params = REAL_PTR ( params->ds, params->si );
+ memset ( disk_params, 0, sizeof ( *disk_params ) );
+ disk_params->bufsize = sizeof ( *disk_params );
+ disk_params->flags = INT13_FL_DMA_TRANSPARENT;
+ disk_params->cylinders = VDISK_CYLINDERS;
+ disk_params->heads = VDISK_HEADS;
+ disk_params->sectors_per_track = VDISK_SECTORS_PER_TRACK;
+ disk_params->sectors = VDISK_COUNT;
+ disk_params->sector_size = VDISK_SECTOR_SIZE;
+ DBG2 ( "Get extended parameters: C/H/S = %d/%d/%d, sectors = %#08llx "
+ "(%d bytes)\n", disk_params->cylinders, disk_params->heads,
+ disk_params->sectors_per_track, disk_params->sectors,
+ disk_params->sector_size );
+
+ /* Success */
+ params->ah = 0;
+}
+
+/**
+ * INT 13, 42 - Extended read
+ *
+ * @v ds:si Disk address packet
+ * @ret ah Status code
+ */
+static void int13_extended_read ( struct bootapp_callback_params *params ) {
+ struct int13_disk_address *disk_address;
+ void *data;
+
+ /* Read from emulated disk */
+ disk_address = REAL_PTR ( params->ds, params->si );
+ data = REAL_PTR ( disk_address->buffer.segment,
+ disk_address->buffer.offset );
+ vdisk_read ( disk_address->lba, disk_address->count, data );
+
+ /* Success */
+ params->ah = 0;
+}
+
+/**
+ * Emulate INT 13 drive
+ *
+ * @v params Parameters
+ */
+void emulate_int13 ( struct bootapp_callback_params *params ) {
+ int command = params->ah;
+ int drive = params->dl;
+ int min_num_drives;
+ unsigned long eflags;
+
+ if ( drive == vdisk_drive ) {
+
+ /* Emulated drive - handle internally */
+
+ /* Populate eflags with a sensible starting value */
+ __asm__ ( "pushf\n\t"
+ "pop %0\n\t"
+ : "=r" ( eflags ) );
+ params->eflags = ( eflags & ~CF );
+
+ /* Handle command */
+ switch ( command ) {
+ case INT13_GET_PARAMETERS:
+ int13_get_parameters ( params );
+ break;
+ case INT13_GET_DISK_TYPE:
+ int13_get_disk_type ( params );
+ break;
+ case INT13_EXTENSION_CHECK:
+ int13_extension_check ( params );
+ break;
+ case INT13_GET_EXTENDED_PARAMETERS:
+ int13_get_extended_parameters ( params );
+ break;
+ case INT13_EXTENDED_READ:
+ int13_extended_read ( params );
+ break;
+ default:
+ DBG ( "Unrecognised INT 13,%02x\n", command );
+ params->eflags |= CF;
+ break;
+ }
+
+ } else {
+
+ /* Pass through command to underlying INT 13 */
+ call_interrupt ( params );
+
+ /* Modify drive count, if applicable */
+ if ( command == INT13_GET_PARAMETERS ) {
+ min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
+ if ( params->dl < min_num_drives )
+ params->dl = min_num_drives;
+ }
+ }
+}
--- /dev/null
+#ifndef _INT13_H
+#define _INT13_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * INT 13 emulation
+ *
+ */
+
+/** Construct a pointer from a real-mode segment:offset address */
+#define REAL_PTR( segment, offset ) \
+ ( ( void * ) ( intptr_t ) ( ( (segment) << 4 ) + offset ) )
+
+/** Get drive parameters */
+#define INT13_GET_PARAMETERS 0x08
+/** Get disk type */
+#define INT13_GET_DISK_TYPE 0x15
+/** Extensions installation check */
+#define INT13_EXTENSION_CHECK 0x41
+/** Extended read */
+#define INT13_EXTENDED_READ 0x42
+/** Get extended drive parameters */
+#define INT13_GET_EXTENDED_PARAMETERS 0x48
+
+/** Operation completed successfully */
+#define INT13_STATUS_SUCCESS 0x00
+/** Invalid function or parameter */
+#define INT13_STATUS_INVALID 0x01
+/** Read error */
+#define INT13_STATUS_READ_ERROR 0x04
+/** Reset failed */
+#define INT13_STATUS_RESET_FAILED 0x05
+/** Write error */
+#define INT13_STATUS_WRITE_ERROR 0xcc
+
+/** No such drive */
+#define INT13_DISK_TYPE_NONE 0x00
+/** Floppy without change-line support */
+#define INT13_DISK_TYPE_FDD 0x01
+/** Floppy with change-line support */
+#define INT13_DISK_TYPE_FDD_CL 0x02
+/** Hard disk */
+#define INT13_DISK_TYPE_HDD 0x03
+
+/** Extended disk access functions supported */
+#define INT13_EXTENSION_LINEAR 0x01
+
+/** INT13 extensions version 1.x */
+#define INT13_EXTENSION_VER_1_X 0x01
+
+/** DMA boundary errors handled transparently */
+#define INT13_FL_DMA_TRANSPARENT 0x01
+
+/** BIOS drive counter */
+#define INT13_DRIVE_COUNT ( *( ( ( uint8_t * ) REAL_PTR ( 0x40, 0x75 ) ) ) )
+
+/** An INT 13 disk address packet */
+struct int13_disk_address {
+ /** Size of the packet, in bytes */
+ uint8_t bufsize;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Block count */
+ uint8_t count;
+ /** Reserved */
+ uint8_t reserved_b;
+ /** Data buffer */
+ struct segoff buffer;
+ /** Starting block number */
+ uint64_t lba;
+ /** Data buffer (EDD 3.0+ only) */
+ uint64_t buffer_phys;
+ /** Block count (EDD 4.0+ only) */
+ uint32_t long_count;
+ /** Reserved */
+ uint32_t reserved_c;
+} __attribute__ (( packed ));
+
+/** INT 13 disk parameters */
+struct int13_disk_parameters {
+ /** Size of this structure */
+ uint16_t bufsize;
+ /** Flags */
+ uint16_t flags;
+ /** Number of cylinders */
+ uint32_t cylinders;
+ /** Number of heads */
+ uint32_t heads;
+ /** Number of sectors per track */
+ uint32_t sectors_per_track;
+ /** Total number of sectors on drive */
+ uint64_t sectors;
+ /** Bytes per sector */
+ uint16_t sector_size;
+} __attribute__ (( packed ));
+
+extern int initialise_int13 ( void );
+extern void emulate_int13 ( struct bootapp_callback_params *params );
+
+#endif /* _INT13_H */
--- /dev/null
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <wchar.h>
+#include <ipxe/vsprintf.h>
+
+/** @file */
+
+#define CHAR_LEN 0 /**< "hh" length modifier */
+#define SHORT_LEN 1 /**< "h" length modifier */
+#define INT_LEN 2 /**< no length modifier */
+#define LONG_LEN 3 /**< "l" length modifier */
+#define LONGLONG_LEN 4 /**< "ll" length modifier */
+#define SIZE_T_LEN 5 /**< "z" length modifier */
+
+static uint8_t type_sizes[] = {
+ [CHAR_LEN] = sizeof ( char ),
+ [SHORT_LEN] = sizeof ( short ),
+ [INT_LEN] = sizeof ( int ),
+ [LONG_LEN] = sizeof ( long ),
+ [LONGLONG_LEN] = sizeof ( long long ),
+ [SIZE_T_LEN] = sizeof ( size_t ),
+};
+
+/**
+ * Use lower-case for hexadecimal digits
+ *
+ * Note that this value is set to 0x20 since that makes for very
+ * efficient calculations. (Bitwise-ORing with @c LCASE converts to a
+ * lower-case character, for example.)
+ */
+#define LCASE 0x20
+
+/**
+ * Use "alternate form"
+ *
+ * For hexadecimal numbers, this means to add a "0x" or "0X" prefix to
+ * the number.
+ */
+#define ALT_FORM 0x02
+
+/**
+ * Use zero padding
+ *
+ * Note that this value is set to 0x10 since that allows the pad
+ * character to be calculated as @c 0x20|(flags&ZPAD)
+ */
+#define ZPAD 0x10
+
+/**
+ * Format a hexadecimal number
+ *
+ * @v end End of buffer to contain number
+ * @v num Number to format
+ * @v width Minimum field width
+ * @v flags Format flags
+ * @ret ptr End of buffer
+ *
+ * Fills a buffer in reverse order with a formatted hexadecimal
+ * number. The number will be zero-padded to the specified width.
+ * Lower-case and "alternate form" (i.e. "0x" prefix) flags may be
+ * set.
+ *
+ * There must be enough space in the buffer to contain the largest
+ * number that this function can format.
+ */
+static char * format_hex ( char *end, unsigned long long num, int width,
+ int flags ) {
+ char *ptr = end;
+ int case_mod = ( flags & LCASE );
+ int pad = ( ( flags & ZPAD ) | ' ' );
+
+ /* Generate the number */
+ do {
+ *(--ptr) = "0123456789ABCDEF"[ num & 0xf ] | case_mod;
+ num >>= 4;
+ } while ( num );
+
+ /* Pad to width */
+ while ( ( end - ptr ) < width )
+ *(--ptr) = pad;
+
+ /* Add "0x" or "0X" if alternate form specified */
+ if ( flags & ALT_FORM ) {
+ *(--ptr) = 'X' | case_mod;
+ *(--ptr) = '0';
+ }
+
+ return ptr;
+}
+
+/**
+ * Format a decimal number
+ *
+ * @v end End of buffer to contain number
+ * @v num Number to format
+ * @v width Minimum field width
+ * @v flags Format flags
+ * @ret ptr End of buffer
+ *
+ * Fills a buffer in reverse order with a formatted decimal number.
+ * The number will be space-padded to the specified width.
+ *
+ * There must be enough space in the buffer to contain the largest
+ * number that this function can format.
+ */
+static char * format_decimal ( char *end, signed long num, int width,
+ int flags ) {
+ char *ptr = end;
+ int negative = 0;
+ int zpad = ( flags & ZPAD );
+ int pad = ( zpad | ' ' );
+
+ /* Generate the number */
+ if ( num < 0 ) {
+ negative = 1;
+ num = -num;
+ }
+ do {
+ *(--ptr) = '0' + ( num % 10 );
+ num /= 10;
+ } while ( num );
+
+ /* Add "-" if necessary */
+ if ( negative && ( ! zpad ) )
+ *(--ptr) = '-';
+
+ /* Pad to width */
+ while ( ( end - ptr ) < width )
+ *(--ptr) = pad;
+
+ /* Add "-" if necessary */
+ if ( negative && zpad )
+ *ptr = '-';
+
+ return ptr;
+}
+
+/**
+ * Print character via a printf context
+ *
+ * @v ctx Context
+ * @v c Character
+ *
+ * Call's the printf_context::handler() method and increments
+ * printf_context::len.
+ */
+static inline void cputchar ( struct printf_context *ctx, unsigned int c ) {
+ ctx->handler ( ctx, c );
+ ++ctx->len;
+}
+
+/**
+ * Write a formatted string to a printf context
+ *
+ * @v ctx Context
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
+ int flags;
+ int width;
+ uint8_t *length;
+ char *ptr;
+ char tmp_buf[32]; /* 32 is enough for all numerical formats.
+ * Insane width fields could overflow this buffer. */
+ wchar_t *wptr;
+
+ /* Initialise context */
+ ctx->len = 0;
+
+ for ( ; *fmt ; fmt++ ) {
+ /* Pass through ordinary characters */
+ if ( *fmt != '%' ) {
+ cputchar ( ctx, *fmt );
+ continue;
+ }
+ fmt++;
+ /* Process flag characters */
+ flags = 0;
+ for ( ; ; fmt++ ) {
+ if ( *fmt == '#' ) {
+ flags |= ALT_FORM;
+ } else if ( *fmt == '0' ) {
+ flags |= ZPAD;
+ } else {
+ /* End of flag characters */
+ break;
+ }
+ }
+ /* Process field width */
+ width = 0;
+ for ( ; ; fmt++ ) {
+ if ( ( ( unsigned ) ( *fmt - '0' ) ) < 10 ) {
+ width = ( width * 10 ) + ( *fmt - '0' );
+ } else {
+ break;
+ }
+ }
+ /* We don't do floating point */
+ /* Process length modifier */
+ length = &type_sizes[INT_LEN];
+ for ( ; ; fmt++ ) {
+ if ( *fmt == 'h' ) {
+ length--;
+ } else if ( *fmt == 'l' ) {
+ length++;
+ } else if ( *fmt == 'z' ) {
+ length = &type_sizes[SIZE_T_LEN];
+ } else {
+ break;
+ }
+ }
+ /* Process conversion specifier */
+ ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
+ *ptr = '\0';
+ wptr = NULL;
+ if ( *fmt == 'c' ) {
+ if ( length < &type_sizes[LONG_LEN] ) {
+ cputchar ( ctx, va_arg ( args, unsigned int ) );
+ } else {
+ wchar_t wc;
+ size_t len;
+
+ wc = va_arg ( args, wint_t );
+ len = wcrtomb ( tmp_buf, wc, NULL );
+ tmp_buf[len] = '\0';
+ ptr = tmp_buf;
+ }
+ } else if ( *fmt == 's' ) {
+ if ( length < &type_sizes[LONG_LEN] ) {
+ ptr = va_arg ( args, char * );
+ } else {
+ wptr = va_arg ( args, wchar_t * );
+ }
+ if ( ( ptr == NULL ) && ( wptr == NULL ) )
+ ptr = "<NULL>";
+ } else if ( *fmt == 'p' ) {
+ intptr_t ptrval;
+
+ ptrval = ( intptr_t ) va_arg ( args, void * );
+ ptr = format_hex ( ptr, ptrval, width,
+ ( ALT_FORM | LCASE ) );
+ } else if ( ( *fmt & ~0x20 ) == 'X' ) {
+ unsigned long long hex;
+
+ flags |= ( *fmt & 0x20 ); /* LCASE */
+ if ( *length >= sizeof ( unsigned long long ) ) {
+ hex = va_arg ( args, unsigned long long );
+ } else if ( *length >= sizeof ( unsigned long ) ) {
+ hex = va_arg ( args, unsigned long );
+ } else {
+ hex = va_arg ( args, unsigned int );
+ }
+ ptr = format_hex ( ptr, hex, width, flags );
+ } else if ( ( *fmt == 'd' ) || ( *fmt == 'i' ) ){
+ signed long decimal;
+
+ if ( *length >= sizeof ( signed long ) ) {
+ decimal = va_arg ( args, signed long );
+ } else {
+ decimal = va_arg ( args, signed int );
+ }
+ ptr = format_decimal ( ptr, decimal, width, flags );
+ } else {
+ *(--ptr) = *fmt;
+ }
+ /* Write out conversion result */
+ if ( wptr == NULL ) {
+ for ( ; *ptr ; ptr++ ) {
+ cputchar ( ctx, *ptr );
+ }
+ } else {
+ for ( ; *wptr ; wptr++ ) {
+ size_t len = wcrtomb ( tmp_buf, *wptr, NULL );
+ for ( ptr = tmp_buf ; len-- ; ptr++ ) {
+ cputchar ( ctx, *ptr );
+ }
+ }
+ }
+ }
+
+ return ctx->len;
+}
+
+/** Context used by vsnprintf() and friends */
+struct sputc_context {
+ struct printf_context ctx;
+ /** Buffer for formatted string (used by printf_sputc()) */
+ char *buf;
+ /** Buffer length (used by printf_sputc()) */
+ size_t max_len;
+};
+
+/**
+ * Write character to buffer
+ *
+ * @v ctx Context
+ * @v c Character
+ */
+static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
+ struct sputc_context * sctx =
+ container_of ( ctx, struct sputc_context, ctx );
+
+ if ( ctx->len < sctx->max_len )
+ sctx->buf[ctx->len] = c;
+}
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ *
+ * If the buffer is too small to contain the string, the returned
+ * length is the length that would have been written had enough space
+ * been available.
+ */
+int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) {
+ struct sputc_context sctx;
+ size_t len;
+ size_t end;
+
+ /* Hand off to vcprintf */
+ sctx.ctx.handler = printf_sputc;
+ sctx.buf = buf;
+ sctx.max_len = size;
+ len = vcprintf ( &sctx.ctx, fmt, args );
+
+ /* Add trailing NUL */
+ if ( size ) {
+ end = size - 1;
+ if ( len < end )
+ end = len;
+ buf[end] = '\0';
+ }
+
+ return len;
+}
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vsnprintf ( buf, size, fmt, args );
+ va_end ( args );
+ return i;
+}
+
+/**
+ * Version of vsnprintf() that accepts a signed buffer size
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int vssnprintf ( char *buf, ssize_t ssize, const char *fmt, va_list args ) {
+
+ /* Treat negative buffer size as zero buffer size */
+ if ( ssize < 0 )
+ ssize = 0;
+
+ /* Hand off to vsnprintf */
+ return vsnprintf ( buf, ssize, fmt, args );
+}
+
+/**
+ * Version of vsnprintf() that accepts a signed buffer size
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ) {
+ va_list args;
+ int len;
+
+ /* Hand off to vssnprintf */
+ va_start ( args, fmt );
+ len = vssnprintf ( buf, ssize, fmt, args );
+ va_end ( args );
+ return len;
+}
+
+/**
+ * Write character to console
+ *
+ * @v ctx Context
+ * @v c Character
+ */
+static void printf_putchar ( struct printf_context *ctx __unused,
+ unsigned int c ) {
+ putchar ( c );
+}
+
+/**
+ * Write a formatted string to the console
+ *
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int vprintf ( const char *fmt, va_list args ) {
+ struct printf_context ctx;
+
+ /* Hand off to vcprintf */
+ ctx.handler = printf_putchar;
+ return vcprintf ( &ctx, fmt, args );
+}
+
+/**
+ * Write a formatted string to the console.
+ *
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int printf ( const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vprintf ( fmt, args );
+ va_end ( args );
+ return i;
+}
--- /dev/null
+#ifndef _IPXE_VSPRINTF_H
+#define _IPXE_VSPRINTF_H
+
+/** @file
+ *
+ * printf() and friends
+ *
+ * Etherboot's printf() functions understand the following subset of
+ * the standard C printf()'s format specifiers:
+ *
+ * - Flag characters
+ * - '#' - Alternate form (i.e. "0x" prefix)
+ * - '0' - Zero-pad
+ * - Field widths
+ * - Length modifiers
+ * - 'hh' - Signed / unsigned char
+ * - 'h' - Signed / unsigned short
+ * - 'l' - Signed / unsigned long
+ * - 'll' - Signed / unsigned long long
+ * - 'z' - Signed / unsigned size_t
+ * - Conversion specifiers
+ * - 'd' - Signed decimal
+ * - 'x','X' - Unsigned hexadecimal
+ * - 'c' - Character
+ * - 's' - String
+ * - 'p' - Pointer
+ *
+ * Hexadecimal numbers are always zero-padded to the specified field
+ * width (if any); decimal numbers are always space-padded. Decimal
+ * long longs are not supported.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/**
+ * A printf context
+ *
+ * Contexts are used in order to be able to share code between
+ * vprintf() and vsnprintf(), without requiring the allocation of a
+ * buffer for vprintf().
+ */
+struct printf_context {
+ /**
+ * Character handler
+ *
+ * @v ctx Context
+ * @v c Character
+ *
+ * This method is called for each character written to the
+ * formatted string.
+ */
+ void ( * handler ) ( struct printf_context *ctx, unsigned int c );
+ /** Length of formatted string
+ *
+ * When handler() is called, @len will be set to the number of
+ * characters written so far (i.e. zero for the first call to
+ * handler()).
+ */
+ size_t len;
+};
+
+extern size_t vcprintf ( struct printf_context *ctx, const char *fmt,
+ va_list args );
+extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt,
+ va_list args );
+extern int __attribute__ (( format ( printf, 3, 4 ) ))
+ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... );
+
+#endif /* _IPXE_VSPRINTF_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * LZNT1 decompression
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include "wimboot.h"
+#include "lznt1.h"
+
+/**
+ * Decompress LZNT1-compressed data block
+ *
+ * @v data Compressed data
+ * @v limit Length of compressed data up to end of block
+ * @v offset Starting offset within compressed data
+ * @v block Decompression buffer for this block, or NULL
+ * @ret out_len Length of decompressed block, or negative error
+ */
+static ssize_t lznt1_block ( const void *data, size_t limit, size_t offset,
+ void *block ) {
+ const uint16_t *tuple;
+ const uint8_t *copy_src;
+ uint8_t *copy_dest = block;
+ size_t copy_len;
+ size_t block_out_len = 0;
+ unsigned int split = 12;
+ unsigned int next_threshold = 16;
+ unsigned int tag_bit = 0;
+ unsigned int tag = 0;
+
+ while ( offset != limit ) {
+
+ /* Extract tag */
+ if ( tag_bit == 0 ) {
+ tag = *( ( uint8_t * ) ( data + offset ) );
+ offset++;
+ if ( offset == limit )
+ break;
+ }
+
+ /* Calculate copy source and length */
+ if ( tag & 1 ) {
+
+ /* Compressed value */
+ if ( offset + sizeof ( *tuple ) > limit ) {
+ DBG ( "LZNT1 compressed value overrun at "
+ "%#zx\n", offset );
+ return -1;
+ }
+ tuple = ( data + offset );
+ offset += sizeof ( *tuple );
+ copy_len = LZNT1_VALUE_LEN ( *tuple, split );
+ block_out_len += copy_len;
+ if ( copy_dest ) {
+ copy_src = ( copy_dest -
+ LZNT1_VALUE_OFFSET ( *tuple,
+ split ) );
+ while ( copy_len-- )
+ *(copy_dest++) = *(copy_src++);
+ }
+
+ } else {
+
+ /* Uncompressed value */
+ copy_src = ( data + offset );
+ if ( copy_dest )
+ *(copy_dest++) = *copy_src;
+ offset++;
+ block_out_len++;
+ }
+
+ /* Update split, if applicable */
+ while ( block_out_len > next_threshold ) {
+ split--;
+ next_threshold <<= 1;
+ }
+
+ /* Move to next value */
+ tag >>= 1;
+ tag_bit = ( ( tag_bit + 1 ) % 8 );
+ }
+
+ return block_out_len;
+}
+
+/**
+ * Decompress LZNT1-compressed data
+ *
+ * @v data Compressed data
+ * @v len Length of compressed data
+ * @v buf Decompression buffer, or NULL
+ * @ret out_len Length of decompressed data, or negative error
+ */
+ssize_t lznt1_decompress ( const void *data, size_t len, void *buf ) {
+ const uint16_t *header;
+ const uint8_t *end;
+ size_t offset = 0;
+ ssize_t out_len = 0;
+ size_t block_len;
+ size_t limit;
+ void *block;
+ ssize_t block_out_len;
+
+ while ( offset != len ) {
+
+ /* Check for end marker */
+ if ( ( offset + sizeof ( *end ) ) == len ) {
+ end = ( data + offset );
+ if ( *end == 0 )
+ break;
+ }
+
+ /* Extract block header */
+ if ( ( offset + sizeof ( *header ) ) > len ) {
+ DBG ( "LZNT1 block header overrun at %#zx\n", offset );
+ return -1;
+ }
+ header = ( data + offset );
+ offset += sizeof ( *header );
+
+ /* Process block */
+ block_len = LZNT1_BLOCK_LEN ( *header );
+ if ( LZNT1_BLOCK_COMPRESSED ( *header ) ) {
+
+ /* Compressed block */
+ DBG2 ( "LZNT1 compressed block %#zx+%#zx\n",
+ offset, block_len );
+ limit = ( offset + block_len );
+ block = ( buf ? ( buf + out_len ) : NULL );
+ block_out_len = lznt1_block ( data, limit, offset,
+ block );
+ if ( block_out_len < 0 )
+ return block_out_len;
+ offset += block_len;
+ out_len += block_out_len;
+
+ } else {
+
+ /* Uncompressed block */
+ if ( ( offset + block_len ) > len ) {
+ DBG ( "LZNT1 uncompressed block overrun at "
+ "%#zx+%#zx\n", offset, block_len );
+ return -1;
+ }
+ DBG2 ( "LZNT1 uncompressed block %#zx+%#zx\n",
+ offset, block_len );
+ if ( buf ) {
+ memcpy ( ( buf + out_len ), ( data + offset ),
+ block_len );
+ }
+ offset += block_len;
+ out_len += block_len;
+ }
+ }
+
+ return out_len;
+}
--- /dev/null
+#ifndef _LZNT1_H
+#define _LZNT1_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * LZNT1 decompression
+ *
+ */
+
+#include <stdint.h>
+
+/** Extract LZNT1 block length */
+#define LZNT1_BLOCK_LEN( header ) ( ( (header) & 0x0fff ) + 1 )
+
+/** Determine if LZNT1 block is compressed */
+#define LZNT1_BLOCK_COMPRESSED( header ) ( (header) & 0x8000 )
+
+/** Extract LZNT1 compressed value length */
+#define LZNT1_VALUE_LEN( tuple, split ) \
+ ( ( (tuple) & ( ( 1 << (split) ) - 1 ) ) + 3 )
+
+/** Extract LZNT1 compressed value offset */
+#define LZNT1_VALUE_OFFSET( tuple, split ) ( ( (tuple) >> split ) + 1 )
+
+extern ssize_t lznt1_decompress ( const void *data, size_t len, void *buf );
+
+#endif /* _LZNT1_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * LZX decompression
+ *
+ * This algorithm is derived jointly from the document "[MS-PATCH]:
+ * LZX DELTA Compression and Decompression", available from
+ *
+ * http://msdn.microsoft.com/en-us/library/cc483133.aspx
+ *
+ * and from the file lzx-decompress.c in the wimlib source code.
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include "wimboot.h"
+#include "huffman.h"
+#include "lzx.h"
+
+/** Base positions, indexed by position slot */
+static unsigned int lzx_position_base[LZX_POSITION_SLOTS];
+
+/**
+ * Attempt to accumulate bits from LZX bitstream
+ *
+ * @v lzx Decompressor
+ * @v bits Number of bits to accumulate
+ * @v norm_value Accumulated value (normalised to 16 bits)
+ *
+ * Note that there may not be sufficient accumulated bits in the
+ * bitstream; callers must check that sufficient bits are available
+ * before using the value.
+ */
+static int lzx_accumulate ( struct lzx *lzx, unsigned int bits ) {
+ const uint16_t *src16;
+
+ /* Accumulate more bits if required */
+ if ( ( lzx->bits < bits ) &&
+ ( lzx->input.offset < lzx->input.len ) ) {
+ src16 = ( ( void * ) lzx->input.data + lzx->input.offset );
+ lzx->input.offset += sizeof ( *src16 );
+ lzx->accumulator |= ( *src16 << ( 16 - lzx->bits ) );
+ lzx->bits += 16;
+ }
+
+ return ( lzx->accumulator >> 16 );
+}
+
+/**
+ * Consume accumulated bits from LZX bitstream
+ *
+ * @v lzx Decompressor
+ * @v bits Number of bits to consume
+ * @ret rc Return status code
+ */
+static int lzx_consume ( struct lzx *lzx, unsigned int bits ) {
+
+ /* Fail if insufficient bits are available */
+ if ( lzx->bits < bits ) {
+ DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
+ lzx->input.offset, lzx->input.len, lzx->output.offset );
+ return -1;
+ }
+
+ /* Consume bits */
+ lzx->accumulator <<= bits;
+ lzx->bits -= bits;
+
+ return 0;
+}
+
+/**
+ * Get bits from LZX bitstream
+ *
+ * @v lzx Decompressor
+ * @v bits Number of bits to fetch
+ * @ret value Value, or negative error
+ */
+static int lzx_getbits ( struct lzx *lzx, unsigned int bits ) {
+ int norm_value;
+ int rc;
+
+ /* Accumulate more bits if required */
+ norm_value = lzx_accumulate ( lzx, bits );
+
+ /* Consume bits */
+ if ( ( rc = lzx_consume ( lzx, bits ) ) != 0 )
+ return rc;
+
+ return ( norm_value >> ( 16 - bits ) );
+}
+
+/**
+ * Align LZX bitstream for byte access
+ *
+ * @v lzx Decompressor
+ * @v bits Minimum number of padding bits
+ * @ret rc Return status code
+ */
+static int lzx_align ( struct lzx *lzx, unsigned int bits ) {
+ int pad;
+
+ /* Get padding bits */
+ pad = lzx_getbits ( lzx, bits );
+ if ( pad < 0 )
+ return pad;
+
+ /* Consume all accumulated bits */
+ lzx_consume ( lzx, lzx->bits );
+
+ return 0;
+}
+
+/**
+ * Get bytes from LZX bitstream
+ *
+ * @v lzx Decompressor
+ * @v data Data buffer, or NULL
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int lzx_getbytes ( struct lzx *lzx, void *data, size_t len ) {
+
+ /* Sanity check */
+ if ( ( lzx->input.offset + len ) > lzx->input.len ) {
+ DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n",
+ lzx->input.offset, lzx->input.len, lzx->output.offset );
+ return -1;
+ }
+
+ /* Copy data */
+ if ( data )
+ memcpy ( data, ( lzx->input.data + lzx->input.offset ), len );
+ lzx->input.offset += len;
+
+ return 0;
+}
+
+/**
+ * Decode LZX Huffman-coded symbol
+ *
+ * @v lzx Decompressor
+ * @v alphabet Huffman alphabet
+ * @ret raw Raw symbol, or negative error
+ */
+static int lzx_decode ( struct lzx *lzx, struct huffman_alphabet *alphabet ) {
+ struct huffman_symbols *sym;
+ int huf;
+ int rc;
+
+ /* Accumulate sufficient bits */
+ huf = lzx_accumulate ( lzx, HUFFMAN_BITS );
+ if ( huf < 0 )
+ return huf;
+
+ /* Decode symbol */
+ sym = huffman_sym ( alphabet, huf );
+
+ /* Consume bits */
+ if ( ( rc = lzx_consume ( lzx, huffman_len ( sym ) ) ) != 0 )
+ return rc;
+
+ return huffman_raw ( sym, huf );
+}
+
+/**
+ * Generate Huffman alphabet from raw length table
+ *
+ * @v lzx Decompressor
+ * @v count Number of symbols
+ * @v bits Length of each length (in bits)
+ * @v lengths Lengths table to fill in
+ * @v alphabet Huffman alphabet to fill in
+ * @ret rc Return status code
+ */
+static int lzx_raw_alphabet ( struct lzx *lzx, unsigned int count,
+ unsigned int bits, uint8_t *lengths,
+ struct huffman_alphabet *alphabet ) {
+ unsigned int i;
+ int len;
+ int rc;
+
+ /* Read lengths */
+ for ( i = 0 ; i < count ; i++ ) {
+ len = lzx_getbits ( lzx, bits );
+ if ( len < 0 )
+ return len;
+ lengths[i] = len;
+ }
+
+ /* Generate Huffman alphabet */
+ if ( ( rc = huffman_alphabet ( alphabet, lengths, count ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Generate pretree
+ *
+ * @v lzx Decompressor
+ * @v count Number of symbols
+ * @v lengths Lengths table to fill in
+ * @ret rc Return status code
+ */
+static int lzx_pretree ( struct lzx *lzx, unsigned int count,
+ uint8_t *lengths ) {
+ unsigned int i;
+ unsigned int length;
+ int dup = 0;
+ int code;
+ int rc;
+
+ /* Generate pretree alphabet */
+ if ( ( rc = lzx_raw_alphabet ( lzx, LZX_PRETREE_CODES,
+ LZX_PRETREE_BITS, lzx->pretree_lengths,
+ &lzx->pretree ) ) != 0 )
+ return rc;
+
+ /* Read lengths */
+ for ( i = 0 ; i < count ; i++ ) {
+
+ if ( dup ) {
+
+ /* Duplicate previous length */
+ lengths[i] = lengths[ i - 1 ];
+ dup--;
+
+ } else {
+
+ /* Get next code */
+ code = lzx_decode ( lzx, &lzx->pretree );
+ if ( code < 0 )
+ return code;
+
+ /* Interpret code */
+ if ( code <= 16 ) {
+ length = ( ( lengths[i] - code + 17 ) % 17 );
+ } else if ( code == 17 ) {
+ length = 0;
+ dup = lzx_getbits ( lzx, 4 );
+ if ( dup < 0 )
+ return dup;
+ dup += 3;
+ } else if ( code == 18 ) {
+ length = 0;
+ dup = lzx_getbits ( lzx, 5 );
+ if ( dup < 0 )
+ return dup;
+ dup += 19;
+ } else if ( code == 19 ) {
+ length = 0;
+ dup = lzx_getbits ( lzx, 1 );
+ if ( dup < 0 )
+ return dup;
+ dup += 3;
+ code = lzx_decode ( lzx, &lzx->pretree );
+ if ( code < 0 )
+ return code;
+ length = ( ( lengths[i] - code + 17 ) % 17 );
+ } else {
+ DBG ( "Unrecognised pretree code %d\n", code );
+ return -1;
+ }
+ lengths[i] = length;
+ }
+ }
+
+ /* Sanity check */
+ if ( dup ) {
+ DBG ( "Pretree duplicate overrun\n" );
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Generate aligned offset Huffman alphabet
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ */
+static int lzx_alignoffset_alphabet ( struct lzx *lzx ) {
+ int rc;
+
+ /* Generate aligned offset alphabet */
+ if ( ( rc = lzx_raw_alphabet ( lzx, LZX_ALIGNOFFSET_CODES,
+ LZX_ALIGNOFFSET_BITS,
+ lzx->alignoffset_lengths,
+ &lzx->alignoffset ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Generate main Huffman alphabet
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ */
+static int lzx_main_alphabet ( struct lzx *lzx ) {
+ int rc;
+
+ /* Generate literal symbols pretree */
+ if ( ( rc = lzx_pretree ( lzx, LZX_MAIN_LIT_CODES,
+ lzx->main_lengths.literals ) ) != 0 ) {
+ DBG ( "Could not construct main literal pretree\n" );
+ return rc;
+ }
+
+ /* Generate remaining symbols pretree */
+ if ( ( rc = lzx_pretree ( lzx, ( LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ),
+ lzx->main_lengths.remainder ) ) != 0 ) {
+ DBG ( "Could not construct main remainder pretree\n" );
+ return rc;
+ }
+
+ /* Generate Huffman alphabet */
+ if ( ( rc = huffman_alphabet ( &lzx->main, lzx->main_lengths.literals,
+ LZX_MAIN_CODES ) ) != 0 ) {
+ DBG ( "Could not generate main alphabet\n" );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Generate length Huffman alphabet
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ */
+static int lzx_length_alphabet ( struct lzx *lzx ) {
+ int rc;
+
+ /* Generate pretree */
+ if ( ( rc = lzx_pretree ( lzx, LZX_LENGTH_CODES,
+ lzx->length_lengths ) ) != 0 ) {
+ DBG ( "Could not generate length pretree\n" );
+ return rc;
+ }
+
+ /* Generate Huffman alphabet */
+ if ( ( rc = huffman_alphabet ( &lzx->length, lzx->length_lengths,
+ LZX_LENGTH_CODES ) ) != 0 ) {
+ DBG ( "Could not generate length alphabet\n" );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Process LZX block header
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ */
+static int lzx_block_header ( struct lzx *lzx ) {
+ size_t block_len;
+ int block_type;
+ int default_len;
+ int len_high;
+ int len_low;
+ int rc;
+
+ /* Get block type */
+ block_type = lzx_getbits ( lzx, LZX_BLOCK_TYPE_BITS );
+ if ( block_type < 0 )
+ return block_type;
+ lzx->block_type = block_type;
+
+ /* Check block length */
+ default_len = lzx_getbits ( lzx, 1 );
+ if ( default_len < 0 )
+ return default_len;
+ if ( default_len ) {
+ block_len = LZX_DEFAULT_BLOCK_LEN;
+ } else {
+ len_high = lzx_getbits ( lzx, 8 );
+ if ( len_high < 0 )
+ return len_high;
+ len_low = lzx_getbits ( lzx, 8 );
+ if ( len_low < 0 )
+ return len_low;
+ block_len = ( ( len_high << 8 ) | len_low );
+ }
+ lzx->output.threshold = ( lzx->output.offset + block_len );
+
+ /* Handle block type */
+ switch ( block_type ) {
+ case LZX_BLOCK_ALIGNOFFSET :
+ /* Generated aligned offset alphabet */
+ if ( ( rc = lzx_alignoffset_alphabet ( lzx ) ) != 0 )
+ return rc;
+ /* Fall through */
+ case LZX_BLOCK_VERBATIM :
+ /* Generate main alphabet */
+ if ( ( rc = lzx_main_alphabet ( lzx ) ) != 0 )
+ return rc;
+ /* Generate lengths alphabet */
+ if ( ( rc = lzx_length_alphabet ( lzx ) ) != 0 )
+ return rc;
+ break;
+ case LZX_BLOCK_UNCOMPRESSED :
+ /* Align input stream */
+ if ( ( rc = lzx_align ( lzx, 1 ) ) != 0 )
+ return rc;
+ /* Read new repeated offsets */
+ if ( ( rc = lzx_getbytes ( lzx, &lzx->repeated_offset,
+ sizeof ( lzx->repeated_offset )))!=0)
+ return rc;
+ break;
+ default:
+ DBG ( "Unrecognised block type %d\n", block_type );
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Process uncompressed data
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ */
+static int lzx_uncompressed ( struct lzx *lzx ) {
+ void *data;
+ size_t len;
+ int rc;
+
+ /* Copy bytes */
+ data = ( lzx->output.data ?
+ ( lzx->output.data + lzx->output.offset ) : NULL );
+ len = ( lzx->output.threshold - lzx->output.offset );
+ if ( ( rc = lzx_getbytes ( lzx, data, len ) ) != 0 )
+ return rc;
+
+ /* Align input stream */
+ if ( len % 2 )
+ lzx->input.offset++;
+
+ return 0;
+}
+
+/**
+ * Process an LZX token
+ *
+ * @v lzx Decompressor
+ * @ret rc Return status code
+ *
+ * Variable names are chosen to match the LZX specification
+ * pseudo-code.
+ */
+static int lzx_token ( struct lzx *lzx ) {
+ unsigned int length_header;
+ unsigned int position_slot;
+ unsigned int offset_bits;
+ unsigned int i;
+ size_t match_offset;
+ size_t match_length;
+ int verbatim_bits;
+ int aligned_bits;
+ int main;
+ int length;
+ uint8_t *copy;
+
+ /* Get main symelse*/
+ main = lzx_decode ( lzx, &lzx->main );
+ if ( main < 0 )
+ return main;
+
+ /* Check for literals */
+ if ( main < LZX_MAIN_LIT_CODES ) {
+ if ( lzx->output.data )
+ lzx->output.data[lzx->output.offset] = main;
+ lzx->output.offset++;
+ return 0;
+ }
+ main -= LZX_MAIN_LIT_CODES;
+
+ /* Calculate the match length */
+ length_header = ( main & 7 );
+ if ( length_header == 7 ) {
+ length = lzx_decode ( lzx, &lzx->length );
+ if ( length < 0 )
+ return length;
+ } else {
+ length = 0;
+ }
+ match_length = ( length_header + 2 + length );
+
+ /* Calculate the position slot */
+ position_slot = ( main >> 3 );
+ if ( position_slot < LZX_REPEATED_OFFSETS ) {
+
+ /* Repeated offset */
+ match_offset = lzx->repeated_offset[position_slot];
+ lzx->repeated_offset[position_slot] = lzx->repeated_offset[0];
+ lzx->repeated_offset[0] = match_offset;
+
+ } else {
+
+ /* Non-repeated offset */
+ offset_bits = lzx_footer_bits ( position_slot );
+ if ( ( lzx->block_type == LZX_BLOCK_ALIGNOFFSET ) &&
+ ( offset_bits >= 3 ) ) {
+ verbatim_bits = lzx_getbits ( lzx, ( offset_bits - 3 ));
+ if ( verbatim_bits < 0 )
+ return verbatim_bits;
+ verbatim_bits <<= 3;
+ aligned_bits = lzx_decode ( lzx, &lzx->alignoffset );
+ if ( aligned_bits < 0 )
+ return aligned_bits;
+ } else {
+ verbatim_bits = lzx_getbits ( lzx, offset_bits );
+ if ( verbatim_bits < 0 )
+ return verbatim_bits;
+ aligned_bits = 0;
+ }
+ match_offset = ( lzx_position_base[position_slot] +
+ verbatim_bits + aligned_bits - 2 );
+
+ /* Update repeated offset list */
+ for ( i = ( LZX_REPEATED_OFFSETS - 1 ) ; i > 0 ; i-- )
+ lzx->repeated_offset[i] = lzx->repeated_offset[ i - 1 ];
+ lzx->repeated_offset[0] = match_offset;
+ }
+
+ /* Copy data */
+ if ( match_offset > lzx->output.offset ) {
+ DBG ( "LZX match underrun out %#zx offset %#zx len %#zx\n",
+ lzx->output.offset, match_offset, match_length );
+ return -1;
+ }
+ if ( lzx->output.data ) {
+ copy = &lzx->output.data[lzx->output.offset];
+ for ( i = 0 ; i < match_length ; i++ )
+ copy[i] = copy[ i - match_offset ];
+ }
+ lzx->output.offset += match_length;
+
+ return 0;
+}
+
+/**
+ * Translate E8 jump addresses
+ *
+ * @v lzx Decompressor
+ */
+static void lzx_translate_jumps ( struct lzx *lzx ) {
+ size_t offset;
+ int32_t *target;
+
+ /* Sanity check */
+ if ( lzx->output.offset < 10 )
+ return;
+
+ /* Scan for jump instructions */
+ for ( offset = 0 ; offset < ( lzx->output.offset - 10 ) ; offset++ ) {
+
+ /* Check for jump instruction */
+ if ( lzx->output.data[offset] != 0xe8 )
+ continue;
+
+ /* Translate jump target */
+ target = ( ( int32_t * ) &lzx->output.data[ offset + 1 ] );
+ if ( *target >= 0 ) {
+ if ( *target < LZX_WIM_MAGIC_FILESIZE )
+ *target -= offset;
+ } else {
+ if ( *target >= -( ( int32_t ) offset ) )
+ *target += LZX_WIM_MAGIC_FILESIZE;
+ }
+ offset += sizeof ( *target );
+ }
+}
+
+/**
+ * Decompress LZX-compressed data
+ *
+ * @v data Compressed data
+ * @v len Length of compressed data
+ * @v buf Decompression buffer, or NULL
+ * @ret out_len Length of decompressed data, or negative error
+ */
+ssize_t lzx_decompress ( const void *data, size_t len, void *buf ) {
+ struct lzx lzx;
+ unsigned int i;
+ int rc;
+
+ /* Sanity check */
+ if ( len % 2 ) {
+ DBG ( "LZX cannot handle odd-length input data\n" );
+ return -1;
+ }
+
+ /* Initialise global state, if required */
+ if ( ! lzx_position_base[ LZX_POSITION_SLOTS - 1 ] ) {
+ for ( i = 1 ; i < LZX_POSITION_SLOTS ; i++ ) {
+ lzx_position_base[i] =
+ ( lzx_position_base[i-1] +
+ ( 1 << lzx_footer_bits ( i - 1 ) ) );
+ }
+ }
+
+ /* Initialise decompressor */
+ memset ( &lzx, 0, sizeof ( lzx ) );
+ lzx.input.data = data;
+ lzx.input.len = len;
+ lzx.output.data = buf;
+ for ( i = 0 ; i < LZX_REPEATED_OFFSETS ; i++ )
+ lzx.repeated_offset[i] = 1;
+
+ /* Process blocks */
+ while ( lzx.input.offset < lzx.input.len ) {
+
+ /* Process block header */
+ if ( ( rc = lzx_block_header ( &lzx ) ) != 0 )
+ return rc;
+
+ /* Process block contents */
+ if ( lzx.block_type == LZX_BLOCK_UNCOMPRESSED ) {
+
+ /* Copy uncompressed data */
+ if ( ( rc = lzx_uncompressed ( &lzx ) ) != 0 )
+ return rc;
+
+ } else {
+
+ /* Process token stream */
+ while ( lzx.output.offset < lzx.output.threshold ) {
+ if ( ( rc = lzx_token ( &lzx ) ) != 0 )
+ return rc;
+ }
+ }
+ }
+
+ /* Postprocess to undo E8 jump compression */
+ if ( lzx.output.data )
+ lzx_translate_jumps ( &lzx );
+
+ return lzx.output.offset;
+}
--- /dev/null
+#ifndef _LZX_H
+#define _LZX_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * LZX decompression
+ *
+ */
+
+#include <stdint.h>
+#include "huffman.h"
+
+/** Number of aligned offset codes */
+#define LZX_ALIGNOFFSET_CODES 8
+
+/** Aligned offset code length (in bits) */
+#define LZX_ALIGNOFFSET_BITS 3
+
+/** Number of pretree codes */
+#define LZX_PRETREE_CODES 20
+
+/** Pretree code length (in bits) */
+#define LZX_PRETREE_BITS 4
+
+/** Number of literal main codes */
+#define LZX_MAIN_LIT_CODES 256
+
+/** Number of position slots */
+#define LZX_POSITION_SLOTS 30
+
+/** Number of main codes */
+#define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) )
+
+/** Number of length codes */
+#define LZX_LENGTH_CODES 249
+
+/** Block type length (in bits) */
+#define LZX_BLOCK_TYPE_BITS 3
+
+/** Default block length */
+#define LZX_DEFAULT_BLOCK_LEN 32768
+
+/** Number of repeated offsets */
+#define LZX_REPEATED_OFFSETS 3
+
+/** Don't ask */
+#define LZX_WIM_MAGIC_FILESIZE 12000000
+
+/** Block types */
+enum lzx_block_type {
+ /** Verbatim block */
+ LZX_BLOCK_VERBATIM = 1,
+ /** Aligned offset block */
+ LZX_BLOCK_ALIGNOFFSET = 2,
+ /** Uncompressed block */
+ LZX_BLOCK_UNCOMPRESSED = 3,
+};
+
+/** An LZX input stream */
+struct lzx_input_stream {
+ /** Data */
+ const uint8_t *data;
+ /** Length */
+ size_t len;
+ /** Offset within stream */
+ size_t offset;
+};
+
+/** An LZX output stream */
+struct lzx_output_stream {
+ /** Data, or NULL */
+ uint8_t *data;
+ /** Offset within stream */
+ size_t offset;
+ /** End of current block within stream */
+ size_t threshold;
+};
+
+/** LZX decompressor */
+struct lzx {
+ /** Input stream */
+ struct lzx_input_stream input;
+ /** Output stream */
+ struct lzx_output_stream output;
+ /** Accumulator */
+ uint32_t accumulator;
+ /** Number of bits in accumulator */
+ unsigned int bits;
+ /** Block type */
+ enum lzx_block_type block_type;
+ /** Repeated offsets */
+ unsigned int repeated_offset[LZX_REPEATED_OFFSETS];
+
+ /** Aligned offset Huffman alphabet */
+ struct huffman_alphabet alignoffset;
+ /** Aligned offset raw symbols
+ *
+ * Must immediately follow the aligned offset Huffman
+ * alphabet.
+ */
+ huffman_raw_symbol_t alignoffset_raw[LZX_ALIGNOFFSET_CODES];
+ /** Aligned offset code lengths */
+ uint8_t alignoffset_lengths[LZX_ALIGNOFFSET_CODES];
+
+ /** Pretree Huffman alphabet */
+ struct huffman_alphabet pretree;
+ /** Pretree raw symbols
+ *
+ * Must immediately follow the pretree Huffman alphabet.
+ */
+ huffman_raw_symbol_t pretree_raw[LZX_PRETREE_CODES];
+ /** Preetree code lengths */
+ uint8_t pretree_lengths[LZX_PRETREE_CODES];
+
+ /** Main Huffman alphabet */
+ struct huffman_alphabet main;
+ /** Main raw symbols
+ *
+ * Must immediately follow the main Huffman alphabet.
+ */
+ huffman_raw_symbol_t main_raw[LZX_MAIN_CODES];
+ /** Main code lengths */
+ struct {
+ /** Literals */
+ uint8_t literals[LZX_MAIN_LIT_CODES];
+ /** Remaining symbols */
+ uint8_t remainder[ LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ];
+ } __attribute__ (( packed )) main_lengths;
+
+ /** Length Huffman alphabet */
+ struct huffman_alphabet length;
+ /** Length raw symbols
+ *
+ * Must immediately follow the length Huffman alphabet.
+ */
+ huffman_raw_symbol_t length_raw[LZX_LENGTH_CODES];
+ /** Length code lengths */
+ uint8_t length_lengths[LZX_LENGTH_CODES];
+};
+
+/**
+ * Calculate number of footer bits for a given position slot
+ *
+ * @v position_slot Position slot
+ * @ret footer_bits Number of footer bits
+ */
+static inline unsigned int lzx_footer_bits ( unsigned int position_slot ) {
+
+ if ( position_slot < 2 ) {
+ return 0;
+ } else if ( position_slot < 38 ) {
+ return ( ( position_slot / 2 ) - 1 );
+ } else {
+ return 17;
+ }
+}
+
+extern ssize_t lzx_decompress ( const void *data, size_t len, void *buf );
+
+#endif /* _LZX_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Main entry point
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include "wimboot.h"
+#include "peloader.h"
+#include "int13.h"
+#include "vdisk.h"
+#include "cpio.h"
+#include "lznt1.h"
+#include "xca.h"
+#include "cmdline.h"
+#include "wimpatch.h"
+#include "wimfile.h"
+#include "pause.h"
+#include "paging.h"
+#include "memmap.h"
+
+/** Start of our image (defined by linker) */
+extern char _start[];
+
+/** End of our image (defined by linker) */
+extern char _end[];
+
+/** Command line */
+char *cmdline;
+
+/** initrd */
+void *initrd;
+
+/** Length of initrd */
+size_t initrd_len;
+
+/** bootmgr.exe path within WIM */
+static const wchar_t bootmgr_path[] = L"\\Windows\\Boot\\PXE\\bootmgr.exe";
+
+/** Other paths within WIM */
+static const wchar_t *wim_paths[] = {
+ L"\\Windows\\Boot\\DVD\\PCAT\\boot.sdi",
+ L"\\Windows\\Boot\\DVD\\PCAT\\BCD",
+ L"\\Windows\\Boot\\Fonts\\segmono_boot.ttf",
+ L"\\Windows\\Boot\\Fonts\\segoen_slboot.ttf",
+ L"\\Windows\\Boot\\Fonts\\segoe_slboot.ttf",
+ L"\\Windows\\Boot\\Fonts\\wgl4_boot.ttf",
+ L"\\sms\\boot\\boot.sdi",
+ NULL
+};
+
+/** bootmgr.exe file */
+static struct vdisk_file *bootmgr;
+
+/** WIM image file */
+static struct vdisk_file *bootwim;
+
+/** Minimal length of embedded bootmgr.exe */
+#define BOOTMGR_MIN_LEN 16384
+
+/** 1MB memory threshold */
+#define ADDR_1MB 0x00100000
+
+/** 2GB memory threshold */
+#define ADDR_2GB 0x80000000
+
+/** Memory regions */
+enum {
+ WIMBOOT_REGION = 0,
+ PE_REGION,
+ INITRD_REGION,
+ NUM_REGIONS
+};
+
+/**
+ * Wrap interrupt callback
+ *
+ * @v params Parameters
+ */
+static void call_interrupt_wrapper ( struct bootapp_callback_params *params ) {
+ struct paging_state state;
+ uint16_t *attributes;
+
+ /* Handle/modify/pass-through interrupt as required */
+ if ( params->vector.interrupt == 0x13 ) {
+
+ /* Enable paging */
+ enable_paging ( &state );
+
+ /* Intercept INT 13 calls for the emulated drive */
+ emulate_int13 ( params );
+
+ /* Disable paging */
+ disable_paging ( &state );
+
+ } else if ( ( params->vector.interrupt == 0x10 ) &&
+ ( params->ax == 0x4f01 ) &&
+ ( ! cmdline_gui ) ) {
+
+ /* Mark all VESA video modes as unsupported */
+ attributes = REAL_PTR ( params->es, params->di );
+ call_interrupt ( params );
+ *attributes &= ~0x0001;
+
+ } else {
+
+ /* Pass through interrupt */
+ call_interrupt ( params );
+ }
+}
+
+/** Real-mode callback functions */
+static struct bootapp_callback_functions callback_fns = {
+ .call_interrupt = call_interrupt_wrapper,
+ .call_real = call_real,
+};
+
+/** Real-mode callbacks */
+static struct bootapp_callback callback = {
+ .fns = &callback_fns,
+};
+
+/** Boot application descriptor set */
+static struct {
+ /** Boot application descriptor */
+ struct bootapp_descriptor bootapp;
+ /** Boot application memory descriptor */
+ struct bootapp_memory_descriptor memory;
+ /** Boot application memory descriptor regions */
+ struct bootapp_memory_region regions[NUM_REGIONS];
+ /** Boot application entry descriptor */
+ struct bootapp_entry_descriptor entry;
+ struct bootapp_entry_wtf1_descriptor wtf1;
+ struct bootapp_entry_wtf2_descriptor wtf2;
+ struct bootapp_entry_wtf3_descriptor wtf3;
+ struct bootapp_entry_wtf3_descriptor wtf3_copy;
+ /** Boot application callback descriptor */
+ struct bootapp_callback_descriptor callback;
+ /** Boot application pointless descriptor */
+ struct bootapp_pointless_descriptor pointless;
+} __attribute__ (( packed )) bootapps = {
+ .bootapp = {
+ .signature = BOOTAPP_SIGNATURE,
+ .version = BOOTAPP_VERSION,
+ .len = sizeof ( bootapps ),
+ .arch = BOOTAPP_ARCH_I386,
+ .memory = offsetof ( typeof ( bootapps ), memory ),
+ .entry = offsetof ( typeof ( bootapps ), entry ),
+ .xxx = offsetof ( typeof ( bootapps ), wtf3_copy ),
+ .callback = offsetof ( typeof ( bootapps ), callback ),
+ .pointless = offsetof ( typeof ( bootapps ), pointless ),
+ },
+ .memory = {
+ .version = BOOTAPP_MEMORY_VERSION,
+ .len = sizeof ( bootapps.memory ),
+ .num_regions = NUM_REGIONS,
+ .region_len = sizeof ( bootapps.regions[0] ),
+ .reserved_len = sizeof ( bootapps.regions[0].reserved ),
+ },
+ .entry = {
+ .signature = BOOTAPP_ENTRY_SIGNATURE,
+ .flags = BOOTAPP_ENTRY_FLAGS,
+ },
+ .wtf1 = {
+ .flags = 0x11000001,
+ .len = sizeof ( bootapps.wtf1 ),
+ .extra_len = ( sizeof ( bootapps.wtf2 ) +
+ sizeof ( bootapps.wtf3 ) ),
+ },
+ .wtf3 = {
+ .flags = 0x00000006,
+ .len = sizeof ( bootapps.wtf3 ),
+ .boot_partition_offset = ( VDISK_VBR_LBA * VDISK_SECTOR_SIZE ),
+ .xxx = 0x01,
+ .mbr_signature = VDISK_MBR_SIGNATURE,
+ },
+ .wtf3_copy = {
+ .flags = 0x00000006,
+ .len = sizeof ( bootapps.wtf3 ),
+ .boot_partition_offset = ( VDISK_VBR_LBA * VDISK_SECTOR_SIZE ),
+ .xxx = 0x01,
+ .mbr_signature = VDISK_MBR_SIGNATURE,
+ },
+ .callback = {
+ .callback = &callback,
+ },
+ .pointless = {
+ .version = BOOTAPP_POINTLESS_VERSION,
+ },
+};
+
+/**
+ * Test if a paragraph is empty
+ *
+ * @v pgh Paragraph
+ * @ret is_empty Paragraph is empty (all zeroes)
+ */
+static int is_empty_pgh ( const void *pgh ) {
+ const uint32_t *dwords = pgh;
+
+ return ( ( dwords[0] | dwords[1] | dwords[2] | dwords[3] ) == 0 );
+}
+
+/**
+ * Read from file
+ *
+ * @v file Virtual file
+ * @v data Data buffer
+ * @v offset Offset
+ * @v len Length
+ */
+static void read_file ( struct vdisk_file *file, void *data, size_t offset,
+ size_t len ) {
+
+ memcpy ( data, ( file->opaque + offset ), len );
+}
+
+/**
+ * Add embedded bootmgr.exe extracted from bootmgr
+ *
+ * @v data File data
+ * @v len Length
+ * @ret file Virtual file, or NULL
+ *
+ * bootmgr.exe is awkward to obtain, since it is not available as a
+ * standalone file on the installation media, or on an installed
+ * system, or in a Windows PE image as created by WAIK or WADK. It
+ * can be extracted from a typical boot.wim image using ImageX, but
+ * this requires installation of the WAIK/WADK/wimlib.
+ *
+ * A compressed version of bootmgr.exe is contained within bootmgr,
+ * which is trivial to obtain.
+ */
+static struct vdisk_file * add_bootmgr ( const void *data, size_t len ) {
+ const uint8_t *compressed;
+ size_t offset;
+ size_t compressed_len;
+ ssize_t ( * decompress ) ( const void *data, size_t len, void *buf );
+ ssize_t decompressed_len;
+ size_t padded_len;
+
+ /* Look for an embedded compressed bootmgr.exe on an
+ * eight-byte boundary.
+ */
+ for ( offset = BOOTMGR_MIN_LEN ; offset < ( len - BOOTMGR_MIN_LEN ) ;
+ offset += 0x08 ) {
+
+ /* Initialise checks */
+ decompress = NULL;
+ compressed = ( data + offset );
+ compressed_len = ( len - offset );
+
+ /* Check for an embedded LZNT1-compressed bootmgr.exe.
+ * Since there is no way for LZNT1 to compress the
+ * initial "MZ" bytes of bootmgr.exe, we look for this
+ * signature starting three bytes after a paragraph
+ * boundary, with a preceding tag byte indicating that
+ * these two bytes would indeed be uncompressed.
+ */
+ if ( ( ( offset & 0x0f ) == 0x00 ) &&
+ ( ( compressed[0x02] & 0x03 ) == 0x00 ) &&
+ ( compressed[0x03] == 'M' ) &&
+ ( compressed[0x04] == 'Z' ) ) {
+ DBG ( "...checking for LZNT1-compressed bootmgr.exe at "
+ "+%#zx\n", offset );
+ decompress = lznt1_decompress;
+ }
+
+ /* Check for an embedded XCA-compressed bootmgr.exe.
+ * The bytes 0x00, 'M', and 'Z' will always be
+ * present, and so the corresponding symbols must have
+ * a non-zero Huffman length. The embedded image
+ * tends to have a large block of zeroes immediately
+ * beforehand, which we check for. It's implausible
+ * that the compressed data could contain substantial
+ * runs of zeroes, so we check for that too, in order
+ * to eliminate some common false positive matches.
+ */
+ if ( ( ( compressed[0x00] & 0x0f ) != 0x00 ) &&
+ ( ( compressed[0x26] & 0xf0 ) != 0x00 ) &&
+ ( ( compressed[0x2d] & 0x0f ) != 0x00 ) &&
+ ( is_empty_pgh ( compressed - 0x10 ) ) &&
+ ( ! is_empty_pgh ( ( compressed + 0x400 ) ) ) &&
+ ( ! is_empty_pgh ( ( compressed + 0x800 ) ) ) &&
+ ( ! is_empty_pgh ( ( compressed + 0xc00 ) ) ) ) {
+ DBG ( "...checking for XCA-compressed bootmgr.exe at "
+ "+%#zx\n", offset );
+ decompress = xca_decompress;
+ }
+
+ /* If we have not found a possible bootmgr.exe, skip
+ * to the next offset.
+ */
+ if ( ! decompress )
+ continue;
+
+ /* Find length of decompressed image */
+ decompressed_len = decompress ( compressed, compressed_len,
+ NULL );
+ if ( decompressed_len < 0 ) {
+ /* May be a false positive signature match */
+ continue;
+ }
+
+ /* Prepend decompressed image to initrd */
+ DBG ( "...extracting embedded bootmgr.exe\n" );
+ padded_len = ( ( decompressed_len + PAGE_SIZE - 1 ) &
+ ~( PAGE_SIZE - 1 ) );
+ initrd -= padded_len;
+ initrd_len += padded_len;
+ decompress ( compressed, compressed_len, initrd );
+
+ /* Add decompressed image */
+ return vdisk_add_file ( "bootmgr.exe", initrd,
+ decompressed_len, read_file );
+ }
+
+ DBG ( "...no embedded bootmgr.exe found\n" );
+ return NULL;
+}
+
+/**
+ * File handler
+ *
+ * @v name File name
+ * @v data File data
+ * @v len Length
+ * @ret rc Return status code
+ */
+static int add_file ( const char *name, void *data, size_t len ) {
+ struct vdisk_file *file;
+
+ /* Store file */
+ file = vdisk_add_file ( name, data, len, read_file );
+
+ /* Check for special-case files */
+ if ( strcasecmp ( name, "bootmgr.exe" ) == 0 ) {
+ DBG ( "...found bootmgr.exe\n" );
+ bootmgr = file;
+ } else if ( strcasecmp ( name, "bootmgr" ) == 0 ) {
+ DBG ( "...found bootmgr\n" );
+ if ( ( ! bootmgr ) &&
+ ( bootmgr = add_bootmgr ( data, len ) ) ) {
+ DBG ( "...extracted bootmgr.exe\n" );
+ }
+ } else if ( strcasecmp ( ( name + strlen ( name ) - 4 ),
+ ".wim" ) == 0 ) {
+ DBG ( "...found WIM file %s\n", name );
+ bootwim = file;
+ }
+
+ return 0;
+}
+
+/**
+ * Relocate data between 1MB and 2GB if possible
+ *
+ * @v data Start of data
+ * @v len Length of data
+ * @ret start Start address
+ */
+static void * relocate_memory_low ( void *data, size_t len ) {
+ struct e820_entry *e820 = NULL;
+ uint64_t end;
+ intptr_t start;
+
+ /* Read system memory map */
+ while ( ( e820 = memmap_next ( e820 ) ) != NULL ) {
+
+ /* Find highest compatible placement within this region */
+ end = ( e820->start + e820->len );
+ start = ( ( end > ADDR_2GB ) ? ADDR_2GB : end );
+ if ( start < len )
+ continue;
+ start -= len;
+ start &= ~( PAGE_SIZE - 1 );
+ if ( start < e820->start )
+ continue;
+ if ( start < ADDR_1MB )
+ continue;
+
+ /* Relocate to this region */
+ memmove ( ( void * ) start, data, len );
+ return ( ( void * ) start );
+ }
+
+ /* Leave at original location */
+ return data;
+}
+
+/**
+ * Main entry point
+ *
+ */
+int main ( void ) {
+ size_t padded_len;
+ void *raw_pe;
+ struct loaded_pe pe;
+ struct paging_state state;
+ uint64_t initrd_phys;
+
+ /* Initialise stack cookie */
+ init_cookie();
+
+ /* Print welcome banner */
+ printf ( "\n\nBooting wim file...... (This may take a few minutes, please wait)\n\n");
+ //printf ( "\n\nwimboot " VERSION " -- Windows Imaging Format "
+ // "bootloader -- https://ipxe.org/wimboot\n\n" );
+
+ /* Process command line */
+ process_cmdline ( cmdline );
+
+ /* Initialise paging */
+ init_paging();
+
+ /* Enable paging */
+ enable_paging ( &state );
+
+ /* Relocate initrd below 2GB if possible, to avoid collisions */
+ DBG ( "Found initrd at [%p,%p)\n", initrd, ( initrd + initrd_len ) );
+ initrd = relocate_memory_low ( initrd, initrd_len );
+ DBG ( "Placing initrd at [%p,%p)\n", initrd, ( initrd + initrd_len ) );
+
+ /* Extract files from initrd */
+ if ( cpio_extract ( initrd, initrd_len, add_file ) != 0 )
+ die ( "FATAL: could not extract initrd files\n" );
+
+ /* Process WIM image */
+ if ( bootwim ) {
+ vdisk_patch_file ( bootwim, patch_wim );
+ if ( ( ! bootmgr ) &&
+ ( bootmgr = wim_add_file ( bootwim, cmdline_index,
+ bootmgr_path,
+ L"bootmgr.exe" ) ) ) {
+ DBG ( "...extracted bootmgr.exe\n" );
+ }
+ wim_add_files ( bootwim, cmdline_index, wim_paths );
+ }
+
+ /* Add INT 13 drive */
+ callback.drive = initialise_int13();
+
+ /* Read bootmgr.exe into memory */
+ if ( ! bootmgr )
+ die ( "FATAL: no bootmgr.exe\n" );
+ if ( bootmgr->read == read_file ) {
+ raw_pe = bootmgr->opaque;
+ } else {
+ padded_len = ( ( bootmgr->len + PAGE_SIZE - 1 ) &
+ ~( PAGE_SIZE -1 ) );
+ raw_pe = ( initrd - padded_len );
+ bootmgr->read ( bootmgr, raw_pe, 0, bootmgr->len );
+ }
+
+ /* Load bootmgr.exe into memory */
+ if ( load_pe ( raw_pe, bootmgr->len, &pe ) != 0 )
+ die ( "FATAL: Could not load bootmgr.exe\n" );
+
+ /* Relocate initrd above 4GB if possible, to free up 32-bit memory */
+ initrd_phys = relocate_memory_high ( initrd, initrd_len );
+ DBG ( "Placing initrd at physical [%#llx,%#llx)\n",
+ initrd_phys, ( initrd_phys + initrd_len ) );
+
+ /* Complete boot application descriptor set */
+ bootapps.bootapp.pe_base = pe.base;
+ bootapps.bootapp.pe_len = pe.len;
+ bootapps.regions[WIMBOOT_REGION].start_page = page_start ( _start );
+ bootapps.regions[WIMBOOT_REGION].num_pages = page_len ( _start, _end );
+ bootapps.regions[PE_REGION].start_page = page_start ( pe.base );
+ bootapps.regions[PE_REGION].num_pages =
+ page_len ( pe.base, ( pe.base + pe.len ) );
+ bootapps.regions[INITRD_REGION].start_page =
+ ( initrd_phys / PAGE_SIZE );
+ bootapps.regions[INITRD_REGION].num_pages =
+ page_len ( initrd, initrd + initrd_len );
+
+ /* Omit initrd region descriptor if located above 4GB */
+ if ( initrd_phys >= ADDR_4GB )
+ bootapps.memory.num_regions--;
+
+ /* Disable paging */
+ disable_paging ( &state );
+
+ /* Jump to PE image */
+ DBG ( "Entering bootmgr.exe with parameters at %p\n", &bootapps );
+ if ( cmdline_pause )
+ pause();
+ pe.entry ( &bootapps.bootapp );
+ die ( "FATAL: bootmgr.exe returned\n" );
+}
--- /dev/null
+/*
+ * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Memory map
+ *
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "wimboot.h"
+#include "memmap.h"
+
+/** Buffer for INT 15,e820 calls */
+static struct e820_entry e820_buf __attribute__ (( section ( ".bss16" ) ));
+
+/** Continuation value for next INT 15,e820 call */
+static uint32_t e820_ebx;
+
+/**
+ * Get system memory map entry
+ *
+ * @v prev Previous system memory map entry, or NULL at start
+ * @v next Next system memory map entry, or NULL at end
+ */
+struct e820_entry * memmap_next ( struct e820_entry *prev ) {
+ struct bootapp_callback_params params;
+
+ /* Reset buffer and continuation value if restarting */
+ if ( ! prev ) {
+ memset ( &e820_buf, 0, sizeof ( e820_buf ) );
+ e820_ebx = 0;
+ } else if ( e820_ebx == 0 ) {
+ /* Reach the end */
+ return NULL;
+ }
+
+ /* Read system memory map */
+ memset ( ¶ms, 0, sizeof ( params ) );
+ do {
+
+ /* Call INT 15,e820 */
+ params.vector.interrupt = 0x15;
+ params.eax = 0xe820;
+ params.ebx = e820_ebx;
+ params.ecx = sizeof ( e820_buf );
+ params.edx = E820_SMAP;
+ params.es = BASE_SEG;
+ params.edi = ( ( ( void * ) &e820_buf ) -
+ ( ( void * ) BASE_ADDRESS ) );
+ call_interrupt ( ¶ms );
+
+ /* Record continuation value */
+ e820_ebx = params.ebx;
+
+ /* Check result */
+ if ( params.eflags & CF ) {
+ DBG ( "INT 15,e820 failed: error %02x\n", params.ah );
+ break;
+ }
+ if ( params.eax != E820_SMAP ) {
+ DBG ( "INT 15,e820 invalid SMAP signature %08x\n",
+ params.eax );
+ break;
+ }
+ DBG2 ( "INT 15,e820 region [%llx,%llx) type %d\n",
+ e820_buf.start, ( e820_buf.start + e820_buf.len ),
+ e820_buf.type );
+
+ /* Skip non-RAM regions */
+ if ( e820_buf.type != E820_TYPE_RAM )
+ continue;
+ if ( params.ecx > offsetof ( typeof ( e820_buf ), attrs ) ) {
+ if ( ! ( e820_buf.attrs & E820_ATTR_ENABLED ) )
+ continue;
+ if ( e820_buf.attrs & E820_ATTR_NONVOLATILE )
+ continue;
+ }
+
+ /* Return this region */
+ return &e820_buf;
+
+ } while ( e820_ebx != 0 );
+
+ return NULL;
+}
--- /dev/null
+#ifndef _MEMMAP_H
+#define _MEMMAP_H
+
+/*
+ * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Memory map
+ *
+ */
+
+#include <stdint.h>
+
+/** Magic value for INT 15,e820 calls */
+#define E820_SMAP 0x534d4150
+
+/** An INT 15,e820 memory map entry */
+struct e820_entry {
+ /** Start of region */
+ uint64_t start;
+ /** Length of region */
+ uint64_t len;
+ /** Type of region */
+ uint32_t type;
+ /** Extended attributes (optional) */
+ uint32_t attrs;
+} __attribute__ (( packed ));
+
+/** Normal RAM */
+#define E820_TYPE_RAM 1
+
+/** Region is enabled (if extended attributes are present) */
+#define E820_ATTR_ENABLED 0x00000001UL
+
+/** Region is non-volatile memory (if extended attributes are present) */
+#define E820_ATTR_NONVOLATILE 0x00000002UL
+
+extern struct e820_entry * memmap_next ( struct e820_entry *prev );
+
+#endif /* _MEMMAP_H */
--- /dev/null
+/*
+ * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Paging
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "wimboot.h"
+#include "memmap.h"
+#include "paging.h"
+
+/** Virtual address used as a 2MB window during relocation */
+#define COPY_WINDOW 0x200000
+
+/** Paging is available */
+int paging;
+
+/** Page directory pointer table */
+static uint64_t pdpt[4] __attribute__ (( aligned ( PAGE_SIZE ) ));
+
+/** Page directories */
+static uint64_t pd[2048] __attribute__ (( aligned ( PAGE_SIZE ) ));
+
+/**
+ * Check that paging can be supported
+ *
+ * @ret supported Paging can be supported on this CPU
+ */
+static int paging_supported ( void ) {
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+
+ /* Get CPU features */
+ __asm__ ( "cpuid"
+ : "=a" ( eax ), "=b" ( ebx ), "=c" ( ecx ), "=d" ( edx )
+ : "0" ( CPUID_FEATURES ) );
+
+ return ( edx & CPUID_FEATURE_EDX_PAE );
+}
+
+/**
+ * Map 2MB page directory entry containing address
+ *
+ * @v vaddr Virtual address
+ * @v paddr Physical address
+ */
+static void map_page ( uint32_t vaddr, uint64_t paddr ) {
+ char *byte = ( ( char * ) ( intptr_t ) vaddr );
+ unsigned int index;
+
+ /* Sanity checks */
+ assert ( ( vaddr & ( PAGE_SIZE_2MB - 1 ) ) == 0 );
+ assert ( ( paddr & ( PAGE_SIZE_2MB - 1 ) ) == 0 );
+
+ /* Populate page directory entry */
+ index = ( vaddr / PAGE_SIZE_2MB );
+ pd[index] = ( paddr | PG_P | PG_RW | PG_US | PG_PS );
+
+ /* Invalidate TLB */
+ __asm__ __volatile__ ( "invlpg %0" : : "m" ( *byte ) );
+}
+
+/**
+ * Initialise paging
+ *
+ */
+void init_paging ( void ) {
+ uint32_t addr;
+ unsigned int i;
+
+ /* Do nothing if paging is disabled */
+ if ( cmdline_linear ) {
+ DBG ( "Paging disabled\n" );
+ return;
+ }
+
+ /* Check for PAE */
+ if ( ! paging_supported() ) {
+ DBG ( "Paging not possible on this CPU\n" );
+ return;
+ }
+
+ /* Initialise page directory entries */
+ addr = 0;
+ do {
+ map_page ( addr, addr );
+ addr += PAGE_SIZE_2MB;
+ } while ( addr );
+
+ /* Initialise page directory pointer table */
+ for ( i = 0 ; i < ( sizeof ( pdpt ) / sizeof ( pdpt[0] ) ) ; i++ ) {
+ addr = ( ( intptr_t ) &pd[ i * PAGE_SIZE / sizeof ( pd[0] ) ] );
+ pdpt[i] = ( addr | PG_P );
+ }
+
+ /* Mark paging as available */
+ paging = 1;
+}
+
+/**
+ * Enable paging
+ *
+ * @v state Saved paging state to fill in
+ */
+void enable_paging ( struct paging_state *state ) {
+ unsigned long cr0;
+ unsigned long cr3;
+ unsigned long cr4;
+
+ /* Do nothing if paging is unavailable */
+ if ( ! paging )
+ return;
+
+ /* Save paging state */
+ __asm__ __volatile__ ( "mov %%cr0, %0\n\t"
+ "mov %%cr3, %1\n\t"
+ "mov %%cr4, %2\n\t"
+ : "=r" ( cr0 ), "=r" ( cr3 ), "=r" ( cr4 ) );
+ state->cr0 = cr0;
+ state->cr3 = cr3;
+ state->cr4 = cr4;
+
+ /* Disable any existing paging */
+ __asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 & ~CR0_PG ) );
+
+ /* Enable PAE */
+ __asm__ __volatile__ ( "mov %0, %%cr4" : : "r" ( cr4 | CR4_PAE ) );
+
+ /* Load page directory pointer table */
+ __asm__ __volatile__ ( "mov %0, %%cr3" : : "r" ( pdpt ) );
+
+ /* Enable paging */
+ __asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 | CR0_PG ) );
+}
+
+/**
+ * Disable paging
+ *
+ * @v state Previously saved paging state
+ */
+void disable_paging ( struct paging_state *state ) {
+ unsigned long cr0 = state->cr0;
+ unsigned long cr3 = state->cr3;
+ unsigned long cr4 = state->cr4;
+
+ /* Do nothing if paging is unavailable */
+ if ( ! paging )
+ return;
+
+ /* Disable paging */
+ __asm__ __volatile__ ( "mov %0, %%cr0" : : "r" ( cr0 & ~CR0_PG ) );
+
+ /* Restore saved paging state */
+ __asm__ __volatile__ ( "mov %2, %%cr4\n\t"
+ "mov %1, %%cr3\n\t"
+ "mov %0, %%cr0\n\t"
+ : : "r" ( cr0 ), "r" ( cr3 ), "r" ( cr4 ) );
+}
+
+/**
+ * Relocate data out of 32-bit address space, if possible
+ *
+ * @v data Start of data
+ * @v len Length of data
+ * @ret start Physical start address
+ */
+uint64_t relocate_memory_high ( void *data, size_t len ) {
+ intptr_t end = ( ( ( intptr_t ) data ) + len );
+ struct e820_entry *e820 = NULL;
+ uint64_t start;
+ uint64_t dest;
+ size_t offset;
+ size_t frag_len;
+
+ /* Do nothing if paging is unavailable */
+ if ( ! paging )
+ return ( ( intptr_t ) data );
+
+ /* Read system memory map */
+ while ( ( e820 = memmap_next ( e820 ) ) != NULL ) {
+
+ /* Find highest compatible placement within this region */
+ start = ( e820->start + e820->len );
+ if ( start < ADDR_4GB )
+ continue;
+ start = ( ( ( start - end ) & ~( PAGE_SIZE_2MB - 1 ) ) + end );
+ start -= len;
+ if ( start < e820->start )
+ continue;
+ if ( start < ADDR_4GB )
+ continue;
+
+ /* Relocate to this region */
+ dest = start;
+ while ( len ) {
+
+ /* Calculate length within this 2MB page */
+ offset = ( ( ( intptr_t ) data ) &
+ ( PAGE_SIZE_2MB - 1 ) );
+ frag_len = ( PAGE_SIZE_2MB - offset );
+ if ( frag_len > len )
+ frag_len = len;
+
+ /* Map copy window to destination */
+ map_page ( COPY_WINDOW,
+ ( dest & ~( PAGE_SIZE_2MB - 1 ) ) );
+
+ /* Copy data through copy window */
+ memcpy ( ( ( ( void * ) COPY_WINDOW ) + offset ),
+ data, frag_len );
+
+ /* Map original page to destination */
+ map_page ( ( ( ( intptr_t ) data ) - offset ),
+ ( dest & ~( PAGE_SIZE_2MB - 1 ) ) );
+
+ /* Move to next 2MB page */
+ data += frag_len;
+ dest += frag_len;
+ len -= frag_len;
+ }
+
+ /* Remap copy window */
+ map_page ( COPY_WINDOW, COPY_WINDOW );
+
+ return start;
+ }
+
+ /* Leave at original location */
+ return ( ( intptr_t ) data );
+}
--- /dev/null
+#ifndef _PAGING_H
+#define _PAGING_H
+
+/*
+ * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Paging
+ *
+ */
+
+#include <stddef.h>
+
+/** Get CPU features */
+#define CPUID_FEATURES 0x00000001
+
+/** CPU supports PAE */
+#define CPUID_FEATURE_EDX_PAE 0x00000040
+
+/* CR0: paging */
+#define CR0_PG 0x80000000
+
+/* CR4: physical address extensions */
+#define CR4_PAE 0x00000020
+
+/* Page: present */
+#define PG_P 0x01
+
+/* Page: read/write */
+#define PG_RW 0x02
+
+/* Page: user/supervisor */
+#define PG_US 0x04
+
+/* Page: page size */
+#define PG_PS 0x80
+
+/** 2MB page size */
+#define PAGE_SIZE_2MB 0x200000
+
+/** 32-bit address space size */
+#define ADDR_4GB 0x100000000ULL
+
+/** Saved paging state */
+struct paging_state {
+ /** Control register 0 */
+ unsigned long cr0;
+ /** Control register 3 */
+ unsigned long cr3;
+ /** Control register 4 */
+ unsigned long cr4;
+};
+
+extern int paging;
+
+extern void init_paging ( void );
+extern void enable_paging ( struct paging_state *state );
+extern void disable_paging ( struct paging_state *state );
+extern uint64_t relocate_memory_high ( void *start, size_t len );
+
+#endif /* _PAGING_H */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Diagnostic pause
+ *
+ */
+
+#include <stdio.h>
+#include "wimboot.h"
+#include "cmdline.h"
+#include "pause.h"
+
+/**
+ * Pause before booting
+ *
+ */
+void pause ( void ) {
+
+ /* Wait for keypress, prompting unless inhibited */
+ if ( cmdline_pause_quiet ) {
+ getchar();
+ } else {
+ printf ( "Press any key to continue booting..." );
+ getchar();
+ printf ( "\n" );
+ }
+}
--- /dev/null
+#ifndef _PAUSE_H
+#define _PAUSE_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Diagnostic pause
+ *
+ */
+
+extern void pause ( void );
+
+#endif /* _PAUSE_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * PE image loader
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "wimboot.h"
+#include "peloader.h"
+
+/**
+ * Load PE image into memory
+ *
+ * @v data PE image
+ * @v len Length of PE image
+ * @v pe Loaded PE structure to fill in
+ * @ret rc Return status code
+ */
+int load_pe ( const void *data, size_t len, struct loaded_pe *pe ) {
+ const struct mz_header *mzhdr;
+ size_t pehdr_offset;
+ const struct pe_header *pehdr;
+ size_t opthdr_offset;
+ const struct pe_optional_header *opthdr;
+ size_t section_offset;
+ const struct coff_section *section;
+ char name[ sizeof ( section->name ) + 1 /* NUL */ ];
+ unsigned int i;
+ void *section_base;
+ size_t filesz;
+ size_t memsz;
+ void *end;
+ void *raw_base;
+
+ DBG2 ( "Loading PE executable...\n" );
+
+ /* Parse PE header */
+ mzhdr = data;
+ if ( mzhdr->magic != MZ_HEADER_MAGIC ) {
+ DBG ( "Bad MZ magic %04x\n", mzhdr->magic );
+ return -1;
+ }
+ pehdr_offset = mzhdr->lfanew;
+ if ( pehdr_offset > len ) {
+ DBG ( "PE header outside file\n" );
+ return -1;
+ }
+ pehdr = ( data + pehdr_offset );
+ if ( pehdr->magic != PE_HEADER_MAGIC ) {
+ DBG ( "Bad PE magic %08x\n", pehdr->magic );
+ return -1;
+ }
+ opthdr_offset = ( pehdr_offset + sizeof ( *pehdr ) );
+ opthdr = ( data + opthdr_offset );
+ pe->base = ( ( void * ) ( intptr_t ) ( opthdr->base ) );
+ section_offset = ( opthdr_offset + pehdr->coff.opthdr_len );
+ section = ( data + section_offset );
+
+ /* Load header into memory */
+ DBG2 ( "...headers to %p+%#x\n", pe->base, opthdr->header_len );
+ memcpy ( pe->base, data, opthdr->header_len );
+ end = ( pe->base + opthdr->header_len );
+
+ /* Load each section into memory */
+ for ( i = 0 ; i < pehdr->coff.num_sections ; i++, section++ ) {
+ memset ( name, 0, sizeof ( name ) );
+ memcpy ( name, section->name, sizeof ( section->name ) );
+ section_base = ( pe->base + section->virtual );
+ filesz = section->raw_len;
+ memsz = section->misc.virtual_len;
+ DBG2 ( "...from %#05x to %p+%#zx/%#zx (%s)\n",
+ section->raw, section_base, filesz, memsz, name );
+ memset ( section_base, 0, memsz );
+ memcpy ( section_base, ( data + section->raw ), filesz );
+ if ( end < ( section_base + memsz ) )
+ end = ( section_base + memsz );
+ }
+ pe->len = ( ( ( end - pe->base ) + opthdr->section_align - 1 )
+ & ~( opthdr->section_align - 1 ) );
+
+ /* Load copy of raw image into memory immediately after loaded
+ * sections. This seems to be used for verification of X.509
+ * signatures.
+ */
+ raw_base = ( pe->base + pe->len );
+ memcpy ( raw_base, data, len );
+ pe->len += len;
+ DBG2 ( "...raw copy to %p+%#zx\n", raw_base, len );
+
+ /* Extract entry point */
+ pe->entry = ( pe->base + opthdr->entry );
+ DBG2 ( "...entry point %p\n", pe->entry );
+
+ return 0;
+}
--- /dev/null
+#ifndef _PELOADER_H
+#define _PELOADER_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * PE image loader
+ *
+ */
+
+#include <stdint.h>
+#include "wimboot.h"
+
+/** DOS MZ header */
+struct mz_header {
+ /** Magic number */
+ uint16_t magic;
+ /** Bytes on last page of file */
+ uint16_t cblp;
+ /** Pages in file */
+ uint16_t cp;
+ /** Relocations */
+ uint16_t crlc;
+ /** Size of header in paragraphs */
+ uint16_t cparhdr;
+ /** Minimum extra paragraphs needed */
+ uint16_t minalloc;
+ /** Maximum extra paragraphs needed */
+ uint16_t maxalloc;
+ /** Initial (relative) SS value */
+ uint16_t ss;
+ /** Initial SP value */
+ uint16_t sp;
+ /** Checksum */
+ uint16_t csum;
+ /** Initial IP value */
+ uint16_t ip;
+ /** Initial (relative) CS value */
+ uint16_t cs;
+ /** File address of relocation table */
+ uint16_t lfarlc;
+ /** Overlay number */
+ uint16_t ovno;
+ /** Reserved words */
+ uint16_t res[4];
+ /** OEM identifier (for oeminfo) */
+ uint16_t oemid;
+ /** OEM information; oemid specific */
+ uint16_t oeminfo;
+ /** Reserved words */
+ uint16_t res2[10];
+ /** File address of new exe header */
+ uint32_t lfanew;
+} __attribute__ (( packed ));
+
+/** MZ header magic */
+#define MZ_HEADER_MAGIC 0x5a4d
+
+/** COFF file header */
+struct coff_header {
+ /** Magic number */
+ uint16_t magic;
+ /** Number of sections */
+ uint16_t num_sections;
+ /** Timestamp (seconds since the Epoch) */
+ uint32_t timestamp;
+ /** Offset to symbol table */
+ uint32_t symtab;
+ /** Number of symbol table entries */
+ uint32_t num_syms;
+ /** Length of optional header */
+ uint16_t opthdr_len;
+ /** Flags */
+ uint16_t flags;
+} __attribute__ (( packed ));
+
+/** COFF section */
+struct coff_section {
+ /** Section name */
+ char name[8];
+ /** Physical address or virtual length */
+ union {
+ /** Physical address */
+ uint32_t physical;
+ /** Virtual length */
+ uint32_t virtual_len;
+ } misc;
+ /** Virtual address */
+ uint32_t virtual;
+ /** Length of raw data */
+ uint32_t raw_len;
+ /** Offset to raw data */
+ uint32_t raw;
+ /** Offset to relocations */
+ uint32_t relocations;
+ /** Offset to line numbers */
+ uint32_t line_numbers;
+ /** Number of relocations */
+ uint16_t num_relocations;
+ /** Number of line numbers */
+ uint16_t num_line_numbers;
+ /** Flags */
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/** PE file header */
+struct pe_header {
+ /** Magic number */
+ uint32_t magic;
+ /** COFF header */
+ struct coff_header coff;
+} __attribute__ (( packed ));
+
+/** PE header magic */
+#define PE_HEADER_MAGIC 0x00004550
+
+/** PE optional header */
+struct pe_optional_header {
+ /** Magic number */
+ uint16_t magic;
+ /** Major linker version */
+ uint8_t linker_major;
+ /** Minor linker version */
+ uint8_t linker_minor;
+ /** Length of code */
+ uint32_t text_len;
+ /** Length of initialised data */
+ uint32_t data_len;
+ /** Length of uninitialised data */
+ uint32_t bss_len;
+ /** Entry point */
+ uint32_t entry;
+ /** Base of code */
+ uint32_t text;
+ /** Base of data */
+ uint32_t data;
+ /** Image base address */
+ uint32_t base;
+ /** Section alignment */
+ uint32_t section_align;
+ /** File alignment */
+ uint32_t file_align;
+ /** Major operating system version */
+ uint16_t os_major;
+ /** Minor operating system version */
+ uint16_t os_minor;
+ /** Major image version */
+ uint16_t image_major;
+ /** Minor image version */
+ uint16_t image_minor;
+ /** Major subsystem version */
+ uint16_t subsystem_major;
+ /** Minor subsystem version */
+ uint16_t subsystem_minor;
+ /** Win32 version */
+ uint32_t win32_version;
+ /** Size of image */
+ uint32_t len;
+ /** Size of headers */
+ uint32_t header_len;
+ /* Plus extra fields that we don't care about */
+} __attribute__ (( packed ));
+
+/** A loaded PE image */
+struct loaded_pe {
+ /** Base address */
+ void *base;
+ /** Length */
+ size_t len;
+ /** Entry point */
+ void ( * entry ) ( struct bootapp_descriptor *bootapp );
+};
+
+extern int load_pe ( const void *data, size_t len, struct loaded_pe *pe );
+
+#endif /* _PELOADER_H */
--- /dev/null
+#ifndef _ROTATE_H
+#define _ROTATE_H
+
+/** @file
+ *
+ * Bit operations
+ */
+
+#include <stdint.h>
+
+static inline __attribute__ (( always_inline )) uint8_t
+rol8 ( uint8_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 8 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint8_t
+ror8 ( uint8_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 8 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint16_t
+rol16 ( uint16_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 16 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint16_t
+ror16 ( uint16_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 16 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint32_t
+rol32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint32_t
+ror32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint64_t
+rol64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint64_t
+ror64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) );
+}
+
+#endif /* _ROTATE_H */
--- /dev/null
+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.*)
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+/**
+ * @file
+ *
+ * SHA-1 algorithm
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <assert.h>
+#include "rotate.h"
+#include "sha1.h"
+
+/** SHA-1 variables */
+struct sha1_variables {
+ /* This layout matches that of struct sha1_digest_data,
+ * allowing for efficient endianness-conversion,
+ */
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+ uint32_t e;
+ uint32_t w[80];
+} __attribute__ (( packed ));
+
+/**
+ * f(a,b,c,d) for steps 0 to 19
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_0_19 ( struct sha1_variables *v ) {
+ return ( ( v->b & v->c ) | ( (~v->b) & v->d ) );
+}
+
+/**
+ * f(a,b,c,d) for steps 20 to 39 and 60 to 79
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables *v ) {
+ return ( v->b ^ v->c ^ v->d );
+}
+
+/**
+ * f(a,b,c,d) for steps 40 to 59
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_40_59 ( struct sha1_variables *v ) {
+ return ( ( v->b & v->c ) | ( v->b & v->d ) | ( v->c & v->d ) );
+}
+
+/** An SHA-1 step function */
+struct sha1_step {
+ /**
+ * Calculate f(a,b,c,d)
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+ uint32_t ( * f ) ( struct sha1_variables *v );
+ /** Constant k */
+ uint32_t k;
+};
+
+/** SHA-1 steps */
+static struct sha1_step sha1_steps[4] = {
+ /** 0 to 19 */
+ { .f = sha1_f_0_19, .k = 0x5a827999 },
+ /** 20 to 39 */
+ { .f = sha1_f_20_39_60_79, .k = 0x6ed9eba1 },
+ /** 40 to 59 */
+ { .f = sha1_f_40_59, .k = 0x8f1bbcdc },
+ /** 60 to 79 */
+ { .f = sha1_f_20_39_60_79, .k = 0xca62c1d6 },
+};
+
+/**
+ * Initialise SHA-1 algorithm
+ *
+ * @v ctx SHA-1 context
+ */
+void sha1_init ( void *ctx ) {
+ struct sha1_context *context = ctx;
+
+ context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x67452301 );
+ context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xefcdab89 );
+ context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x98badcfe );
+ context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0x10325476 );
+ context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0xc3d2e1f0 );
+ context->len = 0;
+}
+
+/**
+ * Calculate SHA-1 digest of accumulated data
+ *
+ * @v context SHA-1 context
+ */
+static void sha1_digest ( struct sha1_context *context ) {
+ union {
+ union sha1_digest_data_dwords ddd;
+ struct sha1_variables v;
+ } u;
+ uint32_t *a = &u.v.a;
+ uint32_t *b = &u.v.b;
+ uint32_t *c = &u.v.c;
+ uint32_t *d = &u.v.d;
+ uint32_t *e = &u.v.e;
+ uint32_t *w = u.v.w;
+ uint32_t f;
+ uint32_t k;
+ uint32_t temp;
+ struct sha1_step *step;
+ unsigned int i;
+
+ /* Convert h[0..4] to host-endian, and initialise a, b, c, d,
+ * e, and w[0..15]
+ */
+ for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
+ sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
+ be32_to_cpus ( &context->ddd.dword[i] );
+ u.ddd.dword[i] = context->ddd.dword[i];
+ }
+
+ /* Initialise w[16..79] */
+ for ( i = 16 ; i < 80 ; i++ )
+ w[i] = rol32 ( ( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16] ), 1 );
+
+ /* Main loop */
+ for ( i = 0 ; i < 80 ; i++ ) {
+ step = &sha1_steps[ i / 20 ];
+ f = step->f ( &u.v );
+ k = step->k;
+ temp = ( rol32 ( *a, 5 ) + f + *e + k + w[i] );
+ *e = *d;
+ *d = *c;
+ *c = rol32 ( *b, 30 );
+ *b = *a;
+ *a = temp;
+ }
+
+ /* Add chunk to hash and convert back to big-endian */
+ for ( i = 0 ; i < 5 ; i++ ) {
+ context->ddd.dd.digest.h[i] =
+ cpu_to_be32 ( context->ddd.dd.digest.h[i] +
+ u.ddd.dd.digest.h[i] );
+ }
+}
+
+/**
+ * Accumulate data with SHA-1 algorithm
+ *
+ * @v ctx SHA-1 context
+ * @v data Data
+ * @v len Length of data
+ */
+void sha1_update ( void *ctx, const void *data, size_t len ) {
+ struct sha1_context *context = ctx;
+ const uint8_t *byte = data;
+ size_t offset;
+
+ /* Accumulate data a byte at a time, performing the digest
+ * whenever we fill the data buffer
+ */
+ while ( len-- ) {
+ offset = ( context->len % sizeof ( context->ddd.dd.data ) );
+ context->ddd.dd.data.byte[offset] = *(byte++);
+ context->len++;
+ if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
+ sha1_digest ( context );
+ }
+}
+
+/**
+ * Generate SHA-1 digest
+ *
+ * @v ctx SHA-1 context
+ * @v out Output buffer
+ */
+void sha1_final ( void *ctx, void *out ) {
+ struct sha1_context *context = ctx;
+ uint64_t len_bits;
+ uint8_t pad;
+
+ /* Record length before pre-processing */
+ len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
+
+ /* Pad with a single "1" bit followed by as many "0" bits as required */
+ pad = 0x80;
+ do {
+ sha1_update ( ctx, &pad, sizeof ( pad ) );
+ pad = 0x00;
+ } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
+ offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
+
+ /* Append length (in bits) */
+ sha1_update ( ctx, &len_bits, sizeof ( len_bits ) );
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+
+ /* Copy out final digest */
+ memcpy ( out, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
--- /dev/null
+#ifndef _SHA1_H
+#define _SHA1_H
+
+/** @file
+ *
+ * SHA-1 algorithm
+ *
+ */
+
+#include <stdint.h>
+
+/** An SHA-1 digest */
+struct sha1_digest {
+ /** Hash output */
+ uint32_t h[5];
+};
+
+/** An SHA-1 data block */
+union sha1_block {
+ /** Raw bytes */
+ uint8_t byte[64];
+ /** Raw dwords */
+ uint32_t dword[16];
+ /** Final block structure */
+ struct {
+ /** Padding */
+ uint8_t pad[56];
+ /** Length in bits */
+ uint64_t len;
+ } final;
+};
+
+/** SHA-1 digest and data block
+ *
+ * The order of fields within this structure is designed to minimise
+ * code size.
+ */
+struct sha1_digest_data {
+ /** Digest of data already processed */
+ struct sha1_digest digest;
+ /** Accumulated data */
+ union sha1_block data;
+} __attribute__ (( packed ));
+
+/** SHA-1 digest and data block */
+union sha1_digest_data_dwords {
+ /** Digest and data block */
+ struct sha1_digest_data dd;
+ /** Raw dwords */
+ uint32_t dword[ sizeof ( struct sha1_digest_data ) /
+ sizeof ( uint32_t ) ];
+};
+
+/** An SHA-1 context */
+struct sha1_context {
+ /** Amount of accumulated data */
+ size_t len;
+ /** Digest and accumulated data */
+ union sha1_digest_data_dwords ddd;
+} __attribute__ (( packed ));
+
+/** SHA-1 context size */
+#define SHA1_CTX_SIZE sizeof ( struct sha1_context )
+
+/** SHA-1 digest size */
+#define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest )
+
+extern void sha1_init ( void *ctx );
+extern void sha1_update ( void *ctx, const void *data, size_t len );
+extern void sha1_final ( void *ctx, void *out );
+
+#endif /* _SHA1_H */
--- /dev/null
+#ifndef _STDARG_H
+#define _STDARG_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard arguments
+ *
+ */
+
+typedef __builtin_va_list va_list;
+#define va_start( ap, last ) __builtin_va_start ( ap, last )
+#define va_arg( ap, type ) __builtin_va_arg ( ap, type )
+#define va_end( ap ) __builtin_va_end ( ap )
+#define va_copy( dest, src ) __builtin_va_copy ( dest, src )
+
+#endif /* _STDARG_H */
--- /dev/null
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard definitions
+ *
+ */
+
+#include <stdint.h>
+
+#define NULL ( ( void * ) 0 )
+
+#define offsetof( type, member ) ( ( size_t ) &( ( type * ) NULL )->member )
+
+#define container_of( ptr, type, member ) ( { \
+ const typeof ( ( ( type * ) NULL )->member ) *__mptr = (ptr); \
+ ( type * ) ( ( void * ) __mptr - offsetof ( type, member ) ); } )
+
+#endif /* _STDDEF_H */
--- /dev/null
+#ifndef _STDINT_H
+#define _STDINT_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard integer types
+ *
+ */
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+typedef unsigned long intptr_t;
+
+typedef __SIZE_TYPE__ size_t;
+typedef signed long ssize_t;
+
+typedef __WCHAR_TYPE__ wchar_t;
+typedef __WINT_TYPE__ wint_t;
+
+#endif /* _STDINT_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard Input/Output
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "bootapp.h"
+#include "wimboot.h"
+#include "efi.h"
+
+/**
+ * Print character to console
+ *
+ * @v character Character to print
+ */
+int putchar ( int character ) {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout;
+ struct bootapp_callback_params params;
+ wchar_t wbuf[2];
+
+ /* Convert LF to CR,LF */
+ if ( character == '\n' )
+ putchar ( '\r' );
+
+ /* Print character to bochs debug port */
+ __asm__ __volatile__ ( "outb %b0, $0xe9"
+ : : "a" ( character ) );
+
+ /* Print character to EFI/BIOS console as applicable */
+ if ( efi_systab ) {
+ conout = efi_systab->ConOut;
+ wbuf[0] = character;
+ wbuf[1] = 0;
+ conout->OutputString ( conout, wbuf );
+ } else {
+ memset ( ¶ms, 0, sizeof ( params ) );
+ params.vector.interrupt = 0x10;
+ params.eax = ( 0x0e00 | character );
+ params.ebx = 0x0007;
+ call_interrupt ( ¶ms );
+ }
+
+ return 0;
+}
+
+/**
+ * Get character from console
+ *
+ * @ret character Character
+ */
+int getchar ( void ) {
+ EFI_BOOT_SERVICES *bs;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin;
+ EFI_INPUT_KEY key;
+ UINTN index;
+ struct bootapp_callback_params params;
+ int character;
+
+ /* Get character */
+ if ( efi_systab ) {
+ bs = efi_systab->BootServices;
+ conin = efi_systab->ConIn;
+ bs->WaitForEvent ( 1, &conin->WaitForKey, &index );
+ conin->ReadKeyStroke ( conin, &key );
+ character = key.UnicodeChar;
+ } else {
+ memset ( ¶ms, 0, sizeof ( params ) );
+ params.vector.interrupt = 0x16;
+ call_interrupt ( ¶ms );
+ character = params.al;
+ }
+
+ return character;
+}
--- /dev/null
+#ifndef _STDIO_H
+#define _STDIO_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard Input/Output
+ *
+ */
+
+#include <stdint.h>
+#include <stdarg.h>
+
+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 */
--- /dev/null
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Standard library
+ *
+ */
+
+extern unsigned long strtoul ( const char *nptr, char **endptr, int base );
+
+#endif /* _STDLIB_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * String functions
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#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 );
+}
--- /dev/null
+#ifndef _STRING_H
+#define _STRING_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * String operations
+ *
+ */
+
+#include <stdint.h>
+
+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 */
--- /dev/null
+#ifndef _STRINGS_H
+#define _STRINGS_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * String operations
+ *
+ */
+
+extern int strcasecmp ( const char *str1, const char *str2 );
+
+#endif /* _STRINGS_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Virtual disk
+ *
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#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 );
+}
--- /dev/null
+#ifndef _VDISK_H
+#define _VDISK_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Virtual disk emulation
+ *
+ */
+
+#include <stdint.h>
+
+/** 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 */
--- /dev/null
+/*
+ * Quick and dirty wrapper around iPXE's unmodified vsprintf.c
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "wimboot.h"
+
+#define FILE_LICENCE(x)
+
+#include "ipxe/vsprintf.c"
--- /dev/null
+#ifndef _WCHAR_H
+#define _WCHAR_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Wide characters
+ *
+ */
+
+#include <stdint.h>
+
+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 */
--- /dev/null
+#ifndef _WCTYPE_H
+#define _WCTYPE_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * 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 <ctype.h>
+
+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 */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * WIM images
+ *
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <assert.h>
+#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;
+ }
+}
--- /dev/null
+#ifndef _WIM_H
+#define _WIM_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * 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 <stdint.h>
+
+/** 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 */
--- /dev/null
+#ifndef _WIMBOOT_H
+#define _WIMBOOT_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * 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 <stdint.h>
+#include <bootapp.h>
+#include <cmdline.h>
+
+/** 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 */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * WIM virtual files
+ *
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <wchar.h>
+#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 );
+ }
+}
--- /dev/null
+#ifndef _WIMFILE_H
+#define _WIMFILE_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * WIM virtual files
+ *
+ */
+
+#include <wchar.h>
+
+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 */
--- /dev/null
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * WIM dynamic patching
+ *
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#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 ) );
+ }
+ }
+}
--- /dev/null
+#ifndef _WIMPATCH_H
+#define _WIMPATCH_H
+
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * WIM dynamic patching
+ *
+ */
+
+#include <stdint.h>
+
+struct vdisk_file;
+
+extern void patch_wim ( struct vdisk_file *file, void *data, size_t offset,
+ size_t len );
+
+#endif /* _WIMPATCH_H */
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Xpress Compression Algorithm (MS-XCA) decompression
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#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;
+}
--- /dev/null
+#ifndef _XCA_H
+#define _XCA_H
+
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * @file
+ *
+ * Xpress Compression Algorithm (MS-XCA) decompression
+ *
+ */
+
+#include <stdint.h>
+#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 */