--- /dev/null
+#
+# Make.common
+# Common make rules for building with gnu-efi
+#
+
+EFIINC = /usr/include/efi
+GNUEFILIB = /usr/lib
+EFILIB = /usr/lib
+EFICRT0 = /usr/lib
+
+HOSTARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
+ARCH := $(HOSTARCH)
+OS = $(shell uname -s)
+CPPFLAGS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -DCONFIG_$(ARCH)
+
+OPTIMFLAGS = -O2 -fno-strict-aliasing
+DEBUGFLAGS = -Wall
+CFLAGS = $(ARCH3264) $(OPTIMFLAGS) -fpic -fshort-wchar $(DEBUGFLAGS)
+ASFLAGS = $(ARCH3264)
+LDFLAGS = -nostdlib -znocombreloc
+
+prefix = /usr/bin/
+CC = $(prefix)gcc
+AS = $(prefix)as
+LD = $(prefix)ld
+AR = $(prefix)ar
+RANLIB = $(prefix)ranlib
+OBJCOPY = $(prefix)objcopy
+
+ifeq ($(ARCH),ia64)
+ # EFI specs allows only lower floating point partition to be used
+ CFLAGS += -frename-registers -mfixed-range=f32-f127
+endif
+
+ifeq ($(ARCH),x86_64)
+ CFLAGS += -DEFI_FUNCTION_WRAPPER
+ CPPFLAGS += -DEFIX64
+
+ ifeq ($(HOSTARCH),ia32)
+ ARCH3264 = -m64
+
+ GNUEFILIB := $(GNUEFILIB)64
+ EFILIB := $(EFILIB)64
+ EFICRT0 := $(EFICRT0)64
+ endif
+endif
+
+ifeq ($(ARCH),ia32)
+ CPPFLAGS += -DEFI32
+
+ ifeq ($(HOSTARCH),x86_64)
+ ARCH3264 = -m32
+
+ GNUEFILIB := $(GNUEFILIB)32
+ EFILIB := $(EFILIB)32
+ EFICRT0 := $(EFICRT0)32
+ endif
+endif
+
+
+CRTOBJS = $(EFICRT0)/crt0-efi-$(ARCH).o
+
+ifneq (,$(findstring FreeBSD,$(OS)))
+ ifeq ($(ARCH),x86_64)
+ LDSCRIPT = $(EFICRT0)/elf_$(ARCH)_fbsd_efi.lds
+ else
+ LDSCRIPT = $(EFICRT0)/elf_$(ARCH)_efi.lds
+ endif
+else
+ LDSCRIPT = $(EFICRT0)/elf_$(ARCH)_efi.lds
+endif
+
+LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L$(EFILIB) -L$(GNUEFILIB) $(CRTOBJS)
+LIBS = -lefi -lgnuefi $(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
+FORMAT = efi-app-$(ARCH)
+
+
+# general rules
+
+%.o: %.c
+ $(CC) $(LOCAL_CPPFLAGS) $(CPPFLAGS) $(LOCAL_CFLAGS) $(CFLAGS) -c $< -o $@
+
+# rules for EFI applications
+
+ifneq (,$(filter %.efi,$(TARGET)))
+
+SHLIB_TARGET = $(subst .efi,.so,$(TARGET))
+
+$(SHLIB_TARGET): $(OBJS)
+ $(LD) $(LOCAL_LDFLAGS) $(LDFLAGS) $(OBJS) -o $@ $(LOCAL_LIBS) $(LIBS)
+
+$(TARGET): $(SHLIB_TARGET)
+ $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
+ -j .rela -j .reloc --target=$(FORMAT) $< $@
+
+endif
+
+# rules for libraries
+
+ifneq (,$(filter %.a,$(TARGET)))
+
+$(TARGET): $(OBJS)
+ $(AR) cq $@ $(OBJS)
+
+endif
+
+# utility rules
+
+clean:
+ rm -f $(TARGET) *~ *.so $(OBJS)
+
+# EOF
--- /dev/null
+static const UINT8 egemb_arrow_left_data[2407] = {
+ 0xff, 0xff, 0xdc, 0xff, 0x02, 0x00, 0x13, 0x21, 0xa8, 0xff, 0x80, 0x00,
+ 0x02, 0x5e, 0x74, 0x00, 0xa6, 0xff, 0x80, 0x00, 0x03, 0x43, 0xb2, 0x30,
+ 0x00, 0xa5, 0xff, 0x80, 0x00, 0x04, 0x62, 0x9f, 0x8a, 0x00, 0x00, 0xa4,
+ 0xff, 0x08, 0x00, 0x00, 0x09, 0x7a, 0x96, 0x91, 0x56, 0x00, 0x00, 0xa2,
+ 0xff, 0x80, 0x00, 0x07, 0x1d, 0x85, 0x8c, 0x8b, 0x89, 0x53, 0x00, 0x00,
+ 0xa1, 0xff, 0x80, 0x00, 0x08, 0x34, 0x87, 0x85, 0x84, 0x82, 0x81, 0x50,
+ 0x00, 0x00, 0xa0, 0xff, 0x80, 0x00, 0x09, 0x4c, 0x84, 0x7f, 0x7d, 0x7c,
+ 0x7a, 0x79, 0x4d, 0x00, 0x00, 0x9f, 0xff, 0x0d, 0x00, 0x00, 0x07, 0x60,
+ 0x7c, 0x79, 0x76, 0x75, 0x73, 0x72, 0x70, 0x49, 0x00, 0x00, 0x9d, 0xff,
+ 0x80, 0x00, 0x0c, 0x16, 0x69, 0x73, 0x71, 0x70, 0x6e, 0x6d, 0x6b, 0x6a,
+ 0x68, 0x46, 0x00, 0x00, 0x9c, 0xff, 0x80, 0x00, 0x0d, 0x26, 0x6c, 0x6d,
+ 0x6a, 0x69, 0x67, 0x66, 0x64, 0x63, 0x61, 0x60, 0x42, 0x00, 0x00, 0x9b,
+ 0xff, 0x80, 0x00, 0x0e, 0x38, 0x69, 0x66, 0x64, 0x62, 0x61, 0x5f, 0x5e,
+ 0x5c, 0x5b, 0x59, 0x58, 0x3f, 0x00, 0x00, 0x9a, 0xff, 0x12, 0x00, 0x00,
+ 0x05, 0x47, 0x62, 0x5e, 0x5d, 0x5b, 0x5a, 0x58, 0x57, 0x55, 0x54, 0x52,
+ 0x51, 0x4f, 0x3d, 0x00, 0x00, 0x98, 0xff, 0x80, 0x00, 0x11, 0x0e, 0x4d,
+ 0x5a, 0x58, 0x56, 0x55, 0x53, 0x52, 0x50, 0x4f, 0x4d, 0x4c, 0x4a, 0x49,
+ 0x47, 0x3a, 0x00, 0x00, 0x97, 0xff, 0x80, 0x00, 0x12, 0x1a, 0x50, 0x53,
+ 0x51, 0x4f, 0x4e, 0x4c, 0x4b, 0x49, 0x48, 0x46, 0x45, 0x43, 0x42, 0x40,
+ 0x3f, 0x38, 0x00, 0x00, 0x96, 0xff, 0x80, 0x00, 0x13, 0x25, 0x4d, 0x4c,
+ 0x4a, 0x49, 0x47, 0x46, 0x44, 0x43, 0x41, 0x40, 0x3e, 0x3d, 0x3b, 0x3a,
+ 0x38, 0x37, 0x36, 0x00, 0x00, 0x95, 0xff, 0x17, 0x00, 0x00, 0x05, 0x2f,
+ 0x47, 0x45, 0x43, 0x42, 0x40, 0x3f, 0x3d, 0x3c, 0x3a, 0x39, 0x37, 0x36,
+ 0x34, 0x33, 0x31, 0x30, 0x2e, 0x34, 0x00, 0x00, 0x93, 0xff, 0x80, 0x00,
+ 0x16, 0x0a, 0x39, 0x40, 0x3f, 0x3d, 0x3c, 0x3a, 0x38, 0x37, 0x35, 0x34,
+ 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b, 0x29, 0x27, 0x25, 0x32, 0x00, 0x00,
+ 0x92, 0xff, 0x1a, 0x25, 0x08, 0x05, 0x14, 0x39, 0x3a, 0x38, 0x37, 0x34,
+ 0x33, 0x31, 0x30, 0x2e, 0x2d, 0x2b, 0x2a, 0x28, 0x27, 0x25, 0x24, 0x22,
+ 0x20, 0x1f, 0x1d, 0x30, 0x00, 0x00, 0x92, 0xff, 0x10, 0x1d, 0x37, 0x48,
+ 0x39, 0x32, 0x31, 0x31, 0x30, 0x2e, 0x2d, 0x2b, 0x2b, 0x2a, 0x2d, 0x2e,
+ 0x32, 0x31, 0x84, 0x30, 0x02, 0x33, 0x00, 0x00, 0x92, 0xff, 0x0f, 0x3a,
+ 0x5c, 0x5a, 0x0f, 0x00, 0x00, 0x02, 0x04, 0x05, 0x08, 0x0b, 0x0e, 0x0c,
+ 0x09, 0x05, 0x01, 0x85, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x92, 0xff, 0x04,
+ 0x94, 0x33, 0x17, 0x0b, 0x05, 0x90, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x93,
+ 0xff, 0x04, 0xab, 0x02, 0x00, 0x06, 0x0a, 0x8f, 0x00, 0x02, 0x0d, 0x00,
+ 0x00, 0x95, 0xff, 0x03, 0x00, 0x00, 0x05, 0x10, 0x8e, 0x00, 0x02, 0x0f,
+ 0x00, 0x00, 0x96, 0xff, 0x04, 0x00, 0x00, 0x01, 0x00, 0x05, 0x8c, 0x00,
+ 0x02, 0x11, 0x00, 0x00, 0x97, 0xff, 0x80, 0x00, 0x01, 0x0f, 0x09, 0x8b,
+ 0x00, 0x02, 0x12, 0x00, 0x00, 0x98, 0xff, 0x80, 0x00, 0x01, 0x0b, 0x10,
+ 0x8a, 0x00, 0x02, 0x14, 0x00, 0x00, 0x9a, 0xff, 0x03, 0x00, 0x00, 0x07,
+ 0x18, 0x89, 0x00, 0x02, 0x16, 0x00, 0x00, 0x9b, 0xff, 0x04, 0x00, 0x00,
+ 0x01, 0x00, 0x07, 0x87, 0x00, 0x02, 0x17, 0x00, 0x00, 0x9c, 0xff, 0x80,
+ 0x00, 0x01, 0x15, 0x0d, 0x86, 0x00, 0x02, 0x19, 0x00, 0x00, 0x9d, 0xff,
+ 0x80, 0x00, 0x01, 0x0e, 0x17, 0x85, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x9f,
+ 0xff, 0x04, 0x00, 0x00, 0x09, 0x20, 0x01, 0x83, 0x00, 0x02, 0x1d, 0x00,
+ 0x00, 0xa0, 0xff, 0x04, 0x00, 0x00, 0x01, 0x22, 0x09, 0x82, 0x00, 0x02,
+ 0x1e, 0x00, 0x00, 0xa1, 0xff, 0x80, 0x00, 0x01, 0x1b, 0x12, 0x81, 0x00,
+ 0x02, 0x20, 0x00, 0x00, 0xa2, 0xff, 0x80, 0x00, 0x01, 0x13, 0x1d, 0x80,
+ 0x00, 0x02, 0x22, 0x00, 0x00, 0xa4, 0xff, 0x08, 0x00, 0x00, 0x0b, 0x29,
+ 0x01, 0x00, 0x24, 0x00, 0x00, 0xa5, 0xff, 0x07, 0x00, 0x00, 0x02, 0x2b,
+ 0x0b, 0x3c, 0x00, 0x00, 0xa6, 0xff, 0x80, 0x00, 0x03, 0x23, 0x66, 0x0b,
+ 0x00, 0xa7, 0xff, 0x80, 0x00, 0x02, 0x39, 0x24, 0x00, 0xa9, 0xff, 0x02,
+ 0x00, 0x11, 0x0b, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xdc, 0xff, 0x02,
+ 0x4d, 0x59, 0x64, 0xa8, 0xff, 0x05, 0x80, 0x4b, 0x4d, 0x8f, 0x9e, 0x49,
+ 0xa6, 0xff, 0x06, 0x4f, 0x4c, 0x4d, 0x7d, 0xd2, 0x6f, 0x47, 0xa5, 0xff,
+ 0x07, 0x49, 0x4d, 0x4d, 0x96, 0xd6, 0xb8, 0x4d, 0x4e, 0xa4, 0xff, 0x08,
+ 0x4d, 0x4d, 0x53, 0xac, 0xd1, 0xce, 0x91, 0x4d, 0x4e, 0xa2, 0xff, 0x0a,
+ 0x80, 0x4b, 0x4d, 0x62, 0xb9, 0xca, 0xc9, 0xc8, 0x91, 0x4d, 0x4e, 0xa1,
+ 0xff, 0x0b, 0x4f, 0x4c, 0x4d, 0x74, 0xc0, 0xc5, 0xc4, 0xc3, 0xc1, 0x8f,
+ 0x4d, 0x4e, 0xa0, 0xff, 0x0c, 0x49, 0x4d, 0x4d, 0x8a, 0xc1, 0xc1, 0xbf,
+ 0xbe, 0xbd, 0xbc, 0x8f, 0x50, 0x4e, 0x9f, 0xff, 0x0d, 0x4d, 0x4d, 0x53,
+ 0x9d, 0xbe, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0x8e, 0x54, 0x4e, 0x9d,
+ 0xff, 0x05, 0x80, 0x4b, 0x4d, 0x5e, 0xa8, 0xb8, 0x80, 0xb6, 0x06, 0xb5,
+ 0xb4, 0xb3, 0xb3, 0x8f, 0x59, 0x4e, 0x9c, 0xff, 0x05, 0x4f, 0x4c, 0x4d,
+ 0x6d, 0xad, 0xb3, 0x81, 0xb2, 0x06, 0xb1, 0xb0, 0xb0, 0xaf, 0x90, 0x5e,
+ 0x4e, 0x9b, 0xff, 0x03, 0x4f, 0x4f, 0x51, 0x7f, 0x82, 0xad, 0x00, 0xae,
+ 0x80, 0xad, 0x04, 0xac, 0xac, 0x91, 0x62, 0x4e, 0x9a, 0xff, 0x0a, 0x50,
+ 0x53, 0x58, 0x8d, 0xa8, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0x81, 0xaa,
+ 0x03, 0xa9, 0x94, 0x67, 0x4e, 0x98, 0xff, 0x0c, 0x80, 0x51, 0x55, 0x62,
+ 0x93, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0x81, 0xa8, 0x03,
+ 0xa7, 0x96, 0x6c, 0x4e, 0x97, 0xff, 0x15, 0x4f, 0x56, 0x59, 0x6c, 0x95,
+ 0x9b, 0x9c, 0x9e, 0x9f, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7,
+ 0xa6, 0xa6, 0x98, 0x6f, 0x4e, 0x96, 0xff, 0x0f, 0x4d, 0x58, 0x5b, 0x71,
+ 0x93, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa1, 0xa2, 0xa3, 0xa4,
+ 0x81, 0xa5, 0x02, 0x99, 0x72, 0x4e, 0x95, 0xff, 0x17, 0x55, 0x5a, 0x61,
+ 0x77, 0x8b, 0x8d, 0x8e, 0x91, 0x94, 0x96, 0x99, 0x9b, 0x9c, 0x9f, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa4, 0x9c, 0x75, 0x4e, 0x93, 0xff, 0x13,
+ 0x80, 0x56, 0x5f, 0x64, 0x7b, 0x82, 0x85, 0x88, 0x8b, 0x8d, 0x8f, 0x93,
+ 0x96, 0x98, 0x9b, 0x9d, 0x9f, 0xa1, 0xa3, 0xa4, 0x80, 0xa5, 0x02, 0x9f,
+ 0x77, 0x4e, 0x92, 0xff, 0x1a, 0x6d, 0x60, 0x63, 0x68, 0x77, 0x79, 0x7c,
+ 0x7f, 0x82, 0x85, 0x88, 0x8c, 0x8f, 0x92, 0x96, 0x99, 0x9c, 0x9e, 0xa0,
+ 0xa2, 0xa4, 0xa4, 0xa5, 0xa5, 0xa1, 0x7a, 0x4e, 0x92, 0xff, 0x1a, 0x6a,
+ 0x85, 0x86, 0x6f, 0x6e, 0x73, 0x78, 0x7a, 0x7f, 0x82, 0x86, 0x89, 0x8e,
+ 0x94, 0x99, 0x9e, 0xa2, 0xa5, 0xa8, 0xab, 0xac, 0xaf, 0xaf, 0xb1, 0xa5,
+ 0x7d, 0x4e, 0x92, 0xff, 0x1a, 0x80, 0x9d, 0x90, 0x43, 0x3d, 0x44, 0x4d,
+ 0x54, 0x5d, 0x65, 0x6e, 0x76, 0x7a, 0x7e, 0x82, 0x85, 0x8b, 0x90, 0x95,
+ 0x99, 0x9d, 0xa0, 0xa2, 0xa3, 0x97, 0x7f, 0x4e, 0x92, 0xff, 0x1a, 0xb7,
+ 0x82, 0x76, 0x68, 0x48, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69, 0x70, 0x77,
+ 0x7d, 0x83, 0x89, 0x8f, 0x95, 0x9a, 0x9f, 0xa3, 0xa6, 0xa9, 0xaa, 0x9c,
+ 0x80, 0x4e, 0x93, 0xff, 0x19, 0xd5, 0x61, 0x6b, 0x6d, 0x5b, 0x4f, 0x56,
+ 0x5d, 0x65, 0x6c, 0x72, 0x79, 0x80, 0x87, 0x8d, 0x93, 0x99, 0x9f, 0xa4,
+ 0xa9, 0xac, 0xaf, 0xb1, 0xa1, 0x84, 0x4e, 0x95, 0xff, 0x17, 0x61, 0x6e,
+ 0x72, 0x6a, 0x58, 0x5f, 0x66, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x90, 0x97,
+ 0x9d, 0xa3, 0xa9, 0xae, 0xb2, 0xb6, 0xb8, 0xa5, 0x84, 0x4e, 0x96, 0xff,
+ 0x16, 0x5c, 0x6e, 0x74, 0x6a, 0x65, 0x68, 0x6f, 0x76, 0x7e, 0x85, 0x8c,
+ 0x93, 0x9a, 0xa1, 0xa7, 0xad, 0xb3, 0xb8, 0xbc, 0xbf, 0xaa, 0x86, 0x4e,
+ 0x97, 0xff, 0x15, 0x59, 0x6d, 0x76, 0x7d, 0x72, 0x70, 0x78, 0x7f, 0x86,
+ 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1, 0xb7, 0xbd, 0xc2, 0xc6, 0xaf, 0x87,
+ 0x4e, 0x98, 0xff, 0x14, 0x80, 0x6c, 0x78, 0x7f, 0x7d, 0x78, 0x80, 0x87,
+ 0x8f, 0x96, 0x9e, 0xa5, 0xac, 0xb3, 0xbb, 0xc1, 0xc7, 0xcc, 0xb3, 0x8a,
+ 0x4e, 0x9a, 0xff, 0x12, 0x68, 0x79, 0x7f, 0x89, 0x80, 0x87, 0x8f, 0x96,
+ 0x9e, 0xa6, 0xad, 0xb5, 0xbc, 0xc4, 0xcb, 0xd1, 0xb7, 0x89, 0x4e, 0x9b,
+ 0xff, 0x11, 0x63, 0x7a, 0x7e, 0x8f, 0x8b, 0x8e, 0x96, 0x9e, 0xa5, 0xad,
+ 0xb5, 0xbc, 0xc4, 0xcc, 0xd3, 0xbb, 0x8a, 0x4e, 0x9c, 0xff, 0x10, 0x59,
+ 0x78, 0x7f, 0x8e, 0x93, 0x94, 0x9c, 0xa4, 0xab, 0xb3, 0xba, 0xc2, 0xc9,
+ 0xd0, 0xb8, 0x8a, 0x4e, 0x9d, 0xff, 0x0f, 0x80, 0x74, 0x80, 0x8c, 0x9a,
+ 0x99, 0xa1, 0xa8, 0xaf, 0xb6, 0xbd, 0xc3, 0xc8, 0xb5, 0x8b, 0x4e, 0x9f,
+ 0xff, 0x0d, 0x72, 0x82, 0x89, 0xa0, 0x9d, 0xa4, 0xab, 0xb1, 0xb7, 0xbc,
+ 0xc0, 0xb2, 0x8c, 0x4e, 0xa0, 0xff, 0x0c, 0x6b, 0x82, 0x86, 0x9f, 0xa2,
+ 0xa5, 0xab, 0xb0, 0xb4, 0xb7, 0xae, 0x8c, 0x4e, 0xa1, 0xff, 0x0b, 0x59,
+ 0x81, 0x85, 0x98, 0xa4, 0xa4, 0xa8, 0xac, 0xae, 0xac, 0x8b, 0x4e, 0xa2,
+ 0xff, 0x0a, 0x80, 0x7e, 0x87, 0x92, 0xa5, 0xa0, 0xa3, 0xa5, 0xa8, 0x8b,
+ 0x4e, 0xa4, 0xff, 0x08, 0x76, 0x87, 0x8d, 0xa5, 0x9a, 0x9c, 0xa5, 0x8b,
+ 0x4e, 0xa5, 0xff, 0x07, 0x70, 0x88, 0x88, 0xa3, 0x98, 0xab, 0x8a, 0x4e,
+ 0xa6, 0xff, 0x06, 0x63, 0x89, 0x86, 0x9b, 0xbd, 0x8e, 0x47, 0xa7, 0xff,
+ 0x05, 0x80, 0x84, 0x87, 0xa4, 0x9e, 0x66, 0xa9, 0xff, 0x02, 0x79, 0x8c,
+ 0x80, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xdc, 0xff, 0x02, 0x00, 0x13,
+ 0x21, 0xa8, 0xff, 0x80, 0x00, 0x02, 0x5e, 0x74, 0x00, 0xa6, 0xff, 0x80,
+ 0x00, 0x03, 0x43, 0xb2, 0x30, 0x00, 0xa5, 0xff, 0x80, 0x00, 0x04, 0x62,
+ 0x9f, 0x8a, 0x00, 0x00, 0xa4, 0xff, 0x08, 0x00, 0x00, 0x09, 0x7a, 0x96,
+ 0x91, 0x56, 0x00, 0x00, 0xa2, 0xff, 0x80, 0x00, 0x07, 0x1d, 0x85, 0x8c,
+ 0x8b, 0x89, 0x53, 0x00, 0x00, 0xa1, 0xff, 0x80, 0x00, 0x08, 0x34, 0x87,
+ 0x85, 0x84, 0x82, 0x81, 0x50, 0x00, 0x00, 0xa0, 0xff, 0x80, 0x00, 0x09,
+ 0x4c, 0x84, 0x7f, 0x7d, 0x7c, 0x7a, 0x79, 0x4d, 0x00, 0x00, 0x9f, 0xff,
+ 0x0d, 0x00, 0x00, 0x07, 0x60, 0x7c, 0x79, 0x76, 0x75, 0x73, 0x72, 0x70,
+ 0x49, 0x00, 0x00, 0x9d, 0xff, 0x80, 0x00, 0x0c, 0x16, 0x69, 0x73, 0x71,
+ 0x70, 0x6e, 0x6d, 0x6b, 0x6a, 0x68, 0x46, 0x00, 0x00, 0x9c, 0xff, 0x80,
+ 0x00, 0x0d, 0x26, 0x6c, 0x6d, 0x6a, 0x69, 0x67, 0x66, 0x64, 0x63, 0x61,
+ 0x60, 0x42, 0x00, 0x00, 0x9b, 0xff, 0x80, 0x00, 0x0e, 0x38, 0x69, 0x66,
+ 0x64, 0x62, 0x61, 0x5f, 0x5e, 0x5c, 0x5b, 0x59, 0x58, 0x3f, 0x00, 0x00,
+ 0x9a, 0xff, 0x12, 0x00, 0x00, 0x05, 0x47, 0x62, 0x5e, 0x5d, 0x5b, 0x5a,
+ 0x58, 0x57, 0x55, 0x54, 0x52, 0x51, 0x4f, 0x3d, 0x00, 0x00, 0x98, 0xff,
+ 0x80, 0x00, 0x11, 0x0e, 0x4d, 0x5a, 0x58, 0x56, 0x55, 0x53, 0x52, 0x50,
+ 0x4f, 0x4d, 0x4c, 0x4a, 0x49, 0x47, 0x3a, 0x00, 0x00, 0x97, 0xff, 0x15,
+ 0x00, 0x00, 0x01, 0x1b, 0x50, 0x53, 0x51, 0x4f, 0x4e, 0x4c, 0x4b, 0x49,
+ 0x48, 0x46, 0x45, 0x43, 0x42, 0x40, 0x3f, 0x38, 0x01, 0x00, 0x96, 0xff,
+ 0x16, 0x00, 0x01, 0x01, 0x26, 0x4d, 0x4c, 0x4a, 0x49, 0x47, 0x46, 0x44,
+ 0x43, 0x41, 0x40, 0x3e, 0x3d, 0x3b, 0x3a, 0x38, 0x37, 0x36, 0x01, 0x00,
+ 0x95, 0xff, 0x17, 0x00, 0x01, 0x06, 0x2f, 0x47, 0x45, 0x43, 0x42, 0x40,
+ 0x3f, 0x3d, 0x3c, 0x3a, 0x39, 0x37, 0x36, 0x34, 0x33, 0x31, 0x30, 0x2e,
+ 0x34, 0x01, 0x00, 0x93, 0xff, 0x19, 0x00, 0x02, 0x01, 0x0b, 0x39, 0x40,
+ 0x3f, 0x3d, 0x3c, 0x3a, 0x38, 0x37, 0x35, 0x34, 0x32, 0x31, 0x2f, 0x2e,
+ 0x2c, 0x2b, 0x29, 0x27, 0x25, 0x32, 0x01, 0x00, 0x92, 0xff, 0x1a, 0x25,
+ 0x09, 0x06, 0x15, 0x39, 0x3a, 0x38, 0x37, 0x34, 0x33, 0x31, 0x30, 0x2e,
+ 0x2d, 0x2b, 0x2a, 0x28, 0x27, 0x25, 0x24, 0x22, 0x20, 0x1f, 0x1d, 0x30,
+ 0x01, 0x00, 0x92, 0xff, 0x10, 0x1f, 0x39, 0x49, 0x39, 0x32, 0x31, 0x31,
+ 0x30, 0x2e, 0x2d, 0x2b, 0x2b, 0x2a, 0x2d, 0x2e, 0x32, 0x31, 0x84, 0x30,
+ 0x02, 0x34, 0x02, 0x00, 0x92, 0xff, 0x0f, 0x3c, 0x5d, 0x5b, 0x0f, 0x00,
+ 0x00, 0x02, 0x04, 0x05, 0x08, 0x0b, 0x0e, 0x0c, 0x09, 0x05, 0x01, 0x85,
+ 0x00, 0x02, 0x0b, 0x02, 0x00, 0x92, 0xff, 0x04, 0x94, 0x34, 0x19, 0x0d,
+ 0x05, 0x90, 0x00, 0x02, 0x0d, 0x02, 0x00, 0x93, 0xff, 0x04, 0xab, 0x04,
+ 0x02, 0x08, 0x0a, 0x8f, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x95, 0xff, 0x03,
+ 0x03, 0x02, 0x08, 0x11, 0x8e, 0x00, 0x02, 0x10, 0x03, 0x00, 0x96, 0xff,
+ 0x04, 0x00, 0x02, 0x04, 0x02, 0x05, 0x8c, 0x00, 0x02, 0x12, 0x03, 0x00,
+ 0x97, 0xff, 0x04, 0x00, 0x03, 0x03, 0x11, 0x09, 0x8b, 0x00, 0x02, 0x13,
+ 0x03, 0x00, 0x98, 0xff, 0x04, 0x00, 0x02, 0x03, 0x0e, 0x11, 0x8a, 0x00,
+ 0x02, 0x15, 0x03, 0x00, 0x9a, 0xff, 0x03, 0x02, 0x03, 0x0b, 0x1a, 0x89,
+ 0x00, 0x02, 0x18, 0x04, 0x00, 0x9b, 0xff, 0x04, 0x05, 0x03, 0x05, 0x02,
+ 0x07, 0x87, 0x00, 0x02, 0x19, 0x04, 0x00, 0x9c, 0xff, 0x04, 0x00, 0x03,
+ 0x04, 0x18, 0x0d, 0x86, 0x00, 0x02, 0x1b, 0x04, 0x00, 0x9d, 0xff, 0x04,
+ 0x00, 0x03, 0x04, 0x12, 0x18, 0x85, 0x00, 0x02, 0x1d, 0x04, 0x00, 0x9f,
+ 0xff, 0x04, 0x02, 0x04, 0x0d, 0x22, 0x01, 0x83, 0x00, 0x02, 0x1f, 0x04,
+ 0x00, 0xa0, 0xff, 0x04, 0x05, 0x03, 0x06, 0x25, 0x09, 0x82, 0x00, 0x02,
+ 0x20, 0x05, 0x00, 0xa1, 0xff, 0x04, 0x00, 0x04, 0x05, 0x1e, 0x12, 0x81,
+ 0x00, 0x02, 0x22, 0x05, 0x00, 0xa2, 0xff, 0x04, 0x00, 0x03, 0x05, 0x18,
+ 0x1e, 0x80, 0x00, 0x02, 0x24, 0x05, 0x00, 0xa4, 0xff, 0x08, 0x02, 0x05,
+ 0x10, 0x2b, 0x01, 0x00, 0x26, 0x05, 0x00, 0xa5, 0xff, 0x07, 0x05, 0x04,
+ 0x08, 0x2e, 0x0b, 0x32, 0x06, 0x00, 0xa6, 0xff, 0x06, 0x00, 0x04, 0x06,
+ 0x27, 0x4d, 0x0c, 0x00, 0xa7, 0xff, 0x05, 0x00, 0x03, 0x06, 0x24, 0x17,
+ 0x00, 0xa9, 0xff, 0x02, 0x03, 0x0e, 0x08, 0xff, 0xff, 0xc7, 0xff, 0xff,
+ 0x00, 0xdc, 0x00, 0x02, 0x4f, 0xa1, 0x45, 0xa8, 0x00, 0x05, 0x02, 0x8e,
+ 0xfa, 0xff, 0xee, 0x07, 0xa6, 0x00, 0x01, 0x10, 0xb7, 0x81, 0xff, 0x00,
+ 0x19, 0xa5, 0x00, 0x01, 0x32, 0xd8, 0x82, 0xff, 0x00, 0x1a, 0xa4, 0x00,
+ 0x01, 0x5f, 0xed, 0x83, 0xff, 0x00, 0x1a, 0xa2, 0x00, 0x02, 0x02, 0x8e,
+ 0xfa, 0x84, 0xff, 0x00, 0x1a, 0xa1, 0x00, 0x01, 0x10, 0xb7, 0x86, 0xff,
+ 0x00, 0x1a, 0xa0, 0x00, 0x01, 0x32, 0xd8, 0x87, 0xff, 0x00, 0x1a, 0x9f,
+ 0x00, 0x01, 0x5f, 0xed, 0x88, 0xff, 0x00, 0x1a, 0x9d, 0x00, 0x02, 0x02,
+ 0x8e, 0xfa, 0x89, 0xff, 0x00, 0x1a, 0x9c, 0x00, 0x01, 0x10, 0xb8, 0x8b,
+ 0xff, 0x00, 0x1a, 0x9b, 0x00, 0x01, 0x32, 0xd8, 0x8c, 0xff, 0x00, 0x1a,
+ 0x9a, 0x00, 0x01, 0x5f, 0xed, 0x8d, 0xff, 0x00, 0x1a, 0x98, 0x00, 0x02,
+ 0x02, 0x8e, 0xfa, 0x8e, 0xff, 0x00, 0x1a, 0x97, 0x00, 0x01, 0x10, 0xb9,
+ 0x90, 0xff, 0x00, 0x1a, 0x96, 0x00, 0x01, 0x33, 0xd9, 0x91, 0xff, 0x00,
+ 0x1a, 0x95, 0x00, 0x01, 0x61, 0xee, 0x92, 0xff, 0x00, 0x1a, 0x93, 0x00,
+ 0x02, 0x02, 0x91, 0xfa, 0x93, 0xff, 0x00, 0x1a, 0x92, 0x00, 0x01, 0x07,
+ 0xbd, 0x95, 0xff, 0x00, 0x1a, 0x91, 0x00, 0x01, 0x01, 0x83, 0x96, 0xff,
+ 0x00, 0x1a, 0x91, 0x00, 0x01, 0x02, 0x8c, 0x96, 0xff, 0x00, 0x1a, 0x92,
+ 0x00, 0x01, 0x0e, 0xc7, 0x95, 0xff, 0x00, 0x1a, 0x93, 0x00, 0x02, 0x06,
+ 0x95, 0xfb, 0x93, 0xff, 0x00, 0x1a, 0x95, 0x00, 0x01, 0x65, 0xf0, 0x92,
+ 0xff, 0x00, 0x1a, 0x96, 0x00, 0x01, 0x35, 0xde, 0x91, 0xff, 0x00, 0x1a,
+ 0x97, 0x00, 0x01, 0x11, 0xc1, 0x90, 0xff, 0x00, 0x1a, 0x98, 0x00, 0x02,
+ 0x02, 0x98, 0xfb, 0x8e, 0xff, 0x00, 0x1a, 0x9a, 0x00, 0x01, 0x67, 0xf1,
+ 0x8d, 0xff, 0x00, 0x1a, 0x9b, 0x00, 0x01, 0x36, 0xe0, 0x8c, 0xff, 0x00,
+ 0x1a, 0x9c, 0x00, 0x01, 0x11, 0xc4, 0x8b, 0xff, 0x00, 0x1a, 0x9d, 0x00,
+ 0x02, 0x02, 0x9b, 0xfc, 0x89, 0xff, 0x00, 0x1a, 0x9f, 0x00, 0x01, 0x69,
+ 0xf2, 0x88, 0xff, 0x00, 0x1a, 0xa0, 0x00, 0x01, 0x37, 0xe2, 0x87, 0xff,
+ 0x00, 0x1a, 0xa1, 0x00, 0x01, 0x11, 0xc7, 0x86, 0xff, 0x00, 0x1a, 0xa2,
+ 0x00, 0x02, 0x02, 0x9e, 0xfc, 0x84, 0xff, 0x00, 0x1a, 0xa4, 0x00, 0x01,
+ 0x6c, 0xf4, 0x83, 0xff, 0x00, 0x1a, 0xa5, 0x00, 0x01, 0x38, 0xe5, 0x82,
+ 0xff, 0x00, 0x1a, 0xa6, 0x00, 0x01, 0x12, 0xca, 0x81, 0xff, 0x00, 0x19,
+ 0xa7, 0x00, 0x05, 0x02, 0xa1, 0xfc, 0xff, 0xe5, 0x05, 0xa9, 0x00, 0x02,
+ 0x51, 0x93, 0x43, 0xff, 0x00, 0xc7, 0x00,
+};
+static EG_EMBEDDED_IMAGE egemb_arrow_left = { 48, 48, EG_EIPIXELMODE_COLOR_ALPHA, EG_EICOMPMODE_RLE, egemb_arrow_left_data, 2407 };
--- /dev/null
+static const UINT8 egemb_arrow_right_data[2373] = {
+ 0xff, 0xff, 0xc8, 0xff, 0x03, 0x00, 0x22, 0x32, 0x00, 0xa9, 0xff, 0x04,
+ 0x00, 0x36, 0x81, 0x00, 0x00, 0xa8, 0xff, 0x05, 0x00, 0x0f, 0xbe, 0x0a,
+ 0x00, 0x00, 0xa7, 0xff, 0x04, 0x00, 0x00, 0xad, 0x93, 0x21, 0x80, 0x00,
+ 0xa5, 0xff, 0x05, 0x00, 0x00, 0x9a, 0x92, 0x95, 0x3a, 0x80, 0x00, 0xa4,
+ 0xff, 0x06, 0x00, 0x00, 0x91, 0x8a, 0x8b, 0x92, 0x57, 0x80, 0x00, 0xa3,
+ 0xff, 0x0a, 0x00, 0x00, 0x8a, 0x82, 0x83, 0x85, 0x88, 0x6c, 0x08, 0x00,
+ 0x00, 0xa2, 0xff, 0x09, 0x00, 0x00, 0x84, 0x79, 0x7b, 0x7c, 0x7f, 0x80,
+ 0x77, 0x19, 0x80, 0x00, 0xa0, 0xff, 0x0a, 0x00, 0x00, 0x7c, 0x71, 0x73,
+ 0x74, 0x76, 0x77, 0x79, 0x79, 0x2d, 0x80, 0x00, 0x9f, 0xff, 0x0b, 0x00,
+ 0x00, 0x74, 0x69, 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x73, 0x76, 0x42, 0x80,
+ 0x00, 0x9e, 0xff, 0x0f, 0x00, 0x00, 0x6e, 0x61, 0x62, 0x64, 0x65, 0x67,
+ 0x68, 0x6a, 0x6c, 0x6e, 0x52, 0x07, 0x00, 0x00, 0x9d, 0xff, 0x0e, 0x00,
+ 0x00, 0x67, 0x58, 0x5a, 0x5b, 0x5d, 0x5e, 0x60, 0x61, 0x63, 0x64, 0x67,
+ 0x5b, 0x12, 0x80, 0x00, 0x9b, 0xff, 0x0f, 0x00, 0x00, 0x60, 0x50, 0x52,
+ 0x53, 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x60, 0x5d, 0x20, 0x80,
+ 0x00, 0x9a, 0xff, 0x10, 0x00, 0x00, 0x59, 0x48, 0x49, 0x4b, 0x4c, 0x4e,
+ 0x4f, 0x51, 0x52, 0x54, 0x55, 0x57, 0x59, 0x5c, 0x2f, 0x80, 0x00, 0x99,
+ 0xff, 0x14, 0x00, 0x00, 0x52, 0x40, 0x41, 0x43, 0x44, 0x46, 0x47, 0x49,
+ 0x4a, 0x4c, 0x4d, 0x4f, 0x50, 0x52, 0x54, 0x3b, 0x05, 0x00, 0x00, 0x98,
+ 0xff, 0x13, 0x00, 0x01, 0x4d, 0x37, 0x39, 0x3a, 0x3c, 0x3d, 0x3f, 0x40,
+ 0x42, 0x43, 0x45, 0x46, 0x48, 0x49, 0x4b, 0x4d, 0x43, 0x0c, 0x80, 0x00,
+ 0x96, 0xff, 0x14, 0x00, 0x02, 0x45, 0x2e, 0x31, 0x32, 0x34, 0x35, 0x37,
+ 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x42, 0x43, 0x44, 0x46, 0x43, 0x17,
+ 0x80, 0x00, 0x95, 0xff, 0x15, 0x00, 0x02, 0x3f, 0x26, 0x28, 0x2a, 0x2b,
+ 0x2d, 0x2e, 0x30, 0x31, 0x33, 0x34, 0x36, 0x37, 0x39, 0x3a, 0x3d, 0x3e,
+ 0x40, 0x42, 0x1d, 0x80, 0x00, 0x94, 0xff, 0x19, 0x00, 0x03, 0x39, 0x1e,
+ 0x1f, 0x21, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2b, 0x2c, 0x2e, 0x2f, 0x31,
+ 0x32, 0x34, 0x36, 0x37, 0x39, 0x3a, 0x26, 0x08, 0x06, 0x0b, 0x93, 0xff,
+ 0x02, 0x00, 0x04, 0x43, 0x83, 0x30, 0x11, 0x31, 0x32, 0x2f, 0x2d, 0x2b,
+ 0x2a, 0x2a, 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x40, 0x3d, 0x2d,
+ 0x72, 0x92, 0xff, 0x02, 0x00, 0x05, 0x05, 0x85, 0x00, 0x0f, 0x03, 0x06,
+ 0x0a, 0x0d, 0x0d, 0x09, 0x07, 0x04, 0x02, 0x01, 0x00, 0x03, 0x2d, 0x61,
+ 0x56, 0xa6, 0x92, 0xff, 0x02, 0x00, 0x05, 0x05, 0x90, 0x00, 0x03, 0x0c,
+ 0x0c, 0x2a, 0x39, 0x93, 0xff, 0x02, 0x00, 0x06, 0x06, 0x8e, 0x00, 0x04,
+ 0x04, 0x00, 0x01, 0x00, 0x12, 0x94, 0xff, 0x02, 0x00, 0x07, 0x07, 0x8d,
+ 0x00, 0x01, 0x07, 0x0c, 0x80, 0x00, 0x95, 0xff, 0x02, 0x00, 0x08, 0x08,
+ 0x8c, 0x00, 0x01, 0x0d, 0x08, 0x80, 0x00, 0x96, 0xff, 0x02, 0x00, 0x09,
+ 0x09, 0x8b, 0x00, 0x03, 0x14, 0x06, 0x00, 0x00, 0x98, 0xff, 0x02, 0x00,
+ 0x0a, 0x0a, 0x89, 0x00, 0x04, 0x06, 0x00, 0x01, 0x00, 0x00, 0x99, 0xff,
+ 0x02, 0x00, 0x0a, 0x0a, 0x88, 0x00, 0x01, 0x0b, 0x12, 0x80, 0x00, 0x9a,
+ 0xff, 0x02, 0x00, 0x0b, 0x0b, 0x87, 0x00, 0x01, 0x13, 0x0c, 0x80, 0x00,
+ 0x9b, 0xff, 0x02, 0x00, 0x0c, 0x0c, 0x85, 0x00, 0x04, 0x01, 0x1c, 0x08,
+ 0x00, 0x00, 0x9d, 0xff, 0x02, 0x00, 0x0d, 0x0d, 0x84, 0x00, 0x04, 0x08,
+ 0x1e, 0x01, 0x00, 0x00, 0x9e, 0xff, 0x02, 0x00, 0x0e, 0x0e, 0x83, 0x00,
+ 0x01, 0x0f, 0x18, 0x80, 0x00, 0x9f, 0xff, 0x02, 0x00, 0x0f, 0x0f, 0x82,
+ 0x00, 0x01, 0x1a, 0x11, 0x80, 0x00, 0xa0, 0xff, 0x02, 0x00, 0x10, 0x10,
+ 0x80, 0x00, 0x04, 0x01, 0x24, 0x0a, 0x00, 0x00, 0xa2, 0xff, 0x09, 0x00,
+ 0x11, 0x11, 0x00, 0x00, 0x0a, 0x27, 0x01, 0x00, 0x00, 0xa3, 0xff, 0x05,
+ 0x00, 0x11, 0x12, 0x00, 0x14, 0x1f, 0x80, 0x00, 0xa4, 0xff, 0x04, 0x00,
+ 0x12, 0x1f, 0x21, 0x15, 0x80, 0x00, 0xa5, 0xff, 0x05, 0x00, 0x13, 0x59,
+ 0x0c, 0x00, 0x00, 0xa7, 0xff, 0x04, 0x00, 0x0a, 0x3e, 0x00, 0x00, 0xa8,
+ 0xff, 0x03, 0x00, 0x08, 0x1a, 0x00, 0xff, 0xff, 0xda, 0xff, 0xff, 0xff,
+ 0xc8, 0xff, 0x03, 0x60, 0x64, 0x6f, 0x55, 0xa9, 0xff, 0x04, 0x4b, 0x73,
+ 0xa7, 0x4d, 0x49, 0xa8, 0xff, 0x05, 0x4d, 0x57, 0xdd, 0x54, 0x4d, 0x4e,
+ 0xa7, 0xff, 0x07, 0x4d, 0x4d, 0xe2, 0xc2, 0x64, 0x4d, 0x4b, 0x80, 0xa5,
+ 0xff, 0x08, 0x4d, 0x4d, 0xd2, 0xcf, 0xca, 0x78, 0x4d, 0x4c, 0x4f, 0xa4,
+ 0xff, 0x09, 0x4d, 0x4d, 0xcb, 0xc8, 0xca, 0xcc, 0x90, 0x4d, 0x4d, 0x49,
+ 0xa3, 0xff, 0x0a, 0x4d, 0x4d, 0xc6, 0xc2, 0xc3, 0xc5, 0xc7, 0xa4, 0x52,
+ 0x4d, 0x4d, 0xa2, 0xff, 0x0c, 0x4f, 0x4f, 0xc0, 0xbd, 0xbe, 0xbf, 0xc1,
+ 0xc2, 0xb1, 0x61, 0x4d, 0x4b, 0x80, 0xa0, 0xff, 0x0d, 0x53, 0x54, 0xbc,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xb8, 0x72, 0x4d, 0x4c, 0x4f, 0x9f,
+ 0xff, 0x0e, 0x56, 0x58, 0xb9, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb9,
+ 0xb9, 0x83, 0x4d, 0x4d, 0x49, 0x9e, 0xff, 0x06, 0x59, 0x5d, 0xb5, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0x80, 0xb3, 0x05, 0xb4, 0xb5, 0x95, 0x54, 0x4d, 0x4d,
+ 0x9d, 0xff, 0x06, 0x5d, 0x62, 0xb3, 0xac, 0xad, 0xae, 0xae, 0x83, 0xaf,
+ 0x04, 0xa0, 0x5f, 0x50, 0x4d, 0x80, 0x9b, 0xff, 0x08, 0x60, 0x66, 0xb1,
+ 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xac, 0x80, 0xab, 0x06, 0xaa, 0xaa, 0xa4,
+ 0x6e, 0x54, 0x50, 0x4f, 0x9a, 0xff, 0x04, 0x62, 0x6b, 0xb0, 0xa8, 0xa8,
+ 0x82, 0xa9, 0x09, 0xa8, 0xa7, 0xa6, 0xa5, 0xa5, 0xa3, 0x7b, 0x57, 0x54,
+ 0x4f, 0x99, 0xff, 0x14, 0x67, 0x70, 0xaf, 0xa6, 0xa7, 0xa7, 0xa8, 0xa7,
+ 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa1, 0xa0, 0x9e, 0x9d, 0x85, 0x5d, 0x57,
+ 0x52, 0x98, 0xff, 0x02, 0x68, 0x72, 0xaf, 0x81, 0xa6, 0x0f, 0xa5, 0xa4,
+ 0xa4, 0xa3, 0xa1, 0xa0, 0x9e, 0x9c, 0x9a, 0x98, 0x97, 0x8a, 0x64, 0x5b,
+ 0x53, 0x80, 0x96, 0xff, 0x17, 0x6a, 0x76, 0xaf, 0xa5, 0xa6, 0xa6, 0xa5,
+ 0xa5, 0xa4, 0xa2, 0xa1, 0x9e, 0x9d, 0x9a, 0x98, 0x97, 0x94, 0x92, 0x90,
+ 0x8a, 0x6c, 0x5d, 0x58, 0x4f, 0x95, 0xff, 0x18, 0x6e, 0x79, 0xb0, 0xa5,
+ 0xa5, 0xa6, 0xa5, 0xa4, 0xa3, 0xa1, 0x9f, 0x9d, 0x9a, 0x98, 0x95, 0x92,
+ 0x8f, 0x8e, 0x8b, 0x88, 0x84, 0x6d, 0x5e, 0x5b, 0x51, 0x94, 0xff, 0x02,
+ 0x6f, 0x7b, 0xb1, 0x80, 0xa6, 0x13, 0xa5, 0xa5, 0xa2, 0xa0, 0x9e, 0x9b,
+ 0x98, 0x95, 0x92, 0x8f, 0x8b, 0x88, 0x86, 0x83, 0x7f, 0x7d, 0x6f, 0x65,
+ 0x63, 0x5c, 0x93, 0xff, 0x1a, 0x72, 0x7f, 0xba, 0xb2, 0xb1, 0xaf, 0xaf,
+ 0xac, 0xa9, 0xa7, 0xa4, 0x9f, 0x9a, 0x95, 0x91, 0x8c, 0x89, 0x85, 0x81,
+ 0x7e, 0x7a, 0x76, 0x73, 0x7d, 0x86, 0x7c, 0x8e, 0x92, 0xff, 0x1a, 0x74,
+ 0x82, 0xa6, 0xa4, 0xa3, 0xa1, 0x9e, 0x9b, 0x97, 0x92, 0x8d, 0x89, 0x85,
+ 0x82, 0x7d, 0x78, 0x6f, 0x67, 0x5f, 0x57, 0x4f, 0x48, 0x43, 0x65, 0x9e,
+ 0x97, 0xb8, 0x92, 0xff, 0x19, 0x75, 0x83, 0xad, 0xab, 0xaa, 0xa7, 0xa4,
+ 0xa1, 0x9c, 0x97, 0x92, 0x8c, 0x86, 0x80, 0x7a, 0x73, 0x6d, 0x66, 0x5f,
+ 0x58, 0x51, 0x4a, 0x5d, 0x70, 0x81, 0x81, 0x93, 0xff, 0x18, 0x77, 0x87,
+ 0xb4, 0xb2, 0xb0, 0xae, 0xab, 0xa6, 0xa1, 0x9c, 0x96, 0x90, 0x8a, 0x83,
+ 0x7d, 0x76, 0x6f, 0x68, 0x61, 0x5a, 0x57, 0x60, 0x6e, 0x68, 0x65, 0x94,
+ 0xff, 0x17, 0x79, 0x88, 0xbb, 0xb9, 0xb7, 0xb4, 0xb0, 0xac, 0xa6, 0xa0,
+ 0x9a, 0x94, 0x8d, 0x86, 0x7f, 0x78, 0x71, 0x6a, 0x63, 0x63, 0x74, 0x70,
+ 0x66, 0x4a, 0x95, 0xff, 0x16, 0x7a, 0x8a, 0xc2, 0xc0, 0xbe, 0xba, 0xb6,
+ 0xb0, 0xaa, 0xa4, 0x9d, 0x96, 0x90, 0x89, 0x81, 0x7a, 0x73, 0x6b, 0x72,
+ 0x78, 0x72, 0x65, 0x80, 0x96, 0xff, 0x14, 0x7c, 0x8c, 0xc9, 0xc7, 0xc4,
+ 0xc0, 0xba, 0xb4, 0xae, 0xa7, 0xa0, 0x99, 0x91, 0x8a, 0x83, 0x7b, 0x75,
+ 0x7f, 0x7a, 0x74, 0x64, 0x98, 0xff, 0x13, 0x7e, 0x8f, 0xd0, 0xcd, 0xca,
+ 0xc4, 0xbe, 0xb7, 0xb0, 0xa9, 0xa1, 0x9a, 0x92, 0x8b, 0x83, 0x80, 0x86,
+ 0x7b, 0x75, 0x60, 0x99, 0xff, 0x12, 0x80, 0x8f, 0xd7, 0xd4, 0xce, 0xc7,
+ 0xc0, 0xb8, 0xb1, 0xaa, 0xa2, 0x9a, 0x93, 0x8b, 0x89, 0x88, 0x7b, 0x73,
+ 0x59, 0x9a, 0xff, 0x11, 0x80, 0x8f, 0xdc, 0xd7, 0xd0, 0xc8, 0xc0, 0xb8,
+ 0xb1, 0xa9, 0xa1, 0x9a, 0x92, 0x92, 0x87, 0x7e, 0x70, 0x80, 0x9b, 0xff,
+ 0x0f, 0x82, 0x91, 0xd6, 0xd2, 0xcc, 0xc5, 0xbe, 0xb6, 0xaf, 0xa7, 0xa0,
+ 0x98, 0x9a, 0x84, 0x7e, 0x6c, 0x9d, 0xff, 0x0e, 0x83, 0x92, 0xcd, 0xca,
+ 0xc6, 0xc0, 0xba, 0xb3, 0xac, 0xa4, 0x9f, 0x9b, 0x82, 0x7f, 0x66, 0x9e,
+ 0xff, 0x0d, 0x86, 0x93, 0xc5, 0xc1, 0xbe, 0xba, 0xb4, 0xae, 0xa7, 0xa4,
+ 0x96, 0x84, 0x7d, 0x59, 0x9f, 0xff, 0x0c, 0x87, 0x94, 0xbd, 0xb8, 0xb6,
+ 0xb2, 0xad, 0xa8, 0xa8, 0x90, 0x85, 0x77, 0x80, 0xa0, 0xff, 0x0a, 0x87,
+ 0x94, 0xb5, 0xaf, 0xad, 0xaa, 0xa6, 0xa8, 0x8b, 0x86, 0x74, 0xa2, 0xff,
+ 0x03, 0x89, 0x93, 0xac, 0xa5, 0x80, 0xa4, 0x02, 0x87, 0x85, 0x6c, 0xa3,
+ 0xff, 0x08, 0x89, 0x93, 0xa4, 0x9c, 0xa2, 0x9b, 0x87, 0x85, 0x59, 0xa4,
+ 0xff, 0x07, 0x8b, 0x94, 0xa1, 0xa1, 0x94, 0x88, 0x7f, 0x80, 0xa5, 0xff,
+ 0x05, 0x8b, 0x92, 0xb7, 0x8e, 0x89, 0x7d, 0xa7, 0xff, 0x04, 0x7e, 0x8d,
+ 0xa6, 0x8a, 0x76, 0xa8, 0xff, 0x03, 0x00, 0x85, 0x8f, 0x69, 0xff, 0xff,
+ 0xda, 0xff, 0xff, 0xff, 0xc8, 0xff, 0x03, 0x00, 0x22, 0x32, 0x00, 0xa9,
+ 0xff, 0x04, 0x00, 0x36, 0x81, 0x00, 0x00, 0xa8, 0xff, 0x05, 0x00, 0x0f,
+ 0xbe, 0x0a, 0x00, 0x00, 0xa7, 0xff, 0x04, 0x00, 0x00, 0xad, 0x93, 0x21,
+ 0x80, 0x00, 0xa5, 0xff, 0x05, 0x00, 0x00, 0x9a, 0x92, 0x95, 0x3a, 0x80,
+ 0x00, 0xa4, 0xff, 0x06, 0x00, 0x00, 0x91, 0x8a, 0x8b, 0x92, 0x57, 0x80,
+ 0x00, 0xa3, 0xff, 0x0a, 0x00, 0x00, 0x8a, 0x82, 0x83, 0x85, 0x88, 0x6c,
+ 0x08, 0x00, 0x00, 0xa2, 0xff, 0x09, 0x00, 0x00, 0x84, 0x79, 0x7b, 0x7c,
+ 0x7f, 0x80, 0x77, 0x19, 0x80, 0x00, 0xa0, 0xff, 0x0a, 0x00, 0x00, 0x7c,
+ 0x71, 0x73, 0x74, 0x76, 0x77, 0x79, 0x79, 0x2d, 0x80, 0x00, 0x9f, 0xff,
+ 0x0b, 0x00, 0x00, 0x74, 0x69, 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x73, 0x76,
+ 0x42, 0x80, 0x00, 0x9e, 0xff, 0x0f, 0x00, 0x00, 0x6e, 0x61, 0x62, 0x64,
+ 0x65, 0x67, 0x68, 0x6a, 0x6c, 0x6e, 0x52, 0x07, 0x00, 0x00, 0x9d, 0xff,
+ 0x0e, 0x00, 0x00, 0x67, 0x58, 0x5a, 0x5b, 0x5d, 0x5e, 0x60, 0x61, 0x63,
+ 0x64, 0x67, 0x5b, 0x12, 0x80, 0x00, 0x9b, 0xff, 0x0f, 0x00, 0x00, 0x60,
+ 0x50, 0x52, 0x53, 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x60, 0x5d,
+ 0x20, 0x80, 0x00, 0x9a, 0xff, 0x10, 0x00, 0x00, 0x59, 0x48, 0x49, 0x4b,
+ 0x4c, 0x4e, 0x4f, 0x51, 0x52, 0x54, 0x55, 0x57, 0x59, 0x5c, 0x2f, 0x80,
+ 0x00, 0x99, 0xff, 0x14, 0x00, 0x01, 0x52, 0x40, 0x41, 0x43, 0x44, 0x46,
+ 0x47, 0x49, 0x4a, 0x4c, 0x4d, 0x4f, 0x50, 0x52, 0x54, 0x3b, 0x06, 0x00,
+ 0x00, 0x98, 0xff, 0x16, 0x01, 0x02, 0x4d, 0x37, 0x39, 0x3a, 0x3c, 0x3d,
+ 0x3f, 0x40, 0x42, 0x43, 0x45, 0x46, 0x48, 0x49, 0x4b, 0x4d, 0x43, 0x0d,
+ 0x01, 0x00, 0x00, 0x96, 0xff, 0x17, 0x01, 0x03, 0x45, 0x2e, 0x31, 0x32,
+ 0x34, 0x35, 0x37, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x42, 0x43, 0x44,
+ 0x46, 0x43, 0x18, 0x01, 0x01, 0x00, 0x95, 0xff, 0x18, 0x01, 0x03, 0x3f,
+ 0x26, 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x30, 0x31, 0x33, 0x34, 0x36, 0x37,
+ 0x39, 0x3a, 0x3d, 0x3e, 0x40, 0x42, 0x1e, 0x01, 0x01, 0x00, 0x94, 0xff,
+ 0x19, 0x01, 0x04, 0x39, 0x1e, 0x1f, 0x21, 0x23, 0x25, 0x26, 0x28, 0x29,
+ 0x2b, 0x2c, 0x2e, 0x2f, 0x31, 0x32, 0x34, 0x36, 0x37, 0x39, 0x3a, 0x26,
+ 0x09, 0x07, 0x0b, 0x93, 0xff, 0x02, 0x01, 0x06, 0x43, 0x83, 0x30, 0x11,
+ 0x31, 0x32, 0x2f, 0x2d, 0x2b, 0x2a, 0x2a, 0x2d, 0x2d, 0x2f, 0x30, 0x31,
+ 0x32, 0x34, 0x40, 0x3f, 0x2e, 0x72, 0x92, 0xff, 0x02, 0x01, 0x07, 0x05,
+ 0x85, 0x00, 0x0f, 0x03, 0x06, 0x0a, 0x0d, 0x0d, 0x09, 0x07, 0x04, 0x02,
+ 0x01, 0x00, 0x03, 0x2d, 0x62, 0x57, 0xa6, 0x92, 0xff, 0x02, 0x01, 0x07,
+ 0x05, 0x90, 0x00, 0x03, 0x0d, 0x0e, 0x2c, 0x3c, 0x93, 0xff, 0x02, 0x01,
+ 0x08, 0x06, 0x8e, 0x00, 0x04, 0x04, 0x01, 0x03, 0x02, 0x12, 0x94, 0xff,
+ 0x02, 0x01, 0x0a, 0x07, 0x8d, 0x00, 0x04, 0x07, 0x0e, 0x03, 0x03, 0x00,
+ 0x95, 0xff, 0x02, 0x03, 0x0b, 0x08, 0x8c, 0x00, 0x04, 0x0e, 0x0b, 0x03,
+ 0x02, 0x00, 0x96, 0xff, 0x02, 0x03, 0x0c, 0x09, 0x8b, 0x00, 0x03, 0x15,
+ 0x09, 0x03, 0x03, 0x98, 0xff, 0x02, 0x03, 0x0d, 0x0a, 0x89, 0x00, 0x04,
+ 0x06, 0x02, 0x04, 0x02, 0x00, 0x99, 0xff, 0x02, 0x03, 0x0e, 0x0a, 0x88,
+ 0x00, 0x04, 0x0b, 0x15, 0x04, 0x03, 0x00, 0x9a, 0xff, 0x02, 0x03, 0x0f,
+ 0x0b, 0x87, 0x00, 0x04, 0x14, 0x10, 0x04, 0x02, 0x00, 0x9b, 0xff, 0x02,
+ 0x03, 0x10, 0x0c, 0x85, 0x00, 0x04, 0x01, 0x1e, 0x0c, 0x04, 0x02, 0x9d,
+ 0xff, 0x02, 0x03, 0x11, 0x0d, 0x84, 0x00, 0x04, 0x08, 0x20, 0x05, 0x03,
+ 0x05, 0x9e, 0xff, 0x02, 0x03, 0x12, 0x0e, 0x83, 0x00, 0x04, 0x0f, 0x1b,
+ 0x04, 0x04, 0x00, 0x9f, 0xff, 0x02, 0x03, 0x14, 0x0f, 0x82, 0x00, 0x04,
+ 0x1b, 0x16, 0x05, 0x03, 0x00, 0xa0, 0xff, 0x02, 0x04, 0x15, 0x10, 0x80,
+ 0x00, 0x04, 0x01, 0x26, 0x0f, 0x04, 0x02, 0xa2, 0xff, 0x09, 0x04, 0x16,
+ 0x11, 0x00, 0x00, 0x0a, 0x29, 0x06, 0x04, 0x05, 0xa3, 0xff, 0x08, 0x04,
+ 0x16, 0x12, 0x00, 0x14, 0x22, 0x05, 0x04, 0x00, 0xa4, 0xff, 0x07, 0x04,
+ 0x18, 0x19, 0x22, 0x1a, 0x05, 0x03, 0x00, 0xa5, 0xff, 0x05, 0x04, 0x18,
+ 0x49, 0x12, 0x05, 0x02, 0xa7, 0xff, 0x04, 0x02, 0x0c, 0x25, 0x06, 0x04,
+ 0xa8, 0xff, 0x03, 0x00, 0x08, 0x11, 0x00, 0xff, 0xff, 0xda, 0xff, 0xff,
+ 0x00, 0xc8, 0x00, 0x03, 0x08, 0x87, 0x9a, 0x0f, 0xa9, 0x00, 0x04, 0x7e,
+ 0xff, 0xff, 0xd8, 0x32, 0xa8, 0x00, 0x00, 0xae, 0x80, 0xff, 0x01, 0xed,
+ 0x5e, 0xa7, 0x00, 0x00, 0xaf, 0x81, 0xff, 0x02, 0xfa, 0x8e, 0x02, 0xa5,
+ 0x00, 0x00, 0xaf, 0x83, 0xff, 0x01, 0xb7, 0x10, 0xa4, 0x00, 0x00, 0xaf,
+ 0x84, 0xff, 0x01, 0xd8, 0x32, 0xa3, 0x00, 0x00, 0xaf, 0x85, 0xff, 0x01,
+ 0xed, 0x5f, 0xa2, 0x00, 0x00, 0xaf, 0x86, 0xff, 0x02, 0xfa, 0x8e, 0x02,
+ 0xa0, 0x00, 0x00, 0xaf, 0x88, 0xff, 0x01, 0xb8, 0x10, 0x9f, 0x00, 0x00,
+ 0xaf, 0x89, 0xff, 0x01, 0xd8, 0x32, 0x9e, 0x00, 0x00, 0xaf, 0x8a, 0xff,
+ 0x01, 0xed, 0x5f, 0x9d, 0x00, 0x00, 0xaf, 0x8b, 0xff, 0x02, 0xfa, 0x8e,
+ 0x02, 0x9b, 0x00, 0x00, 0xaf, 0x8d, 0xff, 0x01, 0xb8, 0x10, 0x9a, 0x00,
+ 0x00, 0xaf, 0x8e, 0xff, 0x01, 0xd8, 0x32, 0x99, 0x00, 0x00, 0xb0, 0x8f,
+ 0xff, 0x01, 0xed, 0x60, 0x98, 0x00, 0x00, 0xb1, 0x90, 0xff, 0x02, 0xfa,
+ 0x90, 0x02, 0x96, 0x00, 0x00, 0xb2, 0x92, 0xff, 0x01, 0xbb, 0x10, 0x95,
+ 0x00, 0x00, 0xb2, 0x93, 0xff, 0x01, 0xda, 0x34, 0x94, 0x00, 0x00, 0xb3,
+ 0x94, 0xff, 0x01, 0xef, 0x5d, 0x93, 0x00, 0x00, 0xb4, 0x95, 0xff, 0x01,
+ 0xe6, 0x09, 0x92, 0x00, 0x00, 0xb5, 0x95, 0xff, 0x01, 0xea, 0x0e, 0x92,
+ 0x00, 0x00, 0xb5, 0x94, 0xff, 0x02, 0xf2, 0x6a, 0x02, 0x92, 0x00, 0x00,
+ 0xb6, 0x93, 0xff, 0x02, 0xdd, 0x37, 0x02, 0x93, 0x00, 0x00, 0xb7, 0x92,
+ 0xff, 0x01, 0xc0, 0x11, 0x95, 0x00, 0x00, 0xb7, 0x90, 0xff, 0x02, 0xfb,
+ 0x96, 0x02, 0x96, 0x00, 0x00, 0xb8, 0x8f, 0xff, 0x01, 0xf1, 0x66, 0x98,
+ 0x00, 0x00, 0xb9, 0x8e, 0xff, 0x01, 0xdf, 0x35, 0x99, 0x00, 0x00, 0xba,
+ 0x8d, 0xff, 0x01, 0xc3, 0x11, 0x9a, 0x00, 0x00, 0xbb, 0x8b, 0xff, 0x02,
+ 0xfb, 0x99, 0x02, 0x9b, 0x00, 0x00, 0xbc, 0x8a, 0xff, 0x01, 0xf2, 0x68,
+ 0x9d, 0x00, 0x00, 0xbc, 0x89, 0xff, 0x01, 0xe1, 0x37, 0x9e, 0x00, 0x00,
+ 0xbd, 0x88, 0xff, 0x01, 0xc5, 0x11, 0x9f, 0x00, 0x00, 0xbe, 0x86, 0xff,
+ 0x02, 0xfc, 0x9c, 0x02, 0xa0, 0x00, 0x00, 0xbe, 0x85, 0xff, 0x01, 0xf3,
+ 0x6a, 0xa2, 0x00, 0x00, 0xbf, 0x84, 0xff, 0x01, 0xe4, 0x38, 0xa3, 0x00,
+ 0x00, 0xc0, 0x83, 0xff, 0x01, 0xc8, 0x11, 0xa4, 0x00, 0x00, 0xc1, 0x81,
+ 0xff, 0x02, 0xfc, 0x9f, 0x02, 0xa5, 0x00, 0x00, 0xc1, 0x80, 0xff, 0x01,
+ 0xf4, 0x6c, 0xa7, 0x00, 0x04, 0x73, 0xfe, 0xff, 0xe6, 0x39, 0xa8, 0x00,
+ 0x03, 0x01, 0x86, 0x87, 0x11, 0xff, 0x00, 0xda, 0x00,
+};
+static EG_EMBEDDED_IMAGE egemb_arrow_right = { 48, 48, EG_EIPIXELMODE_COLOR_ALPHA, EG_EICOMPMODE_RLE, egemb_arrow_right_data, 2373 };
--- /dev/null
+static const UINT8 egemb_back_selected_small_data[1503] = {
+ 0x83, 0xbf, 0x02, 0xc8, 0xd2, 0xd6, 0xab, 0xdc, 0x02, 0xd6, 0xd2, 0xc8,
+ 0x87, 0xbf, 0x01, 0xc3, 0xd6, 0x80, 0xdc, 0x04, 0xdb, 0xd7, 0xd5, 0xd3,
+ 0xd1, 0xa1, 0xd0, 0x04, 0xd1, 0xd3, 0xd5, 0xd7, 0xdb, 0x80, 0xdc, 0x01,
+ 0xd6, 0xc3, 0x84, 0xbf, 0x0b, 0xcc, 0xdb, 0xdc, 0xdc, 0xd5, 0xcd, 0xc7,
+ 0xc3, 0xbf, 0xbe, 0xbd, 0xbc, 0x9f, 0xbb, 0x0b, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc3, 0xc7, 0xcd, 0xd5, 0xdc, 0xdc, 0xdb, 0xcc, 0x82, 0xbf, 0x0c, 0xcf,
+ 0xdc, 0xdc, 0xd7, 0xcc, 0xc3, 0xba, 0xb4, 0xb0, 0xad, 0xac, 0xaa, 0xaa,
+ 0x9f, 0xa9, 0x0c, 0xaa, 0xaa, 0xac, 0xad, 0xb0, 0xb4, 0xba, 0xc3, 0xcc,
+ 0xd7, 0xdc, 0xdc, 0xcf, 0x80, 0xbf, 0x0d, 0xc9, 0xdc, 0xdc, 0xd5, 0xc8,
+ 0xbc, 0xb2, 0xaa, 0xa3, 0x9f, 0x9d, 0x9c, 0x9b, 0x9a, 0x9f, 0x99, 0x1c,
+ 0x9a, 0x9b, 0x9c, 0x9d, 0x9f, 0xa3, 0xaa, 0xb2, 0xbc, 0xc8, 0xd5, 0xdc,
+ 0xdc, 0xc9, 0xbf, 0xc0, 0xd9, 0xdc, 0xd7, 0xc8, 0xb9, 0xad, 0xa3, 0x9b,
+ 0x96, 0x92, 0x90, 0x8e, 0x8e, 0xa1, 0x8d, 0x1b, 0x8e, 0x8e, 0x90, 0x92,
+ 0x96, 0x9b, 0xa3, 0xad, 0xb9, 0xc8, 0xd7, 0xdc, 0xd8, 0xc0, 0xc9, 0xdc,
+ 0xdc, 0xcb, 0xbb, 0xad, 0xa1, 0x97, 0x8f, 0x8a, 0x87, 0x85, 0x84, 0x83,
+ 0xa1, 0x82, 0x1a, 0x83, 0x84, 0x85, 0x87, 0x8a, 0x8f, 0x97, 0xa1, 0xad,
+ 0xbb, 0xcb, 0xdc, 0xdc, 0xc9, 0xd2, 0xdc, 0xd4, 0xc2, 0xb2, 0xa3, 0x97,
+ 0x8d, 0x86, 0x81, 0x7e, 0x7c, 0x7c, 0xa3, 0x7b, 0x18, 0x7c, 0x7c, 0x7e,
+ 0x81, 0x86, 0x8d, 0x97, 0xa3, 0xb2, 0xc2, 0xd4, 0xdc, 0xd2, 0xd8, 0xdc,
+ 0xcc, 0xba, 0xa9, 0x9b, 0x8f, 0x86, 0x7f, 0x7a, 0x78, 0x77, 0x80, 0x76,
+ 0x9f, 0x75, 0x80, 0x76, 0x17, 0x77, 0x78, 0x7a, 0x7f, 0x86, 0x8f, 0x9b,
+ 0xa9, 0xba, 0xcc, 0xdc, 0xd8, 0xda, 0xdb, 0xc6, 0xb4, 0xa3, 0x95, 0x8a,
+ 0x81, 0x7a, 0x76, 0x74, 0x74, 0xa5, 0x73, 0x16, 0x74, 0x74, 0x76, 0x7a,
+ 0x80, 0x8a, 0x95, 0xa3, 0xb4, 0xc6, 0xdb, 0xdb, 0xdc, 0xd7, 0xc3, 0xaf,
+ 0x9f, 0x91, 0x86, 0x7d, 0x78, 0x74, 0x74, 0xa7, 0x73, 0x14, 0x74, 0x74,
+ 0x78, 0x7d, 0x86, 0x91, 0x9f, 0xaf, 0xc2, 0xd7, 0xdc, 0xdc, 0xd4, 0xbf,
+ 0xad, 0x9d, 0x90, 0x85, 0x7c, 0x77, 0x74, 0xa9, 0x73, 0x12, 0x74, 0x77,
+ 0x7c, 0x85, 0x90, 0x9d, 0xad, 0xbf, 0xd4, 0xdc, 0xdc, 0xd3, 0xbe, 0xac,
+ 0x9b, 0x8e, 0x83, 0x7c, 0x76, 0xab, 0x73, 0x11, 0x76, 0x7c, 0x83, 0x8e,
+ 0x9b, 0xab, 0xbe, 0xd3, 0xdc, 0xdc, 0xd1, 0xbc, 0xaa, 0x9b, 0x8d, 0x83,
+ 0x7b, 0x76, 0xab, 0x73, 0x11, 0x76, 0x7b, 0x83, 0x8d, 0x9b, 0xaa, 0xbc,
+ 0xd1, 0xdc, 0xdc, 0xd0, 0xbc, 0xaa, 0x9a, 0x8d, 0x82, 0x7b, 0x76, 0xab,
+ 0x73, 0x11, 0x76, 0x7b, 0x82, 0x8d, 0x9a, 0xaa, 0xbc, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82,
+ 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb,
+ 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab,
+ 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc,
+ 0xd0, 0xbb, 0xa9, 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75,
+ 0x7b, 0x82, 0x8d, 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbb, 0xa9,
+ 0x99, 0x8d, 0x82, 0x7b, 0x75, 0xab, 0x73, 0x11, 0x75, 0x7b, 0x82, 0x8d,
+ 0x99, 0xa9, 0xbb, 0xd0, 0xdc, 0xdc, 0xd0, 0xbc, 0xaa, 0x9a, 0x8d, 0x82,
+ 0x7b, 0x76, 0xab, 0x73, 0x11, 0x76, 0x7b, 0x82, 0x8d, 0x9a, 0xaa, 0xbc,
+ 0xd0, 0xdc, 0xdc, 0xd1, 0xbc, 0xaa, 0x9b, 0x8d, 0x83, 0x7b, 0x76, 0xab,
+ 0x73, 0x11, 0x76, 0x7b, 0x83, 0x8d, 0x9b, 0xaa, 0xbc, 0xd1, 0xdc, 0xdc,
+ 0xd3, 0xbe, 0xac, 0x9b, 0x8e, 0x83, 0x7c, 0x76, 0xab, 0x73, 0x12, 0x76,
+ 0x7c, 0x83, 0x8e, 0x9b, 0xab, 0xbe, 0xd3, 0xdc, 0xdc, 0xd4, 0xbf, 0xad,
+ 0x9d, 0x90, 0x85, 0x7c, 0x77, 0x74, 0xa9, 0x73, 0x14, 0x74, 0x77, 0x7c,
+ 0x85, 0x90, 0x9d, 0xad, 0xbf, 0xd4, 0xdc, 0xdc, 0xd7, 0xc2, 0xaf, 0x9f,
+ 0x91, 0x86, 0x7d, 0x78, 0x74, 0x74, 0xa7, 0x73, 0x16, 0x74, 0x74, 0x78,
+ 0x7d, 0x86, 0x91, 0x9f, 0xaf, 0xc2, 0xd7, 0xdc, 0xda, 0xdb, 0xc6, 0xb4,
+ 0xa3, 0x95, 0x8a, 0x80, 0x7a, 0x76, 0x74, 0x74, 0xa5, 0x73, 0x17, 0x74,
+ 0x74, 0x76, 0x7a, 0x80, 0x8a, 0x95, 0xa3, 0xb4, 0xc6, 0xdb, 0xdb, 0xd8,
+ 0xdc, 0xcc, 0xba, 0xa9, 0x9b, 0x8f, 0x86, 0x7f, 0x7a, 0x78, 0x77, 0x80,
+ 0x76, 0x9f, 0x75, 0x80, 0x76, 0x18, 0x77, 0x78, 0x7a, 0x7f, 0x86, 0x8f,
+ 0x9b, 0xa9, 0xba, 0xcc, 0xdc, 0xd8, 0xd2, 0xdc, 0xd4, 0xc2, 0xb1, 0xa3,
+ 0x97, 0x8d, 0x86, 0x81, 0x7e, 0x7c, 0x7c, 0xa3, 0x7b, 0x1a, 0x7c, 0x7c,
+ 0x7e, 0x81, 0x86, 0x8d, 0x97, 0xa3, 0xb1, 0xc2, 0xd4, 0xdc, 0xd2, 0xc9,
+ 0xdc, 0xdc, 0xcb, 0xbb, 0xad, 0xa1, 0x97, 0x8f, 0x8a, 0x87, 0x85, 0x84,
+ 0x83, 0xa1, 0x82, 0x1b, 0x83, 0x84, 0x85, 0x86, 0x8a, 0x8f, 0x97, 0xa1,
+ 0xad, 0xbb, 0xcb, 0xdc, 0xdc, 0xc9, 0xc0, 0xd8, 0xdc, 0xd6, 0xc8, 0xb9,
+ 0xad, 0xa3, 0x9b, 0x95, 0x92, 0x90, 0x8e, 0x8e, 0xa1, 0x8d, 0x1c, 0x8e,
+ 0x8e, 0x90, 0x92, 0x95, 0x9b, 0xa3, 0xad, 0xb9, 0xc8, 0xd6, 0xdc, 0xd8,
+ 0xc0, 0xbf, 0xc9, 0xdc, 0xdc, 0xd5, 0xc8, 0xbb, 0xb2, 0xa9, 0xa3, 0x9f,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x9f, 0x99, 0x0d, 0x9a, 0x9b, 0x9c, 0x9d, 0x9f,
+ 0xa3, 0xa9, 0xb2, 0xbb, 0xc8, 0xd5, 0xdc, 0xdc, 0xc9, 0x80, 0xbf, 0x0c,
+ 0xcf, 0xdc, 0xdc, 0xd7, 0xcc, 0xc2, 0xba, 0xb4, 0xb0, 0xad, 0xac, 0xaa,
+ 0xaa, 0x9f, 0xa9, 0x0c, 0xaa, 0xaa, 0xac, 0xad, 0xb0, 0xb4, 0xba, 0xc2,
+ 0xcc, 0xd7, 0xdc, 0xdc, 0xcf, 0x82, 0xbf, 0x0b, 0xcd, 0xdb, 0xdc, 0xdc,
+ 0xd5, 0xcd, 0xc7, 0xc3, 0xbf, 0xbe, 0xbc, 0xbc, 0x9f, 0xbb, 0x0b, 0xbc,
+ 0xbc, 0xbe, 0xbf, 0xc3, 0xc7, 0xcc, 0xd5, 0xdc, 0xdc, 0xdb, 0xcd, 0x84,
+ 0xbf, 0x01, 0xc3, 0xd6, 0x80, 0xdc, 0x04, 0xdb, 0xd7, 0xd5, 0xd3, 0xd1,
+ 0xa1, 0xd0, 0x04, 0xd1, 0xd3, 0xd5, 0xd7, 0xdb, 0x80, 0xdc, 0x01, 0xd6,
+ 0xc4, 0x87, 0xbf, 0x02, 0xc9, 0xd2, 0xd6, 0xab, 0xdc, 0x02, 0xd6, 0xd2,
+ 0xc9, 0x83, 0xbf,
+};
+static EG_EMBEDDED_IMAGE egemb_back_selected_small = { 64, 64, EG_EIPIXELMODE_GRAY, EG_EICOMPMODE_RLE, egemb_back_selected_small_data, 1503 };
--- /dev/null
+static const UINT8 egemb_refind_banner_data[7592] = {
+ 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0xff, 0xc0, 0x8e, 0xc0, 0x08, 0xb2, 0x98, 0x83, 0x6e, 0x5a,
+ 0x45, 0x30, 0x1b, 0x39, 0xa8, 0xc0, 0x00, 0x26, 0x8c, 0x00, 0x00, 0x49,
+ 0x81, 0xc0, 0x00, 0x53, 0x8c, 0x00, 0x03, 0x0d, 0xc0, 0xa1, 0x02, 0x84,
+ 0x00, 0x00, 0x13, 0x9f, 0xc0, 0x01, 0x6e, 0x0b, 0x83, 0x00, 0x00, 0x5a,
+ 0xa8, 0xc0, 0x01, 0xb9, 0x1d, 0x8b, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01,
+ 0xbf, 0x45, 0x8b, 0x00, 0x03, 0x04, 0xc0, 0xc0, 0x90, 0x83, 0x00, 0x01,
+ 0x41, 0xb5, 0xa0, 0xc0, 0x01, 0xb9, 0x15, 0x82, 0x00, 0x00, 0x82, 0xa9,
+ 0xc0, 0x00, 0x4e, 0x82, 0x00, 0x09, 0x11, 0x80, 0xa6, 0xa6, 0x91, 0x70,
+ 0x22, 0x00, 0x00, 0x38, 0x82, 0xc0, 0x00, 0x7b, 0x82, 0x00, 0x0d, 0x0b,
+ 0x75, 0xa0, 0xab, 0x9a, 0x82, 0x41, 0x04, 0x00, 0x00, 0xbb, 0xc0, 0xbe,
+ 0x07, 0x82, 0x00, 0x00, 0xa3, 0xa2, 0xc0, 0x00, 0x15, 0x82, 0x00, 0x00,
+ 0xaa, 0xa9, 0xc0, 0x00, 0x38, 0x82, 0x00, 0x00, 0x73, 0x82, 0xc0, 0x03,
+ 0xbf, 0x66, 0x00, 0x2f, 0x82, 0xc0, 0x00, 0x65, 0x82, 0x00, 0x00, 0x56,
+ 0x83, 0xc0, 0x05, 0x9d, 0x11, 0x00, 0xb2, 0xc0, 0xb2, 0x82, 0x00, 0x00,
+ 0x1d, 0xa2, 0xc0, 0x00, 0xad, 0x82, 0x00, 0x01, 0x11, 0xbf, 0xa9, 0xc0,
+ 0x00, 0x14, 0x82, 0x00, 0x00, 0xac, 0x80, 0xc0, 0x05, 0xb4, 0x04, 0xc0,
+ 0xc0, 0x48, 0x26, 0x82, 0xc0, 0x00, 0x40, 0x82, 0x00, 0x00, 0x84, 0x80,
+ 0xc0, 0x08, 0xb1, 0x0b, 0xc0, 0xc0, 0x91, 0x00, 0xa9, 0xc0, 0x8e, 0x82,
+ 0x00, 0x00, 0x47, 0xa2, 0xc0, 0x00, 0x85, 0x82, 0x00, 0x00, 0x3a, 0x98,
+ 0xc0, 0x11, 0xb3, 0x95, 0x7a, 0x60, 0x45, 0x2a, 0x0f, 0x66, 0xc0, 0xc0,
+ 0xa4, 0x58, 0x20, 0x0b, 0x69, 0xc0, 0xc0, 0xac, 0x82, 0x00, 0x00, 0x1a,
+ 0x80, 0xc0, 0x06, 0xb2, 0x46, 0x00, 0xc0, 0xc0, 0x97, 0x1d, 0x82, 0xc0,
+ 0x00, 0x18, 0x82, 0x00, 0x0c, 0xb0, 0xc0, 0xc0, 0xb7, 0x54, 0x00, 0xc0,
+ 0xc0, 0xbf, 0x3d, 0xa6, 0xc0, 0x67, 0x82, 0x00, 0x14, 0x6d, 0xc0, 0xc0,
+ 0xaf, 0x91, 0x77, 0x5d, 0x42, 0x28, 0x0e, 0x91, 0xc0, 0xc0, 0xb4, 0x70,
+ 0x34, 0x15, 0x05, 0x17, 0x53, 0xb5, 0x87, 0xc0, 0x04, 0x9d, 0x60, 0x2e,
+ 0x16, 0x08, 0x85, 0x00, 0x00, 0x63, 0x98, 0xc0, 0x00, 0x68, 0x83, 0x00,
+ 0x0a, 0x16, 0xc0, 0x6f, 0x05, 0x00, 0x00, 0x09, 0xb5, 0xc0, 0xc0, 0x85,
+ 0x82, 0x00, 0x0a, 0x08, 0x1d, 0x1d, 0x14, 0x02, 0x00, 0x00, 0xc0, 0xc0,
+ 0xbf, 0xa6, 0x81, 0xc0, 0x00, 0xb1, 0x82, 0x00, 0x06, 0x01, 0x1d, 0x1d,
+ 0x15, 0x04, 0x00, 0x00, 0x83, 0xc0, 0x00, 0x41, 0x82, 0x00, 0x03, 0x93,
+ 0xc0, 0xc0, 0x51, 0x83, 0x00, 0x03, 0x5d, 0xbe, 0x6d, 0x0e, 0x83, 0x00,
+ 0x00, 0x4a, 0x85, 0xc0, 0x01, 0xa7, 0x3c, 0x8a, 0x00, 0x00, 0x8b, 0x99,
+ 0xc0, 0x00, 0x87, 0x82, 0x00, 0x01, 0x05, 0x6e, 0x81, 0x00, 0x00, 0x54,
+ 0x80, 0xc0, 0x00, 0x5e, 0x89, 0x00, 0x85, 0xc0, 0x00, 0x8a, 0x89, 0x00,
+ 0x83, 0xc0, 0x00, 0x1a, 0x81, 0x00, 0x01, 0x01, 0xb7, 0x80, 0xc0, 0x00,
+ 0x68, 0x82, 0x00, 0x01, 0x42, 0x39, 0x85, 0x00, 0x00, 0x0f, 0x84, 0xc0,
+ 0x01, 0x8f, 0x0e, 0x84, 0x00, 0x01, 0x12, 0x02, 0x82, 0x00, 0x00, 0xb2,
+ 0x99, 0xc0, 0x00, 0xb8, 0x82, 0x00, 0x06, 0x02, 0x02, 0x0e, 0x31, 0x14,
+ 0x02, 0xa7, 0x80, 0xc0, 0x00, 0x36, 0x89, 0x00, 0x85, 0xc0, 0x00, 0x63,
+ 0x89, 0x00, 0x82, 0xc0, 0x00, 0xb4, 0x82, 0x00, 0x00, 0x1f, 0x81, 0xc0,
+ 0x00, 0x8b, 0x84, 0x00, 0x02, 0x2c, 0x62, 0x3a, 0x82, 0x00, 0x00, 0x12,
+ 0x83, 0xc0, 0x01, 0x99, 0x06, 0x82, 0x00, 0x04, 0x1b, 0x84, 0xb2, 0xb5,
+ 0x01, 0x81, 0x00, 0x00, 0x1a, 0x9a, 0xc0, 0x00, 0xa2, 0x83, 0x00, 0x04,
+ 0x38, 0xb8, 0xc0, 0xbd, 0x8a, 0x80, 0xc0, 0x01, 0xbf, 0x0f, 0x82, 0x00,
+ 0x06, 0x91, 0xb5, 0xb6, 0x9e, 0x58, 0x02, 0x00, 0x85, 0xc0, 0x00, 0x3b,
+ 0x82, 0x00, 0x06, 0x6d, 0xb3, 0xb8, 0x9f, 0x54, 0x00, 0x00, 0x82, 0xc0,
+ 0x00, 0x8e, 0x82, 0x00, 0x00, 0x45, 0x81, 0xc0, 0x00, 0x72, 0x83, 0x00,
+ 0x03, 0x4c, 0xbe, 0xc0, 0xb2, 0x82, 0x00, 0x00, 0x35, 0x82, 0xc0, 0x01,
+ 0xb2, 0x14, 0x82, 0x00, 0x04, 0x4e, 0xba, 0xc0, 0xc0, 0x8d, 0x82, 0x00,
+ 0x00, 0x42, 0x9a, 0xc0, 0x00, 0x7b, 0x82, 0x00, 0x01, 0x07, 0xaf, 0x84,
+ 0xc0, 0x00, 0xa8, 0x82, 0x00, 0x01, 0x0d, 0xbf, 0x81, 0xc0, 0x01, 0x6c,
+ 0x00, 0x85, 0xc0, 0x00, 0x14, 0x82, 0x00, 0x00, 0xa3, 0x81, 0xc0, 0x01,
+ 0x57, 0x00, 0x82, 0xc0, 0x00, 0x68, 0x82, 0x00, 0x00, 0x6b, 0x81, 0xc0,
+ 0x00, 0x4e, 0x82, 0x00, 0x04, 0x16, 0xbb, 0xc0, 0xc0, 0xa7, 0x82, 0x00,
+ 0x00, 0x59, 0x82, 0xc0, 0x00, 0x54, 0x82, 0x00, 0x01, 0x3b, 0xbe, 0x80,
+ 0xc0, 0x00, 0x63, 0x82, 0x00, 0x00, 0x6b, 0x9a, 0xc0, 0x00, 0x52, 0x82,
+ 0x00, 0x00, 0x45, 0x85, 0xc0, 0x00, 0x81, 0x82, 0x00, 0x00, 0x35, 0x82,
+ 0xc0, 0x01, 0xb6, 0x04, 0x84, 0xc0, 0x00, 0xac, 0x82, 0x00, 0x01, 0x0b,
+ 0xbe, 0x81, 0xc0, 0x01, 0xa2, 0x00, 0x82, 0xc0, 0x00, 0x42, 0x82, 0x00,
+ 0x00, 0x91, 0x81, 0xc0, 0x00, 0x28, 0x82, 0x00, 0x00, 0x6f, 0x80, 0xc0,
+ 0x00, 0x78, 0x82, 0x00, 0x00, 0x8a, 0x81, 0xc0, 0x01, 0xab, 0x04, 0x81,
+ 0x00, 0x01, 0x08, 0xac, 0x81, 0xc0, 0x00, 0x3a, 0x82, 0x00, 0x00, 0x93,
+ 0x9a, 0xc0, 0x00, 0x29, 0x82, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x00, 0x59,
+ 0x82, 0x00, 0x00, 0x5f, 0x83, 0xc0, 0x00, 0xbd, 0x84, 0xc0, 0x00, 0x85,
+ 0x82, 0x00, 0x00, 0x31, 0x82, 0xc0, 0x01, 0xbf, 0xa8, 0x82, 0xc0, 0x00,
+ 0x1a, 0x82, 0x00, 0x00, 0xb5, 0x80, 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00,
+ 0x00, 0xaf, 0x80, 0xc0, 0x00, 0x40, 0x81, 0x00, 0x01, 0x04, 0xb8, 0x81,
+ 0xc0, 0x00, 0x6b, 0x82, 0x00, 0x00, 0x51, 0x81, 0xc0, 0x01, 0xbf, 0x11,
+ 0x81, 0x00, 0x01, 0x02, 0xb8, 0x99, 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00,
+ 0x00, 0xa8, 0x85, 0xc0, 0x00, 0x32, 0x82, 0x00, 0x00, 0x88, 0x86, 0xc0,
+ 0x01, 0xa3, 0x4a, 0x80, 0xc0, 0x00, 0x5e, 0x82, 0x00, 0x00, 0x57, 0x88,
+ 0xc0, 0x00, 0xb4, 0x82, 0x00, 0x00, 0x1d, 0x81, 0xc0, 0x00, 0x9b, 0x82,
+ 0x00, 0x00, 0x25, 0x80, 0xc0, 0x01, 0xbc, 0x0b, 0x81, 0x00, 0x00, 0x2f,
+ 0x82, 0xc0, 0x00, 0x31, 0x82, 0x00, 0x00, 0x8f, 0x81, 0xc0, 0x00, 0xa8,
+ 0x82, 0x00, 0x00, 0x23, 0x9a, 0xc0, 0x00, 0x99, 0x82, 0x00, 0x01, 0x10,
+ 0xbf, 0x84, 0xc0, 0x01, 0xbe, 0x0b, 0x82, 0x00, 0x00, 0xaf, 0x85, 0xc0,
+ 0x02, 0xb3, 0x1d, 0x60, 0x80, 0xc0, 0x00, 0x36, 0x82, 0x00, 0x00, 0x7f,
+ 0x88, 0xc0, 0x00, 0x8e, 0x82, 0x00, 0x00, 0x43, 0x81, 0xc0, 0x00, 0x75,
+ 0x82, 0x00, 0x00, 0x57, 0x80, 0xc0, 0x00, 0x91, 0x82, 0x00, 0x00, 0x62,
+ 0x82, 0xc0, 0x00, 0x15, 0x82, 0x00, 0x00, 0xaf, 0x81, 0xc0, 0x00, 0x7f,
+ 0x82, 0x00, 0x00, 0x4b, 0x9a, 0xc0, 0x00, 0x6f, 0x82, 0x00, 0x00, 0x39,
+ 0x85, 0xc0, 0x00, 0xa3, 0x82, 0x00, 0x01, 0x0c, 0xbf, 0x84, 0xc0, 0x07,
+ 0xb8, 0x33, 0x08, 0xb2, 0xc0, 0xc0, 0xbf, 0x0f, 0x82, 0x00, 0x00, 0xa6,
+ 0x88, 0xc0, 0x00, 0x68, 0x82, 0x00, 0x00, 0x69, 0x81, 0xc0, 0x00, 0x4e,
+ 0x82, 0x00, 0x00, 0x81, 0x80, 0xc0, 0x00, 0x5a, 0x82, 0x00, 0x00, 0x8f,
+ 0x82, 0xc0, 0x00, 0x05, 0x82, 0x00, 0x00, 0xb7, 0x81, 0xc0, 0x00, 0x55,
+ 0x82, 0x00, 0x00, 0x73, 0x9a, 0xc0, 0x00, 0x47, 0x82, 0x00, 0x00, 0x62,
+ 0x85, 0xc0, 0x00, 0x7b, 0x82, 0x00, 0x00, 0x26, 0x84, 0xc0, 0x03, 0xa9,
+ 0x25, 0x00, 0x54, 0x80, 0xc0, 0x00, 0xa9, 0x82, 0x00, 0x01, 0x0c, 0xbf,
+ 0x88, 0xc0, 0x00, 0x42, 0x82, 0x00, 0x00, 0x8f, 0x81, 0xc0, 0x00, 0x28,
+ 0x82, 0x00, 0x00, 0xa9, 0x80, 0xc0, 0x00, 0x2b, 0x82, 0x00, 0x00, 0xb4,
+ 0x82, 0xc0, 0x00, 0x14, 0x82, 0x00, 0x00, 0x97, 0x81, 0xc0, 0x00, 0x2c,
+ 0x82, 0x00, 0x00, 0x9c, 0x9a, 0xc0, 0x00, 0x1e, 0x82, 0x00, 0x00, 0x8b,
+ 0x85, 0xc0, 0x00, 0x51, 0x82, 0x00, 0x01, 0x12, 0xbb, 0x81, 0xc0, 0x05,
+ 0xb8, 0x70, 0x10, 0x00, 0x03, 0xa9, 0x80, 0xc0, 0x00, 0x7f, 0x82, 0x00,
+ 0x00, 0x2f, 0x88, 0xc0, 0x01, 0xbf, 0x19, 0x82, 0x00, 0x00, 0xb2, 0x80,
+ 0xc0, 0x01, 0xbb, 0x05, 0x81, 0x00, 0x01, 0x12, 0xbf, 0x80, 0xc0, 0x00,
+ 0x0e, 0x82, 0x00, 0x01, 0x7b, 0xbd, 0x81, 0xc0, 0x00, 0x41, 0x82, 0x00,
+ 0x05, 0x3e, 0xbf, 0xc0, 0xc0, 0xaf, 0x04, 0x81, 0x00, 0x01, 0x06, 0xbc,
+ 0x99, 0xc0, 0x00, 0xb5, 0x83, 0x00, 0x00, 0xb3, 0x84, 0xc0, 0x01, 0xbf,
+ 0x16, 0x83, 0x00, 0x05, 0x2e, 0x71, 0x79, 0x63, 0x48, 0x0d, 0x80, 0x00,
+ 0x00, 0x46, 0x81, 0xc0, 0x00, 0x42, 0x82, 0x00, 0x00, 0x42, 0x88, 0xc0,
+ 0x00, 0x9f, 0x82, 0x00, 0x01, 0x07, 0xbf, 0x80, 0xc0, 0x00, 0x9b, 0x82,
+ 0x00, 0x00, 0x3b, 0x81, 0xc0, 0x00, 0x12, 0x83, 0x00, 0x06, 0x0b, 0x21,
+ 0xb2, 0xc0, 0xc0, 0x97, 0x02, 0x82, 0x00, 0x03, 0x42, 0x97, 0xa7, 0x49,
+ 0x82, 0x00, 0x00, 0x18, 0x9a, 0xc0, 0x00, 0x8e, 0x82, 0x00, 0x00, 0x1d,
+ 0x84, 0xc0, 0x01, 0xbd, 0x6c, 0x8d, 0x00, 0x05, 0x9f, 0xc0, 0xc0, 0xbf,
+ 0x8e, 0x07, 0x82, 0x00, 0x01, 0x13, 0xb6, 0x86, 0xc0, 0x01, 0xb6, 0x40,
+ 0x83, 0x00, 0x00, 0x91, 0x80, 0xc0, 0x00, 0x75, 0x82, 0x00, 0x00, 0x64,
+ 0x81, 0xc0, 0x00, 0x60, 0x82, 0x00, 0x02, 0x2f, 0x7e, 0xbb, 0x81, 0xc0,
+ 0x01, 0x75, 0x05, 0x8b, 0x00, 0x00, 0x88, 0x99, 0xc0, 0x00, 0x65, 0x82,
+ 0x00, 0x00, 0x45, 0x84, 0xc0, 0x00, 0x40, 0x8d, 0x00, 0x00, 0x38, 0x80,
+ 0xc0, 0x00, 0x6d, 0x85, 0x00, 0x00, 0x1a, 0x86, 0xc0, 0x00, 0x13, 0x84,
+ 0x00, 0x04, 0x02, 0xa1, 0xc0, 0xc0, 0x4e, 0x82, 0x00, 0x00, 0x8e, 0x81,
+ 0xc0, 0x05, 0xbe, 0x76, 0x29, 0x10, 0x52, 0xa0, 0x85, 0xc0, 0x05, 0xa4,
+ 0x5a, 0x2b, 0x11, 0x0a, 0x04, 0x87, 0x00, 0x00, 0x92, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xd6, 0xc0, 0x09,
+ 0xc5, 0xd4, 0xe2, 0xec, 0xf6, 0xfd, 0xfe, 0xf8, 0xe7, 0xc6, 0x95, 0xc0,
+ 0x03, 0xce, 0xe7, 0xfa, 0xdd, 0x81, 0xc0, 0x01, 0xd4, 0xca, 0x80, 0xc0,
+ 0x01, 0xc1, 0xca, 0xd1, 0xc0, 0x01, 0xc2, 0xea, 0x86, 0xff, 0x00, 0xf1,
+ 0x92, 0xc0, 0x02, 0xcf, 0xdf, 0xef, 0x80, 0xff, 0x0c, 0xf9, 0xc0, 0xc0,
+ 0xc5, 0xed, 0xff, 0xed, 0xc0, 0xc0, 0xc5, 0xef, 0xfe, 0xcd, 0xd0, 0xc0,
+ 0x0b, 0xec, 0xff, 0xff, 0xef, 0xdf, 0xd3, 0xc9, 0xc4, 0xc1, 0xc5, 0xda,
+ 0xfb, 0x91, 0xc0, 0x13, 0xd5, 0xfe, 0xff, 0xff, 0xf9, 0xda, 0xc7, 0xf7,
+ 0xc0, 0xc7, 0xf6, 0xfa, 0xff, 0xe2, 0xc0, 0xcb, 0xf7, 0xff, 0xfe, 0xce,
+ 0xcf, 0xc0, 0x0c, 0xd2, 0xfe, 0xf3, 0xe4, 0xc5, 0xc0, 0xcb, 0xe7, 0xca,
+ 0xc0, 0xc0, 0xd1, 0xdc, 0x8b, 0xc0, 0x02, 0xc5, 0xe6, 0xcb, 0x80, 0xc0,
+ 0x12, 0xf1, 0xff, 0xfd, 0xe0, 0xc2, 0xc0, 0xd2, 0xe6, 0xc6, 0xf6, 0xd7,
+ 0xe0, 0xfe, 0xc7, 0xd0, 0xfc, 0xff, 0xff, 0xd6, 0xbc, 0xc0, 0x02, 0xc5,
+ 0xe6, 0xcb, 0x93, 0xc0, 0x06, 0xcf, 0xf4, 0xd1, 0xd2, 0xde, 0xe6, 0xd5,
+ 0x8c, 0xc0, 0x01, 0xef, 0xed, 0x81, 0xc0, 0x02, 0xf8, 0xe5, 0xc6, 0x80,
+ 0xc0, 0x0b, 0xef, 0xd1, 0xf3, 0xd8, 0xc4, 0xfa, 0xe3, 0xcf, 0xfc, 0xe6,
+ 0xfc, 0xdf, 0xbd, 0xc0, 0x01, 0xef, 0xed, 0x93, 0xc0, 0x05, 0xc9, 0xfb,
+ 0xf8, 0xef, 0xe1, 0xcf, 0x8b, 0xc0, 0x05, 0xdf, 0xfa, 0xff, 0xff, 0xf9,
+ 0xc5, 0x85, 0xc0, 0x0b, 0xd4, 0xf3, 0xeb, 0xe0, 0xc0, 0xe7, 0xfb, 0xd0,
+ 0xfb, 0xda, 0xea, 0xec, 0xbb, 0xc0, 0x05, 0xdf, 0xfa, 0xff, 0xff, 0xf9,
+ 0xc5, 0x8f, 0xc0, 0x06, 0xcc, 0xf4, 0xfa, 0xfe, 0xe8, 0xcd, 0xc2, 0x82,
+ 0xc0, 0x0f, 0xcf, 0xef, 0xfd, 0xde, 0xc0, 0xc0, 0xcf, 0xef, 0xfd, 0xde,
+ 0xd6, 0xfb, 0xfd, 0xff, 0xff, 0xd8, 0x85, 0xc0, 0x0c, 0xc3, 0xf8, 0xf7,
+ 0xec, 0xc0, 0xd0, 0xff, 0xe4, 0xf8, 0xd8, 0xdd, 0xfa, 0xc5, 0x80, 0xc0,
+ 0x0b, 0xce, 0xea, 0xfb, 0xd7, 0xc0, 0xc0, 0xc3, 0xda, 0xc1, 0xc0, 0xde,
+ 0xf3, 0x80, 0xc0, 0x03, 0xce, 0xea, 0xfb, 0xd7, 0x80, 0xc0, 0x03, 0xc1,
+ 0xd8, 0xf3, 0xf2, 0x81, 0xc0, 0x03, 0xc7, 0xe7, 0xfb, 0xf4, 0x89, 0xc0,
+ 0x11, 0xc7, 0xe7, 0xfb, 0xf4, 0xc0, 0xc0, 0xc3, 0xda, 0xc1, 0xc0, 0xde,
+ 0xf3, 0xd6, 0xfb, 0xfd, 0xff, 0xff, 0xd8, 0x91, 0xc0, 0x00, 0xd2, 0x81,
+ 0xff, 0x14, 0xfe, 0xee, 0xd7, 0xc1, 0xc0, 0xda, 0xfe, 0xf3, 0xe3, 0xf5,
+ 0xc0, 0xda, 0xfe, 0xf3, 0xe3, 0xf5, 0xc2, 0xc7, 0xf8, 0xd3, 0xc4, 0x86,
+ 0xc0, 0x4e, 0xe5, 0xff, 0xf8, 0xc4, 0xc4, 0xf7, 0xfb, 0xf6, 0xda, 0xce,
+ 0xfe, 0xd8, 0xc0, 0xc0, 0xc3, 0xe8, 0xf8, 0xdf, 0xfa, 0xc9, 0xc0, 0xc0,
+ 0xec, 0xe9, 0xc1, 0xe7, 0xff, 0xef, 0xc0, 0xc3, 0xe8, 0xf8, 0xdf, 0xfa,
+ 0xc9, 0xc0, 0xc0, 0xc6, 0xf0, 0xff, 0xf2, 0xdc, 0xf6, 0xc0, 0xc0, 0xd2,
+ 0xfb, 0xe5, 0xd4, 0xec, 0xc0, 0xc4, 0xe0, 0xe0, 0xc2, 0xe4, 0xfa, 0xcb,
+ 0xc0, 0xcf, 0xe1, 0xd2, 0xfb, 0xe5, 0xd4, 0xec, 0xc0, 0xc0, 0xec, 0xe9,
+ 0xc1, 0xe7, 0xff, 0xef, 0xc2, 0xc7, 0xf8, 0xd3, 0xc4, 0x91, 0xc0, 0x18,
+ 0xc3, 0xf8, 0xfb, 0xce, 0xc6, 0xcf, 0xdb, 0xf0, 0xff, 0xea, 0xd2, 0xff,
+ 0xe3, 0xc1, 0xec, 0xfc, 0xd2, 0xff, 0xe3, 0xc1, 0xec, 0xfc, 0xc6, 0xf5,
+ 0xea, 0x87, 0xc0, 0x4d, 0xd1, 0xff, 0xfe, 0xd0, 0xc0, 0xe9, 0xff, 0xff,
+ 0xde, 0xc1, 0xf5, 0xf5, 0xc0, 0xc0, 0xc6, 0xf3, 0xdf, 0xc2, 0xec, 0xfa,
+ 0xc7, 0xc0, 0xd4, 0xf9, 0xc4, 0xe7, 0xf0, 0xfd, 0xc8, 0xc6, 0xf3, 0xdf,
+ 0xc2, 0xec, 0xfa, 0xc7, 0xc0, 0xc5, 0xf6, 0xfb, 0xd9, 0xc6, 0xfa, 0xf2,
+ 0xc0, 0xcf, 0xfe, 0xe1, 0xd5, 0xe2, 0xc3, 0xc9, 0xf7, 0xf8, 0xd6, 0xf2,
+ 0xff, 0xfc, 0xc4, 0xd5, 0xfe, 0xff, 0xfe, 0xe1, 0xd5, 0xe2, 0xc3, 0xc0,
+ 0xd4, 0xf9, 0xc4, 0xe7, 0xf0, 0xfd, 0xc8, 0xc6, 0xf5, 0xea, 0x93, 0xc0,
+ 0x02, 0xe2, 0xff, 0xd0, 0x81, 0xc0, 0x14, 0xca, 0xff, 0xfb, 0xf4, 0xe5,
+ 0xc0, 0xc0, 0xf9, 0xee, 0xf4, 0xe5, 0xc0, 0xc0, 0xf9, 0xf5, 0xeb, 0xff,
+ 0xcd, 0xc0, 0xcb, 0xc4, 0x83, 0xc0, 0x51, 0xc4, 0xf8, 0xff, 0xe3, 0xc0,
+ 0xd8, 0xff, 0xff, 0xe4, 0xc0, 0xd9, 0xff, 0xda, 0xc0, 0xc0, 0xee, 0xd6,
+ 0xc0, 0xe3, 0xfd, 0xd1, 0xc0, 0xca, 0xf3, 0xd9, 0xde, 0xe5, 0xf6, 0xe3,
+ 0xc0, 0xee, 0xd6, 0xc0, 0xe3, 0xfd, 0xd1, 0xc0, 0xca, 0xe9, 0xfa, 0xca,
+ 0xc0, 0xee, 0xff, 0xdc, 0xc0, 0xf1, 0xff, 0xe0, 0xca, 0xc0, 0xd4, 0xef,
+ 0xf1, 0xcb, 0xf6, 0xd9, 0xf2, 0xde, 0xda, 0xef, 0xfa, 0xfc, 0xff, 0xe0,
+ 0xca, 0xc0, 0xd4, 0xc4, 0xf3, 0xd9, 0xde, 0xe5, 0xf6, 0xe3, 0xc7, 0xeb,
+ 0xff, 0xcd, 0xc0, 0xcb, 0xc4, 0x90, 0xc0, 0x1b, 0xf9, 0xff, 0xd7, 0xc2,
+ 0xc3, 0xcd, 0xe0, 0xfb, 0xff, 0xdb, 0xfd, 0xcb, 0xc0, 0xc0, 0xfc, 0xdf,
+ 0xff, 0xcb, 0xc0, 0xc0, 0xfc, 0xdf, 0xff, 0xff, 0xc8, 0xda, 0xeb, 0xc1,
+ 0x83, 0xc0, 0x51, 0xea, 0xff, 0xf6, 0xc2, 0xc4, 0xfc, 0xff, 0xec, 0xc0,
+ 0xc0, 0xf0, 0xff, 0xc7, 0xc0, 0xc2, 0xff, 0xd2, 0xe7, 0xed, 0xf2, 0xd6,
+ 0xe3, 0xe0, 0xfe, 0xd7, 0xed, 0xdd, 0xff, 0xc9, 0xca, 0xff, 0xc9, 0xe7,
+ 0xed, 0xf2, 0xd6, 0xe3, 0xe0, 0xfc, 0xd3, 0xc0, 0xe5, 0xfb, 0xfd, 0xc4,
+ 0xc7, 0xfd, 0xff, 0xcd, 0xc7, 0xe4, 0xe8, 0xfb, 0xd4, 0xf8, 0xd7, 0xce,
+ 0xf4, 0xe2, 0xd7, 0xfd, 0xcf, 0xfd, 0xff, 0xcd, 0xc7, 0xe4, 0xe8, 0xc0,
+ 0xfe, 0xd7, 0xed, 0xdd, 0xff, 0xc9, 0xcb, 0xfc, 0xff, 0xc8, 0xda, 0xeb,
+ 0xc1, 0x90, 0xc0, 0x00, 0xf6, 0x83, 0xff, 0x0e, 0xf7, 0xd4, 0xc0, 0xef,
+ 0xcb, 0xc5, 0xde, 0xf3, 0xe3, 0xf4, 0xcb, 0xc5, 0xde, 0xf3, 0xe3, 0x80,
+ 0xff, 0x01, 0xec, 0xc2, 0x84, 0xc0, 0x2e, 0xf8, 0xff, 0xd0, 0xc0, 0xd0,
+ 0xff, 0xf2, 0xc2, 0xc0, 0xc0, 0xfc, 0xff, 0xc9, 0xd1, 0xf4, 0xff, 0xff,
+ 0xf8, 0xc5, 0xfb, 0xff, 0xea, 0xc0, 0xfa, 0xfb, 0xc6, 0xf6, 0xff, 0xdc,
+ 0xec, 0xf8, 0xff, 0xf8, 0xc5, 0xfb, 0xff, 0xea, 0xc0, 0xf6, 0xc8, 0xe5,
+ 0xf3, 0xe5, 0xe9, 0xe1, 0xd5, 0xf6, 0x80, 0xff, 0x0b, 0xec, 0xc2, 0xfb,
+ 0xff, 0xdc, 0xc0, 0xec, 0xf6, 0xd1, 0xea, 0xff, 0xd9, 0x81, 0xff, 0x09,
+ 0xec, 0xc2, 0xc0, 0xfa, 0xfb, 0xc6, 0xf6, 0xff, 0xdc, 0xec, 0x80, 0xff,
+ 0x01, 0xec, 0xc2, 0x91, 0xc0, 0x06, 0xcb, 0xed, 0xfb, 0xfe, 0xf7, 0xe8,
+ 0xd2, 0x80, 0xc0, 0x0e, 0xc9, 0xf3, 0xfc, 0xe5, 0xc3, 0xc0, 0xc9, 0xf3,
+ 0xfc, 0xe5, 0xc3, 0xc0, 0xed, 0xf9, 0xdd, 0x86, 0xc0, 0x06, 0xe3, 0xe9,
+ 0xc0, 0xc0, 0xc6, 0xf4, 0xc6, 0x80, 0xc0, 0x44, 0xfa, 0xff, 0xff, 0xfa,
+ 0xcf, 0xd3, 0xf7, 0xcb, 0xc0, 0xfd, 0xeb, 0xc1, 0xc0, 0xe7, 0xd6, 0xc0,
+ 0xfd, 0xff, 0xe7, 0xc2, 0xd3, 0xf7, 0xcb, 0xc0, 0xfd, 0xeb, 0xc1, 0xc0,
+ 0xd8, 0xfb, 0xe3, 0xc6, 0xfb, 0xf2, 0xca, 0xc0, 0xd3, 0xf9, 0xf8, 0xdf,
+ 0xc1, 0xc0, 0xe3, 0xe7, 0xc0, 0xc0, 0xfb, 0xd8, 0xc0, 0xfb, 0xff, 0xeb,
+ 0xd9, 0xf9, 0xf8, 0xdf, 0xc1, 0xc0, 0xc0, 0xe7, 0xd6, 0xc0, 0xfd, 0xff,
+ 0xe7, 0xc2, 0xed, 0xf9, 0xdd, 0xb5, 0xc0, 0x01, 0xc1, 0xc1, 0x85, 0xc0,
+ 0x03, 0xdb, 0xfb, 0xea, 0xc7, 0x82, 0xc0, 0x00, 0xcb, 0x83, 0xc0, 0x01,
+ 0xd3, 0xcf, 0x83, 0xc0, 0x00, 0xcb, 0x82, 0xc0, 0x03, 0xc1, 0xe9, 0xe8,
+ 0xc2, 0x89, 0xc0, 0x04, 0xc2, 0xc0, 0xc0, 0xcf, 0xcc, 0x88, 0xc0, 0x01,
+ 0xd3, 0xcf, 0xe1, 0xc0, 0x03, 0xc4, 0xf0, 0xf5, 0xc1, 0xff, 0xc0, 0x03,
+ 0xc1, 0xf1, 0xfe, 0xcd, 0xff, 0xc0, 0x03, 0xc0, 0xde, 0xff, 0xd8, 0xff,
+ 0xc0, 0x03, 0xc0, 0xc0, 0xef, 0xd7, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0xff, 0xc0, 0xc8, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x8e, 0xc0,
+ 0x08, 0xb2, 0x98, 0x83, 0x6e, 0x5a, 0x45, 0x30, 0x1b, 0x39, 0xa8, 0xc0,
+ 0x00, 0x26, 0x8c, 0x00, 0x00, 0x49, 0x81, 0xc0, 0x00, 0x53, 0x8c, 0x00,
+ 0x03, 0x0d, 0xc0, 0xa1, 0x02, 0x84, 0x00, 0x00, 0x13, 0x9f, 0xc0, 0x01,
+ 0x6e, 0x0b, 0x83, 0x00, 0x00, 0x5a, 0xa8, 0xc0, 0x01, 0xb9, 0x1d, 0x8b,
+ 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0xbf, 0x45, 0x8b, 0x00, 0x03, 0x04,
+ 0xc0, 0xc0, 0x90, 0x83, 0x00, 0x01, 0x41, 0xb5, 0xa0, 0xc0, 0x01, 0xb9,
+ 0x15, 0x82, 0x00, 0x00, 0x82, 0xa9, 0xc0, 0x00, 0x4e, 0x82, 0x00, 0x09,
+ 0x11, 0x80, 0xa6, 0xa6, 0x91, 0x70, 0x22, 0x00, 0x00, 0x38, 0x82, 0xc0,
+ 0x00, 0x7b, 0x82, 0x00, 0x0d, 0x0b, 0x75, 0xa0, 0xab, 0x9a, 0x82, 0x41,
+ 0x04, 0x00, 0x00, 0xbb, 0xc0, 0xbe, 0x07, 0x82, 0x00, 0x00, 0xa3, 0xa2,
+ 0xc0, 0x00, 0x15, 0x82, 0x00, 0x00, 0xaa, 0xa9, 0xc0, 0x00, 0x38, 0x82,
+ 0x00, 0x00, 0x73, 0x82, 0xc0, 0x03, 0xbf, 0x66, 0x00, 0x2f, 0x82, 0xc0,
+ 0x00, 0x65, 0x82, 0x00, 0x00, 0x56, 0x83, 0xc0, 0x05, 0x9d, 0x11, 0x00,
+ 0xb2, 0xc0, 0xb2, 0x82, 0x00, 0x00, 0x1d, 0xa2, 0xc0, 0x00, 0xad, 0x82,
+ 0x00, 0x01, 0x11, 0xbf, 0xa9, 0xc0, 0x00, 0x14, 0x82, 0x00, 0x00, 0xac,
+ 0x80, 0xc0, 0x05, 0xb4, 0x04, 0xc0, 0xc0, 0x48, 0x26, 0x82, 0xc0, 0x00,
+ 0x40, 0x82, 0x00, 0x00, 0x84, 0x80, 0xc0, 0x08, 0xb1, 0x0b, 0xc0, 0xc0,
+ 0x91, 0x00, 0xa9, 0xc0, 0x8e, 0x82, 0x00, 0x00, 0x47, 0xa2, 0xc0, 0x00,
+ 0x85, 0x82, 0x00, 0x00, 0x3a, 0x98, 0xc0, 0x11, 0xb3, 0x95, 0x7a, 0x60,
+ 0x45, 0x2a, 0x0f, 0x66, 0xc0, 0xc0, 0xa4, 0x58, 0x20, 0x0b, 0x69, 0xc0,
+ 0xc0, 0xac, 0x82, 0x00, 0x00, 0x1a, 0x80, 0xc0, 0x06, 0xb2, 0x46, 0x00,
+ 0xc0, 0xc0, 0x97, 0x1d, 0x82, 0xc0, 0x00, 0x18, 0x82, 0x00, 0x0c, 0xb0,
+ 0xc0, 0xc0, 0xb7, 0x54, 0x00, 0xc0, 0xc0, 0xbf, 0x3d, 0xa6, 0xc0, 0x67,
+ 0x82, 0x00, 0x14, 0x6d, 0xc0, 0xc0, 0xaf, 0x91, 0x77, 0x5d, 0x42, 0x28,
+ 0x0e, 0x91, 0xc0, 0xc0, 0xb4, 0x70, 0x34, 0x15, 0x05, 0x17, 0x53, 0xb5,
+ 0x87, 0xc0, 0x04, 0x9d, 0x60, 0x2e, 0x16, 0x08, 0x85, 0x00, 0x00, 0x63,
+ 0x98, 0xc0, 0x00, 0x68, 0x83, 0x00, 0x0a, 0x16, 0xc0, 0x6f, 0x05, 0x00,
+ 0x00, 0x09, 0xb5, 0xc0, 0xc0, 0x85, 0x82, 0x00, 0x0a, 0x08, 0x1d, 0x1d,
+ 0x14, 0x02, 0x00, 0x00, 0xc0, 0xc0, 0xbf, 0xa6, 0x81, 0xc0, 0x00, 0xb1,
+ 0x82, 0x00, 0x06, 0x01, 0x1d, 0x1d, 0x15, 0x04, 0x00, 0x00, 0x83, 0xc0,
+ 0x00, 0x41, 0x82, 0x00, 0x03, 0x93, 0xc0, 0xc0, 0x51, 0x83, 0x00, 0x03,
+ 0x5d, 0xbe, 0x6d, 0x0e, 0x83, 0x00, 0x00, 0x4a, 0x85, 0xc0, 0x01, 0xa7,
+ 0x3c, 0x8a, 0x00, 0x00, 0x8b, 0x99, 0xc0, 0x00, 0x87, 0x82, 0x00, 0x01,
+ 0x05, 0x6e, 0x81, 0x00, 0x00, 0x54, 0x80, 0xc0, 0x00, 0x5e, 0x89, 0x00,
+ 0x85, 0xc0, 0x00, 0x8a, 0x89, 0x00, 0x83, 0xc0, 0x00, 0x1a, 0x81, 0x00,
+ 0x01, 0x01, 0xb7, 0x80, 0xc0, 0x00, 0x68, 0x82, 0x00, 0x01, 0x42, 0x39,
+ 0x85, 0x00, 0x00, 0x0f, 0x84, 0xc0, 0x01, 0x8f, 0x0e, 0x84, 0x00, 0x01,
+ 0x12, 0x02, 0x82, 0x00, 0x00, 0xb2, 0x99, 0xc0, 0x00, 0xb8, 0x82, 0x00,
+ 0x06, 0x02, 0x02, 0x0e, 0x31, 0x14, 0x02, 0xa7, 0x80, 0xc0, 0x00, 0x36,
+ 0x89, 0x00, 0x85, 0xc0, 0x00, 0x63, 0x89, 0x00, 0x82, 0xc0, 0x00, 0xb4,
+ 0x82, 0x00, 0x00, 0x1f, 0x81, 0xc0, 0x00, 0x8b, 0x84, 0x00, 0x02, 0x2c,
+ 0x62, 0x3a, 0x82, 0x00, 0x00, 0x12, 0x83, 0xc0, 0x01, 0x99, 0x06, 0x82,
+ 0x00, 0x04, 0x1b, 0x84, 0xb2, 0xb5, 0x01, 0x81, 0x00, 0x00, 0x1a, 0x9a,
+ 0xc0, 0x00, 0xa2, 0x83, 0x00, 0x04, 0x38, 0xb8, 0xc0, 0xbd, 0x8a, 0x80,
+ 0xc0, 0x01, 0xbf, 0x0f, 0x82, 0x00, 0x06, 0x91, 0xb5, 0xb6, 0x9e, 0x58,
+ 0x02, 0x00, 0x85, 0xc0, 0x00, 0x3b, 0x82, 0x00, 0x06, 0x6d, 0xb3, 0xb8,
+ 0x9f, 0x54, 0x00, 0x00, 0x82, 0xc0, 0x00, 0x8e, 0x82, 0x00, 0x00, 0x45,
+ 0x81, 0xc0, 0x00, 0x72, 0x83, 0x00, 0x03, 0x4c, 0xbe, 0xc0, 0xb2, 0x82,
+ 0x00, 0x00, 0x35, 0x82, 0xc0, 0x01, 0xb2, 0x14, 0x82, 0x00, 0x04, 0x4e,
+ 0xba, 0xc0, 0xc0, 0x8d, 0x82, 0x00, 0x00, 0x42, 0x9a, 0xc0, 0x00, 0x7b,
+ 0x82, 0x00, 0x01, 0x07, 0xaf, 0x84, 0xc0, 0x00, 0xa8, 0x82, 0x00, 0x01,
+ 0x0d, 0xbf, 0x81, 0xc0, 0x01, 0x6c, 0x00, 0x85, 0xc0, 0x00, 0x14, 0x82,
+ 0x00, 0x00, 0xa3, 0x81, 0xc0, 0x01, 0x57, 0x00, 0x82, 0xc0, 0x00, 0x68,
+ 0x82, 0x00, 0x00, 0x6b, 0x81, 0xc0, 0x00, 0x4e, 0x82, 0x00, 0x04, 0x16,
+ 0xbb, 0xc0, 0xc0, 0xa7, 0x82, 0x00, 0x00, 0x59, 0x82, 0xc0, 0x00, 0x54,
+ 0x82, 0x00, 0x01, 0x3b, 0xbe, 0x80, 0xc0, 0x00, 0x63, 0x82, 0x00, 0x00,
+ 0x6b, 0x9a, 0xc0, 0x00, 0x52, 0x82, 0x00, 0x00, 0x45, 0x85, 0xc0, 0x00,
+ 0x81, 0x82, 0x00, 0x00, 0x35, 0x82, 0xc0, 0x01, 0xb6, 0x04, 0x84, 0xc0,
+ 0x00, 0xac, 0x82, 0x00, 0x01, 0x0b, 0xbe, 0x81, 0xc0, 0x01, 0xa2, 0x00,
+ 0x82, 0xc0, 0x00, 0x42, 0x82, 0x00, 0x00, 0x91, 0x81, 0xc0, 0x00, 0x28,
+ 0x82, 0x00, 0x00, 0x6f, 0x80, 0xc0, 0x00, 0x78, 0x82, 0x00, 0x00, 0x8a,
+ 0x81, 0xc0, 0x01, 0xab, 0x04, 0x81, 0x00, 0x01, 0x08, 0xac, 0x81, 0xc0,
+ 0x00, 0x3a, 0x82, 0x00, 0x00, 0x93, 0x9a, 0xc0, 0x00, 0x29, 0x82, 0x00,
+ 0x00, 0x79, 0x85, 0xc0, 0x00, 0x59, 0x82, 0x00, 0x00, 0x5f, 0x83, 0xc0,
+ 0x00, 0xbd, 0x84, 0xc0, 0x00, 0x85, 0x82, 0x00, 0x00, 0x31, 0x82, 0xc0,
+ 0x01, 0xbf, 0xa8, 0x82, 0xc0, 0x00, 0x1a, 0x82, 0x00, 0x00, 0xb5, 0x80,
+ 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00, 0x00, 0xaf, 0x80, 0xc0, 0x00, 0x40,
+ 0x81, 0x00, 0x01, 0x04, 0xb8, 0x81, 0xc0, 0x00, 0x6b, 0x82, 0x00, 0x00,
+ 0x51, 0x81, 0xc0, 0x01, 0xbf, 0x11, 0x81, 0x00, 0x01, 0x02, 0xb8, 0x99,
+ 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00, 0x00, 0xa8, 0x85, 0xc0, 0x00, 0x32,
+ 0x82, 0x00, 0x00, 0x88, 0x86, 0xc0, 0x01, 0xa3, 0x4a, 0x80, 0xc0, 0x00,
+ 0x5e, 0x82, 0x00, 0x00, 0x57, 0x88, 0xc0, 0x00, 0xb4, 0x82, 0x00, 0x00,
+ 0x1d, 0x81, 0xc0, 0x00, 0x9b, 0x82, 0x00, 0x00, 0x25, 0x80, 0xc0, 0x01,
+ 0xbc, 0x0b, 0x81, 0x00, 0x00, 0x2f, 0x82, 0xc0, 0x00, 0x31, 0x82, 0x00,
+ 0x00, 0x8f, 0x81, 0xc0, 0x00, 0xa8, 0x82, 0x00, 0x00, 0x23, 0x9a, 0xc0,
+ 0x00, 0x99, 0x82, 0x00, 0x01, 0x10, 0xbf, 0x84, 0xc0, 0x01, 0xbe, 0x0b,
+ 0x82, 0x00, 0x00, 0xaf, 0x85, 0xc0, 0x02, 0xb3, 0x1d, 0x60, 0x80, 0xc0,
+ 0x00, 0x36, 0x82, 0x00, 0x00, 0x7f, 0x88, 0xc0, 0x00, 0x8e, 0x82, 0x00,
+ 0x00, 0x43, 0x81, 0xc0, 0x00, 0x75, 0x82, 0x00, 0x00, 0x57, 0x80, 0xc0,
+ 0x00, 0x91, 0x82, 0x00, 0x00, 0x62, 0x82, 0xc0, 0x00, 0x15, 0x82, 0x00,
+ 0x00, 0xaf, 0x81, 0xc0, 0x00, 0x7f, 0x82, 0x00, 0x00, 0x4b, 0x9a, 0xc0,
+ 0x00, 0x6f, 0x82, 0x00, 0x00, 0x39, 0x85, 0xc0, 0x00, 0xa3, 0x82, 0x00,
+ 0x01, 0x0c, 0xbf, 0x84, 0xc0, 0x07, 0xb8, 0x33, 0x08, 0xb2, 0xc0, 0xc0,
+ 0xbf, 0x0f, 0x82, 0x00, 0x00, 0xa6, 0x88, 0xc0, 0x00, 0x68, 0x82, 0x00,
+ 0x00, 0x69, 0x81, 0xc0, 0x00, 0x4e, 0x82, 0x00, 0x00, 0x81, 0x80, 0xc0,
+ 0x00, 0x5a, 0x82, 0x00, 0x00, 0x8f, 0x82, 0xc0, 0x00, 0x05, 0x82, 0x00,
+ 0x00, 0xb7, 0x81, 0xc0, 0x00, 0x55, 0x82, 0x00, 0x00, 0x73, 0x9a, 0xc0,
+ 0x00, 0x47, 0x82, 0x00, 0x00, 0x62, 0x85, 0xc0, 0x00, 0x7b, 0x82, 0x00,
+ 0x00, 0x26, 0x84, 0xc0, 0x03, 0xa9, 0x25, 0x00, 0x54, 0x80, 0xc0, 0x00,
+ 0xa9, 0x82, 0x00, 0x01, 0x0c, 0xbf, 0x88, 0xc0, 0x00, 0x42, 0x82, 0x00,
+ 0x00, 0x8f, 0x81, 0xc0, 0x00, 0x28, 0x82, 0x00, 0x00, 0xa9, 0x80, 0xc0,
+ 0x00, 0x2b, 0x82, 0x00, 0x00, 0xb4, 0x82, 0xc0, 0x00, 0x14, 0x82, 0x00,
+ 0x00, 0x97, 0x81, 0xc0, 0x00, 0x2c, 0x82, 0x00, 0x00, 0x9c, 0x9a, 0xc0,
+ 0x00, 0x1e, 0x82, 0x00, 0x00, 0x8b, 0x85, 0xc0, 0x00, 0x51, 0x82, 0x00,
+ 0x01, 0x12, 0xbb, 0x81, 0xc0, 0x05, 0xb8, 0x70, 0x10, 0x00, 0x03, 0xa9,
+ 0x80, 0xc0, 0x00, 0x7f, 0x82, 0x00, 0x00, 0x2f, 0x88, 0xc0, 0x01, 0xbf,
+ 0x19, 0x82, 0x00, 0x00, 0xb2, 0x80, 0xc0, 0x01, 0xbb, 0x05, 0x81, 0x00,
+ 0x01, 0x12, 0xbf, 0x80, 0xc0, 0x00, 0x0e, 0x82, 0x00, 0x01, 0x7b, 0xbd,
+ 0x81, 0xc0, 0x00, 0x41, 0x82, 0x00, 0x05, 0x3e, 0xbf, 0xc0, 0xc0, 0xaf,
+ 0x04, 0x81, 0x00, 0x01, 0x06, 0xbc, 0x99, 0xc0, 0x00, 0xb5, 0x83, 0x00,
+ 0x00, 0xb3, 0x84, 0xc0, 0x01, 0xbf, 0x16, 0x83, 0x00, 0x05, 0x2e, 0x71,
+ 0x79, 0x63, 0x48, 0x0d, 0x80, 0x00, 0x00, 0x46, 0x81, 0xc0, 0x00, 0x42,
+ 0x82, 0x00, 0x00, 0x42, 0x88, 0xc0, 0x00, 0x9f, 0x82, 0x00, 0x01, 0x07,
+ 0xbf, 0x80, 0xc0, 0x00, 0x9b, 0x82, 0x00, 0x00, 0x3b, 0x81, 0xc0, 0x00,
+ 0x12, 0x83, 0x00, 0x06, 0x0b, 0x21, 0xb2, 0xc0, 0xc0, 0x97, 0x02, 0x82,
+ 0x00, 0x03, 0x42, 0x97, 0xa7, 0x49, 0x82, 0x00, 0x00, 0x18, 0x9a, 0xc0,
+ 0x00, 0x8e, 0x82, 0x00, 0x00, 0x1d, 0x84, 0xc0, 0x01, 0xbd, 0x6c, 0x8d,
+ 0x00, 0x05, 0x9f, 0xc0, 0xc0, 0xbf, 0x8e, 0x07, 0x82, 0x00, 0x01, 0x13,
+ 0xb6, 0x86, 0xc0, 0x01, 0xb6, 0x40, 0x83, 0x00, 0x00, 0x91, 0x80, 0xc0,
+ 0x00, 0x75, 0x82, 0x00, 0x00, 0x64, 0x81, 0xc0, 0x00, 0x60, 0x82, 0x00,
+ 0x02, 0x2f, 0x7e, 0xbb, 0x81, 0xc0, 0x01, 0x75, 0x05, 0x8b, 0x00, 0x00,
+ 0x88, 0x99, 0xc0, 0x00, 0x65, 0x82, 0x00, 0x00, 0x45, 0x84, 0xc0, 0x00,
+ 0x40, 0x8d, 0x00, 0x00, 0x38, 0x80, 0xc0, 0x00, 0x6d, 0x85, 0x00, 0x00,
+ 0x1a, 0x86, 0xc0, 0x00, 0x13, 0x84, 0x00, 0x04, 0x02, 0xa1, 0xc0, 0xc0,
+ 0x4e, 0x82, 0x00, 0x00, 0x8e, 0x81, 0xc0, 0x05, 0xbe, 0x76, 0x29, 0x10,
+ 0x52, 0xa0, 0x85, 0xc0, 0x05, 0xa4, 0x5a, 0x2b, 0x11, 0x0a, 0x04, 0x87,
+ 0x00, 0x00, 0x92, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xd6, 0xc0, 0x09, 0xb1, 0x85, 0x5a, 0x38, 0x1b, 0x08,
+ 0x05, 0x16, 0x4b, 0xad, 0x95, 0xc0, 0x03, 0x97, 0x49, 0x10, 0x68, 0x81,
+ 0xc0, 0x01, 0x83, 0xa0, 0x80, 0xc0, 0x01, 0xbe, 0xa1, 0xd1, 0xc0, 0x02,
+ 0xb8, 0x41, 0x01, 0x85, 0x00, 0x00, 0x29, 0x92, 0xc0, 0x02, 0x93, 0x60,
+ 0x2f, 0x80, 0x00, 0x0c, 0x13, 0xc0, 0xc0, 0xb0, 0x35, 0x00, 0x36, 0xc0,
+ 0xc0, 0xb2, 0x2f, 0x03, 0x99, 0xd0, 0xc0, 0x0b, 0x3a, 0x00, 0x01, 0x2f,
+ 0x60, 0x85, 0xa3, 0xb4, 0xbd, 0xb0, 0x72, 0x0e, 0x91, 0xc0, 0x13, 0x7f,
+ 0x02, 0x00, 0x00, 0x14, 0x72, 0xab, 0x18, 0xc0, 0xaa, 0x1b, 0x10, 0x00,
+ 0x58, 0xc0, 0x9d, 0x1a, 0x00, 0x04, 0x97, 0xcf, 0xc0, 0x0c, 0x89, 0x05,
+ 0x26, 0x53, 0xaf, 0xc0, 0x9f, 0x48, 0xa3, 0xc0, 0xc0, 0x8c, 0x6b, 0x8b,
+ 0xc0, 0x02, 0xaf, 0x4b, 0x9f, 0x80, 0xc0, 0x12, 0x2a, 0x00, 0x08, 0x60,
+ 0xb8, 0xc0, 0x89, 0x4d, 0xad, 0x1d, 0x7a, 0x5f, 0x05, 0xab, 0x90, 0x09,
+ 0x00, 0x01, 0x7c, 0xbc, 0xc0, 0x02, 0xaf, 0x4b, 0x9f, 0x8e, 0xc0, 0x01,
+ 0xbf, 0xbe, 0x80, 0xc0, 0x06, 0x91, 0x22, 0x8c, 0x8a, 0x65, 0x4b, 0x82,
+ 0x8c, 0xc0, 0x02, 0x31, 0x38, 0xbf, 0x80, 0xc0, 0x02, 0x14, 0x50, 0xac,
+ 0x80, 0xc0, 0x0b, 0x2f, 0x8e, 0x25, 0x78, 0xb2, 0x0f, 0x54, 0x94, 0x08,
+ 0x4b, 0x08, 0x61, 0xbd, 0xc0, 0x02, 0x31, 0x38, 0xbf, 0x92, 0xc0, 0x06,
+ 0xa3, 0x0e, 0x14, 0x32, 0x5b, 0x91, 0xbf, 0x8a, 0xc0, 0x05, 0x60, 0x0e,
+ 0x01, 0x00, 0x13, 0xb1, 0x85, 0xc0, 0x0b, 0x85, 0x24, 0x3d, 0x5e, 0xc0,
+ 0x49, 0x0c, 0x8f, 0x0e, 0x6f, 0x41, 0x38, 0xbb, 0xc0, 0x05, 0x60, 0x0e,
+ 0x01, 0x00, 0x13, 0xb1, 0x8f, 0xc0, 0x06, 0x9b, 0x23, 0x11, 0x02, 0x48,
+ 0x98, 0xba, 0x82, 0xc0, 0x0f, 0x94, 0x30, 0x08, 0x64, 0xc0, 0xc0, 0x94,
+ 0x30, 0x08, 0x64, 0x7d, 0x0b, 0x06, 0x00, 0x00, 0x75, 0x85, 0xc0, 0x0c,
+ 0xb6, 0x15, 0x19, 0x38, 0xbf, 0x8f, 0x01, 0x51, 0x14, 0x75, 0x66, 0x10,
+ 0xb0, 0x80, 0xc0, 0x0b, 0x96, 0x40, 0x0d, 0x7b, 0xc0, 0xc0, 0xb6, 0x70,
+ 0xbe, 0xc0, 0x65, 0x25, 0x80, 0xc0, 0x03, 0x96, 0x40, 0x0d, 0x7b, 0x80,
+ 0xc0, 0x03, 0xbe, 0x77, 0x23, 0x28, 0x81, 0xc0, 0x03, 0xa9, 0x4a, 0x0d,
+ 0x23, 0x89, 0xc0, 0x11, 0xa9, 0x4a, 0x0d, 0x23, 0xc0, 0xc0, 0xb6, 0x70,
+ 0xbe, 0xc0, 0x65, 0x25, 0x7d, 0x0b, 0x06, 0x00, 0x00, 0x75, 0x91, 0xc0,
+ 0x01, 0x8b, 0x01, 0x80, 0x00, 0x14, 0x05, 0x32, 0x7a, 0xbe, 0xc0, 0x70,
+ 0x02, 0x25, 0x57, 0x1d, 0xc0, 0x70, 0x02, 0x25, 0x57, 0x1d, 0xbb, 0xac,
+ 0x15, 0x86, 0xb5, 0x86, 0xc0, 0x4e, 0x51, 0x00, 0x15, 0xb2, 0xb5, 0x17,
+ 0x0d, 0x1a, 0x71, 0x94, 0x02, 0x77, 0xc0, 0xc0, 0xb7, 0x47, 0x15, 0x60,
+ 0x11, 0xa5, 0xc0, 0xc0, 0x38, 0x44, 0xbc, 0x48, 0x00, 0x30, 0xc0, 0xb7,
+ 0x47, 0x15, 0x60, 0x11, 0xa5, 0xc0, 0xc0, 0xae, 0x2f, 0x00, 0x27, 0x69,
+ 0x1b, 0xc0, 0xc0, 0x8b, 0x0b, 0x50, 0x85, 0x39, 0xc0, 0xb3, 0x5e, 0x5d,
+ 0xba, 0x53, 0x0e, 0x9f, 0xc0, 0x91, 0x5a, 0x8b, 0x0b, 0x50, 0x85, 0x39,
+ 0xc0, 0xc0, 0x38, 0x44, 0xbc, 0x48, 0x00, 0x30, 0xbb, 0xac, 0x15, 0x86,
+ 0xb5, 0x91, 0xc0, 0x18, 0xb6, 0x17, 0x0c, 0x96, 0xad, 0x91, 0x6d, 0x2d,
+ 0x00, 0x3f, 0x88, 0x01, 0x54, 0xbd, 0x3a, 0x09, 0x88, 0x01, 0x54, 0xbd,
+ 0x3a, 0x09, 0xae, 0x1f, 0x3f, 0x87, 0xc0, 0x4d, 0x8e, 0x01, 0x02, 0x91,
+ 0xc0, 0x42, 0x00, 0x00, 0x63, 0xbc, 0x1e, 0x1f, 0xbe, 0xc0, 0xae, 0x23,
+ 0x60, 0xb8, 0x3a, 0x0f, 0xab, 0xc0, 0x82, 0x12, 0xb4, 0x48, 0x2f, 0x06,
+ 0xa6, 0xae, 0x23, 0x60, 0xb8, 0x3a, 0x0f, 0xab, 0xc0, 0xb0, 0x1c, 0x0c,
+ 0x73, 0xac, 0x10, 0x26, 0xc0, 0x94, 0x04, 0x5a, 0x7f, 0x5a, 0xb8, 0xa5,
+ 0x19, 0x17, 0x7e, 0x26, 0x00, 0x0a, 0xb3, 0x7f, 0x05, 0x00, 0x04, 0x5a,
+ 0x7f, 0x5a, 0xb8, 0xc0, 0x82, 0x12, 0xb4, 0x48, 0x2f, 0x06, 0xa6, 0xae,
+ 0x1f, 0x3f, 0x93, 0xc0, 0x02, 0x5a, 0x00, 0x90, 0x81, 0xc0, 0x14, 0xa3,
+ 0x00, 0x0e, 0x23, 0x50, 0xc0, 0xc0, 0x12, 0x32, 0x23, 0x50, 0xc0, 0xc0,
+ 0x12, 0x1d, 0x3d, 0x00, 0x98, 0xc0, 0x9f, 0xb5, 0x83, 0xc0, 0x51, 0xb2,
+ 0x15, 0x00, 0x57, 0xc0, 0x77, 0x00, 0x00, 0x51, 0xc0, 0x74, 0x00, 0x72,
+ 0xc0, 0xc0, 0x33, 0x7b, 0xc0, 0x57, 0x08, 0x8b, 0xc0, 0xa1, 0x25, 0x73,
+ 0x63, 0x50, 0x1b, 0x56, 0xc0, 0x33, 0x7d, 0xc0, 0x57, 0x08, 0x8b, 0xc0,
+ 0xa1, 0x42, 0x11, 0xa2, 0xbe, 0x33, 0x00, 0x6c, 0xc0, 0x2a, 0x00, 0x5f,
+ 0xa1, 0xc0, 0x85, 0x2f, 0x2c, 0x9e, 0x1c, 0x74, 0x29, 0x65, 0x72, 0x32,
+ 0x10, 0x0b, 0x00, 0x5f, 0xa1, 0xc0, 0x85, 0xb2, 0x25, 0x73, 0x63, 0x50,
+ 0x1b, 0x56, 0xab, 0x3d, 0x00, 0x98, 0xc0, 0x9f, 0xb5, 0x90, 0xc0, 0x1b,
+ 0x11, 0x00, 0x79, 0xb9, 0xb8, 0x98, 0x5d, 0x0e, 0x00, 0x6e, 0x06, 0x9d,
+ 0xc0, 0xc0, 0x09, 0x63, 0x00, 0x9d, 0xc0, 0xc0, 0x09, 0x60, 0x00, 0x00,
+ 0xa9, 0x71, 0x3d, 0xbc, 0x83, 0xc0, 0x51, 0x3f, 0x00, 0x1b, 0xb9, 0xb2,
+ 0x0a, 0x00, 0x3b, 0xbe, 0xc0, 0x2c, 0x00, 0xac, 0xc0, 0xb9, 0x00, 0x89,
+ 0x4a, 0x36, 0x27, 0x7d, 0x55, 0x60, 0x02, 0x7b, 0x35, 0x69, 0x00, 0xa5,
+ 0xa0, 0x00, 0xa5, 0x4a, 0x36, 0x27, 0x7d, 0x55, 0x60, 0x08, 0x87, 0xc0,
+ 0x51, 0x0d, 0x08, 0xb3, 0xac, 0x06, 0x00, 0x99, 0xa9, 0x53, 0x45, 0x0b,
+ 0x84, 0x15, 0x78, 0x95, 0x21, 0x5a, 0x79, 0x07, 0x91, 0x06, 0x00, 0x99,
+ 0xa9, 0x53, 0x45, 0xc0, 0x02, 0x7b, 0x35, 0x69, 0x00, 0xa5, 0x9e, 0x08,
+ 0x00, 0xa9, 0x71, 0x3d, 0xbc, 0x90, 0xc0, 0x00, 0x1b, 0x83, 0x00, 0x0e,
+ 0x17, 0x83, 0xc0, 0x32, 0x9f, 0xb0, 0x63, 0x24, 0x54, 0x22, 0x9f, 0xb0,
+ 0x63, 0x24, 0x54, 0x80, 0x00, 0x01, 0x3b, 0xb9, 0x84, 0xc0, 0x2e, 0x17,
+ 0x00, 0x90, 0xc0, 0x91, 0x00, 0x27, 0xb8, 0xc0, 0xc0, 0x08, 0x00, 0xa4,
+ 0x8d, 0x21, 0x00, 0x00, 0x17, 0xb1, 0x0b, 0x00, 0x3f, 0xbf, 0x0e, 0x0c,
+ 0xad, 0x1a, 0x00, 0x6a, 0x39, 0x16, 0x00, 0x17, 0xb1, 0x0b, 0x00, 0x3f,
+ 0xbf, 0x1c, 0xa8, 0x50, 0x23, 0x50, 0x45, 0x5c, 0x81, 0x1b, 0x80, 0x00,
+ 0x0b, 0x39, 0xbb, 0x0c, 0x00, 0x6a, 0xc0, 0x39, 0x1d, 0x8b, 0x40, 0x00,
+ 0x73, 0x81, 0x00, 0x09, 0x39, 0xbb, 0xc0, 0x0e, 0x0c, 0xad, 0x1a, 0x00,
+ 0x6a, 0x39, 0x80, 0x00, 0x01, 0x3b, 0xb9, 0x91, 0xc0, 0x19, 0x9d, 0x37,
+ 0x0e, 0x04, 0x17, 0x45, 0x8b, 0xbe, 0xc0, 0xc0, 0xa4, 0x23, 0x0a, 0x51,
+ 0xb8, 0xc0, 0xa4, 0x23, 0x0a, 0x51, 0xb8, 0xc0, 0x37, 0x12, 0x69, 0xbe,
+ 0x85, 0xc0, 0x06, 0x57, 0x43, 0xc0, 0xc0, 0xaf, 0x23, 0xae, 0x80, 0xc0,
+ 0x45, 0x0e, 0x00, 0x00, 0x11, 0x93, 0x88, 0x19, 0x9e, 0xc0, 0x05, 0x3b,
+ 0xbb, 0xc0, 0x49, 0x7d, 0xc0, 0x08, 0x00, 0x4a, 0xbb, 0x88, 0x19, 0x9e,
+ 0xc0, 0x05, 0x3b, 0xbb, 0xc0, 0x77, 0x0c, 0x57, 0xae, 0x0d, 0x29, 0xa3,
+ 0xc0, 0x85, 0x11, 0x14, 0x63, 0xbd, 0xc0, 0x55, 0x48, 0xc0, 0xc0, 0x0c,
+ 0x75, 0xc0, 0x0c, 0x00, 0x3d, 0x73, 0x11, 0x14, 0x63, 0xbd, 0xc0, 0xc0,
+ 0x49, 0x7d, 0xc0, 0x08, 0x00, 0x4a, 0xbb, 0x37, 0x12, 0x69, 0xbe, 0xb4,
+ 0xc0, 0x01, 0xbe, 0xbd, 0x85, 0xc0, 0x03, 0x6e, 0x0b, 0x3f, 0xac, 0x82,
+ 0xc0, 0x01, 0x9d, 0xbf, 0x82, 0xc0, 0x01, 0x88, 0x92, 0x83, 0xc0, 0x01,
+ 0x9d, 0xbf, 0x81, 0xc0, 0x03, 0xbb, 0x44, 0x48, 0xba, 0x89, 0xc0, 0x04,
+ 0xb8, 0xc0, 0xc0, 0x93, 0x9d, 0x88, 0xc0, 0x01, 0x88, 0x92, 0xe1, 0xc0,
+ 0x03, 0xb4, 0x2d, 0x1f, 0xbb, 0xff, 0xc0, 0x03, 0xbb, 0x2c, 0x05, 0x9a,
+ 0xff, 0xc0, 0x03, 0xc0, 0x65, 0x00, 0x77, 0xff, 0xc0, 0x03, 0xc0, 0xc0,
+ 0x30, 0x78, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0,
+ 0xc8, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x8e, 0xc0, 0x08, 0xb2, 0x98, 0x83,
+ 0x6e, 0x5a, 0x45, 0x30, 0x1b, 0x39, 0xa8, 0xc0, 0x00, 0xf3, 0x8c, 0xff,
+ 0x00, 0xe7, 0x81, 0xc0, 0x00, 0xe4, 0x8c, 0xff, 0x03, 0xfb, 0xc0, 0xca,
+ 0xfe, 0x84, 0xff, 0x00, 0xf9, 0x9f, 0xc0, 0x01, 0x6e, 0x0b, 0x83, 0x00,
+ 0x00, 0x5a, 0xa8, 0xc0, 0x01, 0xc2, 0xf6, 0x8b, 0xff, 0x00, 0xea, 0x82,
+ 0xc0, 0x00, 0xe9, 0x8b, 0xff, 0x03, 0xfe, 0xc0, 0xc0, 0xd0, 0x83, 0xff,
+ 0x01, 0xea, 0xc3, 0xa0, 0xc0, 0x01, 0xb9, 0x15, 0x82, 0x00, 0x00, 0x82,
+ 0xa9, 0xc0, 0x00, 0xe5, 0x82, 0xff, 0x09, 0xf9, 0xd5, 0xc9, 0xc8, 0xcf,
+ 0xda, 0xf4, 0xff, 0xff, 0xed, 0x82, 0xc0, 0x00, 0xd6, 0x82, 0xff, 0x0d,
+ 0xfb, 0xd9, 0xcb, 0xc7, 0xcd, 0xd4, 0xea, 0xfe, 0xff, 0xff, 0xc2, 0xc0,
+ 0xc0, 0xfd, 0x82, 0xff, 0x00, 0xca, 0xa2, 0xc0, 0x00, 0x15, 0x82, 0x00,
+ 0x00, 0xaa, 0xa9, 0xc0, 0x00, 0xec, 0x82, 0xff, 0x00, 0xd9, 0x83, 0xc0,
+ 0x02, 0xde, 0xff, 0xf0, 0x82, 0xc0, 0x00, 0xde, 0x82, 0xff, 0x00, 0xe3,
+ 0x83, 0xc0, 0x05, 0xcc, 0xfa, 0xff, 0xc5, 0xc0, 0xc5, 0x82, 0xff, 0x00,
+ 0xf5, 0xa2, 0xc0, 0x00, 0xad, 0x82, 0x00, 0x01, 0x11, 0xbf, 0xa9, 0xc0,
+ 0x00, 0xf9, 0x82, 0xff, 0x00, 0xc7, 0x80, 0xc0, 0x05, 0xc4, 0xfe, 0xc0,
+ 0xc0, 0xe8, 0xf2, 0x82, 0xc0, 0x00, 0xea, 0x82, 0xff, 0x00, 0xd4, 0x80,
+ 0xc0, 0x08, 0xc5, 0xfb, 0xc0, 0xc0, 0xcf, 0xff, 0xc8, 0xc0, 0xd0, 0x82,
+ 0xff, 0x00, 0xe8, 0xa2, 0xc0, 0x00, 0x85, 0x82, 0x00, 0x00, 0x3a, 0x98,
+ 0xc0, 0x11, 0xb3, 0x95, 0x7a, 0x60, 0x45, 0x2a, 0x0f, 0x66, 0xc0, 0xc0,
+ 0xa4, 0x58, 0x20, 0x0b, 0x69, 0xc0, 0xc0, 0xc6, 0x82, 0xff, 0x00, 0xf6,
+ 0x80, 0xc0, 0x06, 0xc5, 0xe8, 0xff, 0xc0, 0xc0, 0xce, 0xf5, 0x82, 0xc0,
+ 0x00, 0xf7, 0x82, 0xff, 0x05, 0xc5, 0xc0, 0xc0, 0xc3, 0xe4, 0xff, 0x80,
+ 0xc0, 0x03, 0xeb, 0xc9, 0xc0, 0xdd, 0x82, 0xff, 0x14, 0xdb, 0xc0, 0xc0,
+ 0xaf, 0x91, 0x77, 0x5d, 0x42, 0x28, 0x0e, 0x91, 0xc0, 0xc0, 0xb4, 0x70,
+ 0x34, 0x15, 0x05, 0x17, 0x53, 0xb5, 0x87, 0xc0, 0x04, 0x9d, 0x60, 0x2e,
+ 0x16, 0x08, 0x85, 0x00, 0x00, 0x63, 0x98, 0xc0, 0x00, 0x68, 0x83, 0x00,
+ 0x0a, 0x16, 0xc0, 0x6f, 0x05, 0x00, 0x00, 0x09, 0xb5, 0xc0, 0xc0, 0xd3,
+ 0x82, 0xff, 0x06, 0xfd, 0xf5, 0xf6, 0xf9, 0xfe, 0xff, 0xff, 0x80, 0xc0,
+ 0x00, 0xc9, 0x81, 0xc0, 0x00, 0xc5, 0x83, 0xff, 0x05, 0xf5, 0xf6, 0xf8,
+ 0xfe, 0xff, 0xff, 0x83, 0xc0, 0x00, 0xea, 0x82, 0xff, 0x03, 0xcf, 0xc0,
+ 0xc0, 0x51, 0x83, 0x00, 0x03, 0x5d, 0xbe, 0x6d, 0x0e, 0x83, 0x00, 0x00,
+ 0x4a, 0x85, 0xc0, 0x01, 0xa7, 0x3c, 0x8a, 0x00, 0x00, 0x8b, 0x99, 0xc0,
+ 0x00, 0x87, 0x82, 0x00, 0x01, 0x05, 0x6e, 0x81, 0x00, 0x00, 0x54, 0x80,
+ 0xc0, 0x00, 0xe0, 0x89, 0xff, 0x85, 0xc0, 0x00, 0xd2, 0x89, 0xff, 0x83,
+ 0xc0, 0x00, 0xf6, 0x82, 0xff, 0x00, 0xc3, 0x80, 0xc0, 0x00, 0x68, 0x82,
+ 0x00, 0x01, 0x42, 0x39, 0x85, 0x00, 0x00, 0x0f, 0x84, 0xc0, 0x01, 0x8f,
+ 0x0e, 0x84, 0x00, 0x01, 0x12, 0x02, 0x82, 0x00, 0x00, 0xb2, 0x99, 0xc0,
+ 0x00, 0xb8, 0x82, 0x00, 0x06, 0x02, 0x02, 0x0e, 0x31, 0x14, 0x02, 0xa7,
+ 0x80, 0xc0, 0x00, 0xed, 0x89, 0xff, 0x85, 0xc0, 0x00, 0xdf, 0x89, 0xff,
+ 0x82, 0xc0, 0x00, 0xc4, 0x82, 0xff, 0x00, 0xf5, 0x81, 0xc0, 0x00, 0x8b,
+ 0x84, 0x00, 0x02, 0x2c, 0x62, 0x3a, 0x82, 0x00, 0x00, 0x12, 0x83, 0xc0,
+ 0x01, 0x99, 0x06, 0x82, 0x00, 0x04, 0x1b, 0x84, 0xb2, 0xb5, 0x01, 0x81,
+ 0x00, 0x00, 0x1a, 0x9a, 0xc0, 0x00, 0xa2, 0x83, 0x00, 0x04, 0x38, 0xb8,
+ 0xc0, 0xbd, 0x8a, 0x81, 0xc0, 0x00, 0xfa, 0x82, 0xff, 0x06, 0xcf, 0xc3,
+ 0xc3, 0xcb, 0xe2, 0xfe, 0xff, 0x85, 0xc0, 0x00, 0xec, 0x82, 0xff, 0x06,
+ 0xdb, 0xc4, 0xc3, 0xcb, 0xe4, 0xff, 0xff, 0x82, 0xc0, 0x00, 0xd0, 0x82,
+ 0xff, 0x00, 0xe9, 0x81, 0xc0, 0x00, 0x72, 0x83, 0x00, 0x03, 0x4c, 0xbe,
+ 0xc0, 0xb2, 0x82, 0x00, 0x00, 0x35, 0x82, 0xc0, 0x01, 0xb2, 0x14, 0x82,
+ 0x00, 0x04, 0x4e, 0xba, 0xc0, 0xc0, 0x8d, 0x82, 0x00, 0x00, 0x42, 0x9a,
+ 0xc0, 0x00, 0x7b, 0x82, 0x00, 0x01, 0x07, 0xaf, 0x84, 0xc0, 0x00, 0xc8,
+ 0x82, 0xff, 0x00, 0xfb, 0x82, 0xc0, 0x01, 0xdc, 0xff, 0x85, 0xc0, 0x00,
+ 0xf9, 0x82, 0xff, 0x00, 0xc9, 0x81, 0xc0, 0x01, 0xe2, 0xff, 0x82, 0xc0,
+ 0x00, 0xdd, 0x82, 0xff, 0x00, 0xdc, 0x81, 0xc0, 0x00, 0x4e, 0x82, 0x00,
+ 0x04, 0x16, 0xbb, 0xc0, 0xc0, 0xa7, 0x82, 0x00, 0x00, 0x59, 0x82, 0xc0,
+ 0x00, 0x54, 0x82, 0x00, 0x01, 0x3b, 0xbe, 0x80, 0xc0, 0x00, 0x63, 0x82,
+ 0x00, 0x00, 0x6b, 0x9a, 0xc0, 0x00, 0x52, 0x82, 0x00, 0x00, 0x45, 0x85,
+ 0xc0, 0x00, 0xd5, 0x82, 0xff, 0x00, 0xed, 0x82, 0xc0, 0x01, 0xc3, 0xfe,
+ 0x84, 0xc0, 0x00, 0xc6, 0x82, 0xff, 0x00, 0xfc, 0x82, 0xc0, 0x01, 0xca,
+ 0xff, 0x82, 0xc0, 0x00, 0xe9, 0x82, 0xff, 0x00, 0xcf, 0x81, 0xc0, 0x00,
+ 0x28, 0x82, 0x00, 0x00, 0x6f, 0x80, 0xc0, 0x00, 0x78, 0x82, 0x00, 0x00,
+ 0x8a, 0x81, 0xc0, 0x01, 0xab, 0x04, 0x81, 0x00, 0x01, 0x08, 0xac, 0x81,
+ 0xc0, 0x00, 0x3a, 0x82, 0x00, 0x00, 0x93, 0x9a, 0xc0, 0x00, 0x29, 0x82,
+ 0x00, 0x00, 0x79, 0x85, 0xc0, 0x00, 0xe2, 0x82, 0xff, 0x00, 0xe0, 0x83,
+ 0xc0, 0x00, 0xc1, 0x84, 0xc0, 0x00, 0xd3, 0x82, 0xff, 0x00, 0xef, 0x83,
+ 0xc0, 0x00, 0xc8, 0x82, 0xc0, 0x00, 0xf6, 0x82, 0xff, 0x00, 0xc3, 0x80,
+ 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00, 0x00, 0xaf, 0x80, 0xc0, 0x00, 0x40,
+ 0x81, 0x00, 0x01, 0x04, 0xb8, 0x81, 0xc0, 0x00, 0x6b, 0x82, 0x00, 0x00,
+ 0x51, 0x81, 0xc0, 0x01, 0xbf, 0x11, 0x81, 0x00, 0x01, 0x02, 0xb8, 0x99,
+ 0xc0, 0x01, 0xbb, 0x05, 0x82, 0x00, 0x00, 0xa8, 0x85, 0xc0, 0x00, 0xef,
+ 0x82, 0xff, 0x00, 0xd2, 0x86, 0xc0, 0x01, 0xc9, 0xe7, 0x80, 0xc0, 0x00,
+ 0xe0, 0x82, 0xff, 0x00, 0xe2, 0x88, 0xc0, 0x00, 0xc4, 0x82, 0xff, 0x00,
+ 0xf6, 0x81, 0xc0, 0x00, 0x9b, 0x82, 0x00, 0x00, 0x25, 0x80, 0xc0, 0x01,
+ 0xbc, 0x0b, 0x81, 0x00, 0x00, 0x2f, 0x82, 0xc0, 0x00, 0x31, 0x82, 0x00,
+ 0x00, 0x8f, 0x81, 0xc0, 0x00, 0xa8, 0x82, 0x00, 0x00, 0x23, 0x9a, 0xc0,
+ 0x00, 0x99, 0x82, 0x00, 0x01, 0x10, 0xbf, 0x85, 0xc0, 0x00, 0xfc, 0x82,
+ 0xff, 0x00, 0xc6, 0x85, 0xc0, 0x02, 0xc4, 0xf6, 0xdf, 0x80, 0xc0, 0x00,
+ 0xed, 0x82, 0xff, 0x00, 0xd5, 0x88, 0xc0, 0x00, 0xd0, 0x82, 0xff, 0x00,
+ 0xe9, 0x81, 0xc0, 0x00, 0x75, 0x82, 0x00, 0x00, 0x57, 0x80, 0xc0, 0x00,
+ 0x91, 0x82, 0x00, 0x00, 0x62, 0x82, 0xc0, 0x00, 0x15, 0x82, 0x00, 0x00,
+ 0xaf, 0x81, 0xc0, 0x00, 0x7f, 0x82, 0x00, 0x00, 0x4b, 0x9a, 0xc0, 0x00,
+ 0x6f, 0x82, 0x00, 0x00, 0x39, 0x85, 0xc0, 0x00, 0xc9, 0x82, 0xff, 0x00,
+ 0xfb, 0x85, 0xc0, 0x03, 0xc2, 0xee, 0xfd, 0xc5, 0x80, 0xc0, 0x00, 0xfa,
+ 0x82, 0xff, 0x00, 0xc9, 0x88, 0xc0, 0x00, 0xdd, 0x82, 0xff, 0x00, 0xdd,
+ 0x81, 0xc0, 0x00, 0x4e, 0x82, 0x00, 0x00, 0x81, 0x80, 0xc0, 0x00, 0x5a,
+ 0x82, 0x00, 0x00, 0x8f, 0x82, 0xc0, 0x00, 0x05, 0x82, 0x00, 0x00, 0xb7,
+ 0x81, 0xc0, 0x00, 0x55, 0x82, 0x00, 0x00, 0x73, 0x9a, 0xc0, 0x00, 0x47,
+ 0x82, 0x00, 0x00, 0x62, 0x85, 0xc0, 0x00, 0xd6, 0x82, 0xff, 0x00, 0xf2,
+ 0x84, 0xc0, 0x03, 0xc7, 0xf3, 0xff, 0xe4, 0x80, 0xc0, 0x00, 0xc8, 0x82,
+ 0xff, 0x00, 0xfb, 0x89, 0xc0, 0x00, 0xe9, 0x82, 0xff, 0x00, 0xd0, 0x81,
+ 0xc0, 0x00, 0x28, 0x82, 0x00, 0x00, 0xa9, 0x80, 0xc0, 0x00, 0x2b, 0x82,
+ 0x00, 0x00, 0xb4, 0x82, 0xc0, 0x00, 0x14, 0x82, 0x00, 0x00, 0x97, 0x81,
+ 0xc0, 0x00, 0x2c, 0x82, 0x00, 0x00, 0x9c, 0x9a, 0xc0, 0x00, 0x1e, 0x82,
+ 0x00, 0x00, 0x8b, 0x85, 0xc0, 0x00, 0xe4, 0x82, 0xff, 0x01, 0xf9, 0xc2,
+ 0x81, 0xc0, 0x05, 0xc3, 0xda, 0xfa, 0xff, 0xfe, 0xc7, 0x80, 0xc0, 0x00,
+ 0xd5, 0x82, 0xff, 0x00, 0xef, 0x89, 0xc0, 0x00, 0xf7, 0x82, 0xff, 0x00,
+ 0xc4, 0x80, 0xc0, 0x01, 0xbb, 0x05, 0x81, 0x00, 0x01, 0x12, 0xbf, 0x80,
+ 0xc0, 0x00, 0x0e, 0x82, 0x00, 0x01, 0x7b, 0xbd, 0x81, 0xc0, 0x00, 0x41,
+ 0x82, 0x00, 0x05, 0x3e, 0xbf, 0xc0, 0xc0, 0xaf, 0x04, 0x81, 0x00, 0x01,
+ 0x06, 0xbc, 0x99, 0xc0, 0x00, 0xb5, 0x83, 0x00, 0x00, 0xb3, 0x85, 0xc0,
+ 0x00, 0xf8, 0x83, 0xff, 0x05, 0xf0, 0xda, 0xd7, 0xdf, 0xe8, 0xfb, 0x80,
+ 0xff, 0x00, 0xe8, 0x81, 0xc0, 0x00, 0xe9, 0x82, 0xff, 0x00, 0xe9, 0x88,
+ 0xc0, 0x00, 0xcb, 0x82, 0xff, 0x00, 0xfd, 0x81, 0xc0, 0x00, 0x9b, 0x82,
+ 0x00, 0x00, 0x3b, 0x81, 0xc0, 0x00, 0x12, 0x83, 0x00, 0x06, 0x0b, 0x21,
+ 0xb2, 0xc0, 0xc0, 0x97, 0x02, 0x82, 0x00, 0x03, 0x42, 0x97, 0xa7, 0x49,
+ 0x82, 0x00, 0x00, 0x18, 0x9a, 0xc0, 0x00, 0x8e, 0x82, 0x00, 0x00, 0x1d,
+ 0x84, 0xc0, 0x01, 0xc1, 0xdb, 0x8d, 0xff, 0x00, 0xcb, 0x80, 0xc0, 0x01,
+ 0xd0, 0xfd, 0x82, 0xff, 0x01, 0xf9, 0xc3, 0x86, 0xc0, 0x01, 0xc3, 0xea,
+ 0x83, 0xff, 0x00, 0xd0, 0x80, 0xc0, 0x00, 0x75, 0x82, 0x00, 0x00, 0x64,
+ 0x81, 0xc0, 0x00, 0x60, 0x82, 0x00, 0x02, 0x2f, 0x7e, 0xbb, 0x81, 0xc0,
+ 0x01, 0x75, 0x05, 0x8b, 0x00, 0x00, 0x88, 0x99, 0xc0, 0x00, 0x65, 0x82,
+ 0x00, 0x00, 0x45, 0x84, 0xc0, 0x00, 0xea, 0x8d, 0xff, 0x00, 0xec, 0x80,
+ 0xc0, 0x00, 0xdb, 0x85, 0xff, 0x00, 0xf7, 0x86, 0xc0, 0x00, 0xf9, 0x84,
+ 0xff, 0x04, 0xfe, 0xca, 0xc0, 0xc0, 0x4e, 0x82, 0x00, 0x00, 0x8e, 0x81,
+ 0xc0, 0x05, 0xbe, 0x76, 0x29, 0x10, 0x52, 0xa0, 0x85, 0xc0, 0x05, 0xa4,
+ 0x5a, 0x2b, 0x11, 0x0a, 0x04, 0x87, 0x00, 0x00, 0x92, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff,
+ 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xd6, 0xc0, 0x09,
+ 0xb1, 0x85, 0x5a, 0x38, 0x1b, 0x08, 0x05, 0x16, 0x4b, 0xad, 0x95, 0xc0,
+ 0x03, 0x97, 0x49, 0x10, 0x68, 0x81, 0xc0, 0x01, 0x83, 0xa0, 0x80, 0xc0,
+ 0x01, 0xbe, 0xa1, 0xd1, 0xc0, 0x02, 0xb8, 0x41, 0x01, 0x85, 0x00, 0x00,
+ 0x29, 0x92, 0xc0, 0x02, 0x93, 0x60, 0x2f, 0x80, 0x00, 0x0c, 0x13, 0xc0,
+ 0xc0, 0xb0, 0x35, 0x00, 0x36, 0xc0, 0xc0, 0xb2, 0x2f, 0x03, 0x99, 0xd0,
+ 0xc0, 0x0b, 0x3a, 0x00, 0x01, 0x2f, 0x60, 0x85, 0xa3, 0xb4, 0xbd, 0xb0,
+ 0x72, 0x0e, 0x91, 0xc0, 0x13, 0x7f, 0x02, 0x00, 0x00, 0x14, 0x72, 0xab,
+ 0x18, 0xc0, 0xaa, 0x1b, 0x10, 0x00, 0x58, 0xc0, 0x9d, 0x1a, 0x00, 0x04,
+ 0x97, 0xcf, 0xc0, 0x0c, 0x89, 0x05, 0x26, 0x53, 0xaf, 0xc0, 0x9f, 0x48,
+ 0xa3, 0xc0, 0xc0, 0x8c, 0x6b, 0x8b, 0xc0, 0x02, 0xaf, 0x4b, 0x9f, 0x80,
+ 0xc0, 0x12, 0x2a, 0x00, 0x08, 0x60, 0xb8, 0xc0, 0x89, 0x4d, 0xad, 0x1d,
+ 0x7a, 0x5f, 0x05, 0xab, 0x90, 0x09, 0x00, 0x01, 0x7c, 0xbc, 0xc0, 0x02,
+ 0xaf, 0x4b, 0x9f, 0x8e, 0xc0, 0x01, 0xbf, 0xbe, 0x80, 0xc0, 0x06, 0x91,
+ 0x22, 0x8c, 0x8a, 0x65, 0x4b, 0x82, 0x8c, 0xc0, 0x02, 0x31, 0x38, 0xbf,
+ 0x80, 0xc0, 0x02, 0x14, 0x50, 0xac, 0x80, 0xc0, 0x0b, 0x2f, 0x8e, 0x25,
+ 0x78, 0xb2, 0x0f, 0x54, 0x94, 0x08, 0x4b, 0x08, 0x61, 0xbd, 0xc0, 0x02,
+ 0x31, 0x38, 0xbf, 0x92, 0xc0, 0x06, 0xa3, 0x0e, 0x14, 0x32, 0x5b, 0x91,
+ 0xbf, 0x8a, 0xc0, 0x05, 0x60, 0x0e, 0x01, 0x00, 0x13, 0xb1, 0x85, 0xc0,
+ 0x0b, 0x85, 0x24, 0x3d, 0x5e, 0xc0, 0x49, 0x0c, 0x8f, 0x0e, 0x6f, 0x41,
+ 0x38, 0xbb, 0xc0, 0x05, 0x60, 0x0e, 0x01, 0x00, 0x13, 0xb1, 0x8f, 0xc0,
+ 0x06, 0x9b, 0x23, 0x11, 0x02, 0x48, 0x98, 0xba, 0x82, 0xc0, 0x0f, 0x94,
+ 0x30, 0x08, 0x64, 0xc0, 0xc0, 0x94, 0x30, 0x08, 0x64, 0x7d, 0x0b, 0x06,
+ 0x00, 0x00, 0x75, 0x85, 0xc0, 0x0c, 0xb6, 0x15, 0x19, 0x38, 0xbf, 0x8f,
+ 0x01, 0x51, 0x14, 0x75, 0x66, 0x10, 0xb0, 0x80, 0xc0, 0x0b, 0x96, 0x40,
+ 0x0d, 0x7b, 0xc0, 0xc0, 0xb6, 0x70, 0xbe, 0xc0, 0x65, 0x25, 0x80, 0xc0,
+ 0x03, 0x96, 0x40, 0x0d, 0x7b, 0x80, 0xc0, 0x03, 0xbe, 0x77, 0x23, 0x28,
+ 0x81, 0xc0, 0x03, 0xa9, 0x4a, 0x0d, 0x23, 0x89, 0xc0, 0x11, 0xa9, 0x4a,
+ 0x0d, 0x23, 0xc0, 0xc0, 0xb6, 0x70, 0xbe, 0xc0, 0x65, 0x25, 0x7d, 0x0b,
+ 0x06, 0x00, 0x00, 0x75, 0x91, 0xc0, 0x01, 0x8b, 0x01, 0x80, 0x00, 0x14,
+ 0x05, 0x32, 0x7a, 0xbe, 0xc0, 0x70, 0x02, 0x25, 0x57, 0x1d, 0xc0, 0x70,
+ 0x02, 0x25, 0x57, 0x1d, 0xbb, 0xac, 0x15, 0x86, 0xb5, 0x86, 0xc0, 0x4e,
+ 0x51, 0x00, 0x15, 0xb2, 0xb5, 0x17, 0x0d, 0x1a, 0x71, 0x94, 0x02, 0x77,
+ 0xc0, 0xc0, 0xb7, 0x47, 0x15, 0x60, 0x11, 0xa5, 0xc0, 0xc0, 0x38, 0x44,
+ 0xbc, 0x48, 0x00, 0x30, 0xc0, 0xb7, 0x47, 0x15, 0x60, 0x11, 0xa5, 0xc0,
+ 0xc0, 0xae, 0x2f, 0x00, 0x27, 0x69, 0x1b, 0xc0, 0xc0, 0x8b, 0x0b, 0x50,
+ 0x85, 0x39, 0xc0, 0xb3, 0x5e, 0x5d, 0xba, 0x53, 0x0e, 0x9f, 0xc0, 0x91,
+ 0x5a, 0x8b, 0x0b, 0x50, 0x85, 0x39, 0xc0, 0xc0, 0x38, 0x44, 0xbc, 0x48,
+ 0x00, 0x30, 0xbb, 0xac, 0x15, 0x86, 0xb5, 0x91, 0xc0, 0x18, 0xb6, 0x17,
+ 0x0c, 0x96, 0xad, 0x91, 0x6d, 0x2d, 0x00, 0x3f, 0x88, 0x01, 0x54, 0xbd,
+ 0x3a, 0x09, 0x88, 0x01, 0x54, 0xbd, 0x3a, 0x09, 0xae, 0x1f, 0x3f, 0x87,
+ 0xc0, 0x4d, 0x8e, 0x01, 0x02, 0x91, 0xc0, 0x42, 0x00, 0x00, 0x63, 0xbc,
+ 0x1e, 0x1f, 0xbe, 0xc0, 0xae, 0x23, 0x60, 0xb8, 0x3a, 0x0f, 0xab, 0xc0,
+ 0x82, 0x12, 0xb4, 0x48, 0x2f, 0x06, 0xa6, 0xae, 0x23, 0x60, 0xb8, 0x3a,
+ 0x0f, 0xab, 0xc0, 0xb0, 0x1c, 0x0c, 0x73, 0xac, 0x10, 0x26, 0xc0, 0x94,
+ 0x04, 0x5a, 0x7f, 0x5a, 0xb8, 0xa5, 0x19, 0x17, 0x7e, 0x26, 0x00, 0x0a,
+ 0xb3, 0x7f, 0x05, 0x00, 0x04, 0x5a, 0x7f, 0x5a, 0xb8, 0xc0, 0x82, 0x12,
+ 0xb4, 0x48, 0x2f, 0x06, 0xa6, 0xae, 0x1f, 0x3f, 0x93, 0xc0, 0x02, 0x5a,
+ 0x00, 0x90, 0x81, 0xc0, 0x14, 0xa3, 0x00, 0x0e, 0x23, 0x50, 0xc0, 0xc0,
+ 0x12, 0x32, 0x23, 0x50, 0xc0, 0xc0, 0x12, 0x1d, 0x3d, 0x00, 0x98, 0xc0,
+ 0x9f, 0xb5, 0x83, 0xc0, 0x51, 0xb2, 0x15, 0x00, 0x57, 0xc0, 0x77, 0x00,
+ 0x00, 0x51, 0xc0, 0x74, 0x00, 0x72, 0xc0, 0xc0, 0x33, 0x7b, 0xc0, 0x57,
+ 0x08, 0x8b, 0xc0, 0xa1, 0x25, 0x73, 0x63, 0x50, 0x1b, 0x56, 0xc0, 0x33,
+ 0x7d, 0xc0, 0x57, 0x08, 0x8b, 0xc0, 0xa1, 0x42, 0x11, 0xa2, 0xbe, 0x33,
+ 0x00, 0x6c, 0xc0, 0x2a, 0x00, 0x5f, 0xa1, 0xc0, 0x85, 0x2f, 0x2c, 0x9e,
+ 0x1c, 0x74, 0x29, 0x65, 0x72, 0x32, 0x10, 0x0b, 0x00, 0x5f, 0xa1, 0xc0,
+ 0x85, 0xb2, 0x25, 0x73, 0x63, 0x50, 0x1b, 0x56, 0xab, 0x3d, 0x00, 0x98,
+ 0xc0, 0x9f, 0xb5, 0x90, 0xc0, 0x1b, 0x11, 0x00, 0x79, 0xb9, 0xb8, 0x98,
+ 0x5d, 0x0e, 0x00, 0x6e, 0x06, 0x9d, 0xc0, 0xc0, 0x09, 0x63, 0x00, 0x9d,
+ 0xc0, 0xc0, 0x09, 0x60, 0x00, 0x00, 0xa9, 0x71, 0x3d, 0xbc, 0x83, 0xc0,
+ 0x51, 0x3f, 0x00, 0x1b, 0xb9, 0xb2, 0x0a, 0x00, 0x3b, 0xbe, 0xc0, 0x2c,
+ 0x00, 0xac, 0xc0, 0xb9, 0x00, 0x89, 0x4a, 0x36, 0x27, 0x7d, 0x55, 0x60,
+ 0x02, 0x7b, 0x35, 0x69, 0x00, 0xa5, 0xa0, 0x00, 0xa5, 0x4a, 0x36, 0x27,
+ 0x7d, 0x55, 0x60, 0x08, 0x87, 0xc0, 0x51, 0x0d, 0x08, 0xb3, 0xac, 0x06,
+ 0x00, 0x99, 0xa9, 0x53, 0x45, 0x0b, 0x84, 0x15, 0x78, 0x95, 0x21, 0x5a,
+ 0x79, 0x07, 0x91, 0x06, 0x00, 0x99, 0xa9, 0x53, 0x45, 0xc0, 0x02, 0x7b,
+ 0x35, 0x69, 0x00, 0xa5, 0x9e, 0x08, 0x00, 0xa9, 0x71, 0x3d, 0xbc, 0x90,
+ 0xc0, 0x00, 0x1b, 0x83, 0x00, 0x0e, 0x17, 0x83, 0xc0, 0x32, 0x9f, 0xb0,
+ 0x63, 0x24, 0x54, 0x22, 0x9f, 0xb0, 0x63, 0x24, 0x54, 0x80, 0x00, 0x01,
+ 0x3b, 0xb9, 0x84, 0xc0, 0x2e, 0x17, 0x00, 0x90, 0xc0, 0x91, 0x00, 0x27,
+ 0xb8, 0xc0, 0xc0, 0x08, 0x00, 0xa4, 0x8d, 0x21, 0x00, 0x00, 0x17, 0xb1,
+ 0x0b, 0x00, 0x3f, 0xbf, 0x0e, 0x0c, 0xad, 0x1a, 0x00, 0x6a, 0x39, 0x16,
+ 0x00, 0x17, 0xb1, 0x0b, 0x00, 0x3f, 0xbf, 0x1c, 0xa8, 0x50, 0x23, 0x50,
+ 0x45, 0x5c, 0x81, 0x1b, 0x80, 0x00, 0x0b, 0x39, 0xbb, 0x0c, 0x00, 0x6a,
+ 0xc0, 0x39, 0x1d, 0x8b, 0x40, 0x00, 0x73, 0x81, 0x00, 0x09, 0x39, 0xbb,
+ 0xc0, 0x0e, 0x0c, 0xad, 0x1a, 0x00, 0x6a, 0x39, 0x80, 0x00, 0x01, 0x3b,
+ 0xb9, 0x91, 0xc0, 0x19, 0x9d, 0x37, 0x0e, 0x04, 0x17, 0x45, 0x8b, 0xbe,
+ 0xc0, 0xc0, 0xa4, 0x23, 0x0a, 0x51, 0xb8, 0xc0, 0xa4, 0x23, 0x0a, 0x51,
+ 0xb8, 0xc0, 0x37, 0x12, 0x69, 0xbe, 0x85, 0xc0, 0x06, 0x57, 0x43, 0xc0,
+ 0xc0, 0xaf, 0x23, 0xae, 0x80, 0xc0, 0x45, 0x0e, 0x00, 0x00, 0x11, 0x93,
+ 0x88, 0x19, 0x9e, 0xc0, 0x05, 0x3b, 0xbb, 0xc0, 0x49, 0x7d, 0xc0, 0x08,
+ 0x00, 0x4a, 0xbb, 0x88, 0x19, 0x9e, 0xc0, 0x05, 0x3b, 0xbb, 0xc0, 0x77,
+ 0x0c, 0x57, 0xae, 0x0d, 0x29, 0xa3, 0xc0, 0x85, 0x11, 0x14, 0x63, 0xbd,
+ 0xc0, 0x55, 0x48, 0xc0, 0xc0, 0x0c, 0x75, 0xc0, 0x0c, 0x00, 0x3d, 0x73,
+ 0x11, 0x14, 0x63, 0xbd, 0xc0, 0xc0, 0x49, 0x7d, 0xc0, 0x08, 0x00, 0x4a,
+ 0xbb, 0x37, 0x12, 0x69, 0xbe, 0xb4, 0xc0, 0x01, 0xbe, 0xbd, 0x85, 0xc0,
+ 0x03, 0x6e, 0x0b, 0x3f, 0xac, 0x82, 0xc0, 0x01, 0x9d, 0xbf, 0x82, 0xc0,
+ 0x01, 0x88, 0x92, 0x83, 0xc0, 0x01, 0x9d, 0xbf, 0x81, 0xc0, 0x03, 0xbb,
+ 0x44, 0x48, 0xba, 0x89, 0xc0, 0x04, 0xb8, 0xc0, 0xc0, 0x93, 0x9d, 0x88,
+ 0xc0, 0x01, 0x88, 0x92, 0xe1, 0xc0, 0x03, 0xb4, 0x2d, 0x1f, 0xbb, 0xff,
+ 0xc0, 0x03, 0xbb, 0x2c, 0x05, 0x9a, 0xff, 0xc0, 0x03, 0xc0, 0x65, 0x00,
+ 0x77, 0xff, 0xc0, 0x03, 0xc0, 0xc0, 0x30, 0x78, 0xff, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc8, 0xc0,
+};
+static EG_EMBEDDED_IMAGE egemb_refind_banner = { 135, 64, EG_EIPIXELMODE_COLOR, EG_EICOMPMODE_RLE, egemb_refind_banner_data, 7592 };
--- /dev/null
+#ifndef __REFIT_CALL_WRAPPER_H__
+#define __REFIT_CALL_WRAPPER_H__
+
+#ifdef EFIX64
+# define refit_call1_wrapper(f, a1) \
+ uefi_call_wrapper(f, 1, (UINT64)(a1))
+# define refit_call2_wrapper(f, a1, a2) \
+ uefi_call_wrapper(f, 2, (UINT64)(a1), (UINT64)(a2))
+# define refit_call3_wrapper(f, a1, a2, a3) \
+ uefi_call_wrapper(f, 3, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3))
+# define refit_call4_wrapper(f, a1, a2, a3, a4) \
+ uefi_call_wrapper(f, 4, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4))
+# define refit_call5_wrapper(f, a1, a2, a3, a4, a5) \
+ uefi_call_wrapper(f, 5, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), (UINT64)(a5))
+# define refit_call6_wrapper(f, a1, a2, a3, a4, a5, a6) \
+ uefi_call_wrapper(f, 6, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), (UINT64)(a5), (UINT64)(a6))
+# define refit_call10_wrapper(f, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ uefi_call_wrapper(f, 10, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), (UINT64)(a9), (UINT64)(a10))
+#else
+# define refit_call1_wrapper(f, a1) \
+ uefi_call_wrapper(f, 1, a1)
+# define refit_call2_wrapper(f, a1, a2) \
+ uefi_call_wrapper(f, 2, a1, a2)
+# define refit_call3_wrapper(f, a1, a2, a3) \
+ uefi_call_wrapper(f, 3, a1, a2, a3)
+# define refit_call4_wrapper(f, a1, a2, a3, a4) \
+ uefi_call_wrapper(f, 4, a1, a2, a3, a4)
+# define refit_call5_wrapper(f, a1, a2, a3, a4, a5) \
+ uefi_call_wrapper(f, 5, a1, a2, a3, a4, a5)
+# define refit_call6_wrapper(f, a1, a2, a3, a4, a5, a6) \
+ uefi_call_wrapper(f, 6, a1, a2, a3, a4, a5, a6)
+# define refit_call10_wrapper(f, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ uefi_call_wrapper(f, 10, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+#endif
+
+#endif /* !__REFIT_CALL_WRAPPER_H__ */
+
--- /dev/null
+/*
+ * include/syslinux_mbr.h
+ * MBR boot code
+ *
+ * The boot code in this file was taken from syslinux-3.11. It is covered
+ * by the following license:
+ *
+ ; -----------------------------------------------------------------------
+ ;
+ ; Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
+ ;
+ ; Permission is hereby granted, free of charge, to any person
+ ; obtaining a copy of this software and associated documentation
+ ; files (the "Software"), to deal in the Software without
+ ; restriction, including without limitation the rights to use,
+ ; copy, modify, merge, publish, distribute, sublicense, and/or
+ ; sell copies of the Software, and to permit persons to whom
+ ; the Software is furnished to do so, subject to the following
+ ; conditions:
+ ;
+ ; The above copyright notice and this permission notice shall
+ ; be included in all copies or substantial portions of the Software.
+ ;
+ ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ ; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ ; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ ; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ ; OTHER DEALINGS IN THE SOFTWARE.
+ ;
+ ; -----------------------------------------------------------------------
+ *
+ */
+
+#ifndef __SYSLINUX_MBR_H__
+#define __SYSLINUX_MBR_H__
+
+
+#define MBR_BOOTCODE_SIZE (440)
+
+
+#define SYSLINUX_MBR_SIZE (304)
+
+static UINT8 syslinux_mbr[SYSLINUX_MBR_SIZE] = {
+ 0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0x8e,
+ 0xd0, 0xbc, 0x00, 0x7c, 0xfb, 0xfc, 0x89, 0xe6,
+ 0xbf, 0x00, 0x06, 0xb9, 0x00, 0x01, 0xf3, 0xa5,
+ 0xea, 0x1d, 0x06, 0x00, 0x00, 0x88, 0x16, 0x00,
+ 0x08, 0xb4, 0x08, 0xcd, 0x13, 0x31, 0xc0, 0x88,
+ 0xf0, 0x40, 0xa3, 0xf0, 0x06, 0x80, 0xe1, 0x3f,
+ 0x88, 0x0e, 0xf2, 0x06, 0xbe, 0xbe, 0x07, 0x31,
+ 0xc0, 0xb9, 0x04, 0x00, 0xf6, 0x04, 0x80, 0x74,
+ 0x03, 0x40, 0x89, 0xf7, 0x83, 0xc6, 0x10, 0xe2,
+ 0xf3, 0x83, 0xf8, 0x01, 0x75, 0x73, 0x8a, 0x16,
+ 0x00, 0x08, 0xb8, 0x00, 0x41, 0xbb, 0xaa, 0x55,
+ 0x31, 0xc9, 0x30, 0xf6, 0xf9, 0xcd, 0x13, 0x72,
+ 0x23, 0x81, 0xfb, 0x55, 0xaa, 0x75, 0x1d, 0xf6,
+ 0xc1, 0x01, 0x74, 0x18, 0x57, 0xbe, 0xe0, 0x06,
+ 0x8b, 0x5d, 0x08, 0x89, 0x5c, 0x08, 0x8b, 0x5d,
+ 0x0a, 0x89, 0x5c, 0x0a, 0x8a, 0x16, 0x00, 0x08,
+ 0xb4, 0x42, 0xeb, 0x2a, 0x57, 0x8b, 0x45, 0x08,
+ 0x8b, 0x55, 0x0a, 0xf7, 0x36, 0xf2, 0x06, 0x42,
+ 0x89, 0xd1, 0x31, 0xd2, 0xf7, 0x36, 0xf0, 0x06,
+ 0x88, 0xc5, 0xd1, 0xe8, 0xd1, 0xe8, 0x24, 0xc0,
+ 0x08, 0xc1, 0x88, 0xd6, 0x8a, 0x16, 0x00, 0x08,
+ 0xbb, 0x00, 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13,
+ 0x72, 0x16, 0x5e, 0x81, 0x3e, 0xfe, 0x7d, 0x55,
+ 0xaa, 0x75, 0x08, 0xfa, 0xea, 0x00, 0x7c, 0x00,
+ 0x00, 0x77, 0x05, 0xbe, 0xf4, 0x06, 0xeb, 0x03,
+ 0xbe, 0x0f, 0x07, 0xac, 0x20, 0xc0, 0x74, 0x0c,
+ 0xb4, 0x0e, 0x8a, 0x3e, 0x62, 0x04, 0xb3, 0x07,
+ 0xcd, 0x10, 0xeb, 0xef, 0xeb, 0xfe, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x73, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x70, 0x65, 0x72,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x0d, 0x0a, 0x00, 0x4f,
+ 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67,
+ 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20,
+ 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x00
+};
+
+
+#endif /* __SYSLINUX_MBR_H__ */
+
+/* EOF */
--- /dev/null
+#!/bin/bash
+#
+# Script to create a bootable CD image file containing rEFInd.
+# Usage:
+#
+# ./mkcdimage {version}
+#
+# where {version} is the rEFInd version number.
+#
+# This script relies on the mcopy utility.
+#
+# The script creates an image file from the binary package
+# stored in ../snapshots/{version}/refind-bin-{version}.zip
+# The resulting CD image file is stored in
+# ../snapshots/{version}/refind-cd-{version}.iso
+
+StartDir=`pwd`
+Version=$1
+
+# Unzip the binary archive file....
+cd ../snapshots/$Version
+rm -rf temp
+mkdir temp
+cd temp
+unzip ../refind-bin-$Version.zip
+
+# Create hard links to the files so that they'll be suitable for an
+# EFI-boot CD...
+mkdir -p refind-bin-$Version/EFI/boot
+cd refind-bin-$Version/EFI/boot
+ln ../../refind/refind_ia32.efi ./bootia32.efi
+ln ../../refind/refind_x64.efi ./bootx64.efi
+ln ../../refind/refind.conf-sample ./refind.conf
+mkdir icons
+cd icons
+ln ../../../refind/icons/* ./
+cd ../../..
+
+# Get the size of the binaries to go in the El Torito image in kB
+ToritoSize=`du -s EFI | cut -f 1`
+let ToritoSize=($ToritoSize)/28
+let ToritoSize=($ToritoSize)*32
+
+# Prepare a FAT filesystem image and populate it with the
+# EFI boot files....
+dd if=/dev/zero of=refind-bin-$Version.img bs=1024 count=$ToritoSize
+mkdosfs -n "rEFInd.ET" refind-bin-$Version.img
+mcopy -irefind-bin-$Version.img -s EFI ::/
+
+# Make the ISO-9660 image file....
+mkisofs -A "Bootable rEFInd" -V "rEFInd $Version" -volset "rEFInd $Version" \
+ -J -r -v -x ./lost+found -o ../../refind-cd-$Version.iso \
+ -b refind-bin-$Version.img -c boot.cat -no-emul-boot -boot-load-size 4 \
+ -eltorito-alt-boot -efi-boot refind-bin-$Version.img \
+ -no-emul-boot ./
+
+cd ../../
+rm -r temp/
--- /dev/null
+#!/bin/bash
+#
+# Script to prepare source code and binary distribution files of rEFInd.
+# By Rod Smith, 3/11/2012
+#
+# Usage: ./mkdistrib version
+# where "version" is a version number
+# MUST be run from an x86-64 system, on which the current IA32 build
+# (refind_ia32.efi) is already present in the same directory as this script
+
+
+StartDir=`pwd`
+
+make clean
+
+# Prepare a place and copy files there....
+mkdir -p ../snapshots/$1/refind-$1/icons
+cp --preserve=timestamps icons/*icns ../snapshots/$1/refind-$1/icons/
+cp -a docs images include libeg refind NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1
+
+# Go there are prepare a souce code zip file....
+cd ../snapshots/$1/
+zip -9r refind-src-$1.zip refind-$1
+
+# Build the source code into a binary
+cd refind-$1
+make
+mkdir -p refind-bin-$1/refind
+cp -a icons refind-bin-$1/refind/
+cp --preserve=timestamps refind.conf-sample refind-bin-$1/refind/
+cp refind/refind.efi refind-bin-$1/refind/refind_x64.efi
+cp $StartDir/refind_ia32.efi refind-bin-$1/refind/
+cp -a COPYING.txt LICENSE.txt README.txt docs refind-bin-$1
+zip -9r ../refind-bin-$1.zip refind-bin-$1
+cd ..
+rm -r refind-$1
+cd $StartDir
--- /dev/null
+#
+# refind.conf
+# Configuration file for the rEFInd boot menu
+#
+
+# Timeout in seconds for the main menu screen. Setting the timeout to 0
+# disables automatic booting (i.e., no timeout).
+#
+timeout 20
+
+# Disable menu options for increased security. These are intended for a lab
+# environment where the administrator doesn't want users to mess with the
+# operating system. List the names for the options you want to hide from
+# the boot menu. Currently supported:
+# shell - remove the EFI shell
+# tools - remove all EFI tools (shell and gptsync)
+# singleuser - remove the submenu options to boot Mac OS X in single-user
+# or verbose modes
+# hwtest - remove the submenu option to run Apple Hardware Test
+# all - all of the above
+#
+#disable shell singleuser
+#disable all
+
+# Use a custom title banner instead of the rEFInd icon and name. The file
+# path is relative to the directory where refind.efi is located. The color
+# in the top left corner of the image is used as the background color
+# for the menu screens. Currently uncompressed BMP images with color
+# depths of 24, 8, 4 or 1 bits are supported.
+#
+#banner hostname.bmp
+
+# Custom images for the selection background. There is a big one (144 x 144)
+# for the OS icons, and a small one (64 x 64) for the function icons in the
+# second row. If only a small image is given, that one is also used for
+# the big icons by stretching it in the middle. If only a big one is given,
+# the built-in default will be used for the small icons.
+#
+# Like the banner option above, these options take a filename of
+# an uncompressed BMP image file.
+#
+#selection_big selection-big.bmp
+#selection_small selection-small.bmp
+
+# Hide various user interface elements. Here you can list the names of
+# interface elements to hide. Currently supported:
+# banner - the rEFInd title banner
+# shell - the EFI shell icon
+# tools - all EFI tools (shell and gptsync)
+# funcs - built-in functions (about, restart)
+# ('tools' and 'funcs' together hide the complete second row of icons.)
+# label - text label in the menu
+# badges - all volume badges (same as 'hidebadges all'); this setting
+# is not recommended because it won't let you distinguish
+# installed OSes and bootable CDs/DVDs.
+# all - all of the above, except for 'badges'
+#
+# Note: The 'shell' and 'tools' options are equivalent to the 'disable'
+# options with the same names.
+#
+#hideui tools funcs hdbadges
+#hideui all
+
+# Use text mode only. When enabled, this option forces rEFInd into text mode.
+#
+#textonly
+
+# Which types of boot loaders to search:
+# internal - internal EFI disk-based boot loaders
+# external - external EFI disk-based boot loaders
+# optical - EFI optical discs (CD, DVD, etc.)
+# hdbios - BIOS disk-based boot loaders
+# biosexternal - BIOS external boot loaders (USB, eSATA, etc.)
+# cd - BIOS optical-disc boot loaders
+# manual - use stanzas later in this configuration file
+# Default is internal,external,optical
+scanfor internal,external,optical
+
+# Set the default menu selection. The available arguments match the
+# keyboard accelerators available within rEFInd. You may select the default
+# loader using a one-character abbreviation for the OS name ("M" = Mac OS X,
+# "L" = Linux, "W" = Windows). You may also specify a digit between 1 and
+# 9, in which case the Nth loader in the menu will be the default. You can
+# also select a rEFInd tool entry ("S" = EFI Shell, "P" = Partitioning Tool,
+# "U" = shutdown). This is intended as a quick fix to change the default
+# boot choice until full configurability arrives.
+#
+#default_selection 1
+
+# Sample manual configuration stanzas. Each begins with the "menuentry"
+# keyword followed by a name that's to appear in the menu (use quotes
+# if you want the name to contain a space) and an open curly brace
+# ("{"). Each entry ends with a close curly brace ("}"). Common
+# keywords within each stanza include:
+#
+# loader - identifies the boot loader file
+# initrd - Specifies an initial RAM disk file
+# icon - specifies a custom boot loader icon
+# ostype - OS type code to determine boot options available by
+# pressing Insert. Valid values are "MacOS", "Linux",
+# "Windows", and "XOM". Case-sensitive.
+# graphics - set to "on" to enable graphics-mode boot (useful
+# mainly for MacOS) or "off" for text-mode boot.
+# Default is auto-detected from loader filename.
+# options - sets options to be passed to the boot loader; use
+# quotes if more than one option should be passed or
+# if any options use characters that might be changed
+# by rEFInd parsing procedures (=, /, #, or tab).
+# disabled - use alone or set to "yes" to disable this entry.
+#
+# Note that you can use either DOS/Windows/EFI-style backslashes (\)
+# or Unix-style forward slashes (/) as directory separators. Either
+# way, all file references are on the ESP from which rEFInd was
+# launched.
+# Use of quotes around parameters causes them to be interpreted as
+# one keyword, and for parsing of special characters (spaces, =, /,
+# and #) to be disabled. This is useful mainly with the "options"
+# keyword. Use of quotes around parameters that specify filenames is
+# permissible, but you must then use backslashes instead of slashes,
+# except when you must pass a forward slash to the loader, as when
+# passing a root= option to a Linux kernel.
+
+# Below are several sample boot stanzas. All are disabled by default.
+# Find one similar to what you need, copy it, remove the "disabled" line,
+# and adjust the entries to suit your needs.
+
+# A sample entry for a Linux 3.3 kernel with its new EFI boot stub
+# support. This includes Linux-specific boot options and specification
+# of an initial RAM disk. Note uses of Linux-style forward slashes,
+# even in the initrd specification. Also note that a leading slash is
+# optional in file specifications.
+menuentry Linux {
+ loader EFI/Linux/bzImage-3.3.0-rc7
+ initrd EFI/Linux/initrd-3.3.0.img
+ icon EFI/refind/icons/os_linux.icns
+ options "ro root=UUID=5f96cafa-e0a7-4057-b18f-fa709db5b837"
+ disabled
+}
+
+# A sample entry for loading Ubuntu using its standard name for
+# its GRUB 2 boot loader. Note uses of Linux-style forward slashes
+menuentry Ubuntu {
+ loader /EFI/ubuntu/grubx64.efi
+ icon /EFI/refined/icons/os_linux.icns
+ disabled
+}
+
+# A minimal ELILO entry, which probably offers nothing that
+# auto-detection can't accomplish.
+menuentry "ELILO" {
+ loader \EFI\elilo\elilo.efi
+ disabled
+}
+
+# Like the ELILO entry, this one offers nothing that auto-detection
+# can't do; but you might use it if you want to disable auto-detection
+# but still boot Windows....
+menuentry "Windows 7" {
+ loader \EFI\Microsoft\Boot\bootmgfw.efi
+ disabled
+}
+
+# EOF
--- /dev/null
+#
+# refind/Makefile
+# Build control file for the rEFInd boot menu
+#
+
+SRCDIR = .
+
+VPATH = $(SRCDIR)
+
+ifeq ($(ARCH),ia32)
+ LIBEG = build32
+endif
+
+ifeq ($(ARCH),x86_64)
+ LIBEG = build64
+endif
+
+LOCAL_CPPFLAGS = -I$(SRCDIR) -I$(SRCDIR)/../include -I$(SRCDIR)/../libeg -DDEBIAN_VERSION="L\"$(DEBVER)\""
+LOCAL_LDFLAGS = -L$(SRCDIR)/../libeg/$(LIBEG)
+LOCAL_LIBS = -leg
+
+OBJS = main.o config.o menu.o screen.o icns.o lib.o
+TARGET = refind.efi
+
+all: $(TARGET)
+
+include $(SRCDIR)/../Make.common
+
+# EOF
+# DO NOT DELETE
--- /dev/null
+/*
+ * refit/config.c
+ * Configuration file functions
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#include "global.h"
+#include "lib.h"
+#include "icns.h"
+#include "menu.h"
+#include "config.h"
+#include "screen.h"
+#include "refit_call_wrapper.h"
+
+// constants
+
+#define CONFIG_FILE_NAME L"refind.conf"
+#define LINUX_OPTIONS_FILENAME L"linux.conf"
+#define MAXCONFIGFILESIZE (128*1024)
+
+#define ENCODING_ISO8859_1 (0)
+#define ENCODING_UTF8 (1)
+#define ENCODING_UTF16_LE (2)
+
+static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
+
+//
+// read a file into a buffer
+//
+
+static EFI_STATUS ReadFile(IN EFI_FILE_HANDLE BaseDir, CHAR16 *FileName, REFIT_FILE *File)
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE FileHandle;
+ EFI_FILE_INFO *FileInfo;
+ UINT64 ReadSize;
+
+ File->Buffer = NULL;
+ File->BufferSize = 0;
+
+ // read the file, allocating a buffer on the way
+ Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
+ if (CheckError(Status, L"while loading the configuration file"))
+ return Status;
+
+ FileInfo = LibFileInfo(FileHandle);
+ if (FileInfo == NULL) {
+ // TODO: print and register the error
+ refit_call1_wrapper(FileHandle->Close, FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+ ReadSize = FileInfo->FileSize;
+ if (ReadSize > MAXCONFIGFILESIZE)
+ ReadSize = MAXCONFIGFILESIZE;
+ FreePool(FileInfo);
+
+ File->BufferSize = (UINTN)ReadSize; // was limited to a few K before, so this is safe
+ File->Buffer = AllocatePool(File->BufferSize);
+ Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &File->BufferSize, File->Buffer);
+ if (CheckError(Status, L"while loading the configuration file")) {
+ FreePool(File->Buffer);
+ File->Buffer = NULL;
+ refit_call1_wrapper(FileHandle->Close, FileHandle);
+ return Status;
+ }
+ Status = refit_call1_wrapper(FileHandle->Close, FileHandle);
+
+ // setup for reading
+ File->Current8Ptr = (CHAR8 *)File->Buffer;
+ File->End8Ptr = File->Current8Ptr + File->BufferSize;
+ File->Current16Ptr = (CHAR16 *)File->Buffer;
+ File->End16Ptr = File->Current16Ptr + (File->BufferSize >> 1);
+
+ // detect encoding
+ File->Encoding = ENCODING_ISO8859_1; // default: 1:1 translation of CHAR8 to CHAR16
+ if (File->BufferSize >= 4) {
+ if (File->Buffer[0] == 0xFF && File->Buffer[1] == 0xFE) {
+ // BOM in UTF-16 little endian (or UTF-32 little endian)
+ File->Encoding = ENCODING_UTF16_LE; // use CHAR16 as is
+ File->Current16Ptr++;
+ } else if (File->Buffer[0] == 0xEF && File->Buffer[1] == 0xBB && File->Buffer[2] == 0xBF) {
+ // BOM in UTF-8
+ File->Encoding = ENCODING_UTF8; // translate from UTF-8 to UTF-16
+ File->Current8Ptr += 3;
+ } else if (File->Buffer[1] == 0 && File->Buffer[3] == 0) {
+ File->Encoding = ENCODING_UTF16_LE; // use CHAR16 as is
+ }
+ // TODO: detect other encodings as they are implemented
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// get a single line of text from a file
+//
+
+static CHAR16 *ReadLine(REFIT_FILE *File)
+{
+ CHAR16 *Line, *q;
+ UINTN LineLength;
+
+ if (File->Buffer == NULL)
+ return NULL;
+
+ if (File->Encoding == ENCODING_ISO8859_1 || File->Encoding == ENCODING_UTF8) {
+
+ CHAR8 *p, *LineStart, *LineEnd;
+
+ p = File->Current8Ptr;
+ if (p >= File->End8Ptr)
+ return NULL;
+
+ LineStart = p;
+ for (; p < File->End8Ptr; p++)
+ if (*p == 13 || *p == 10)
+ break;
+ LineEnd = p;
+ for (; p < File->End8Ptr; p++)
+ if (*p != 13 && *p != 10)
+ break;
+ File->Current8Ptr = p;
+
+ LineLength = (UINTN)(LineEnd - LineStart) + 1;
+ Line = AllocatePool(LineLength * sizeof(CHAR16));
+ if (Line == NULL)
+ return NULL;
+
+ q = Line;
+ if (File->Encoding == ENCODING_ISO8859_1) {
+ for (p = LineStart; p < LineEnd; )
+ *q++ = *p++;
+ } else if (File->Encoding == ENCODING_UTF8) {
+ // TODO: actually handle UTF-8
+ for (p = LineStart; p < LineEnd; )
+ *q++ = *p++;
+ }
+ *q = 0;
+
+ } else if (File->Encoding == ENCODING_UTF16_LE) {
+
+ CHAR16 *p, *LineStart, *LineEnd;
+
+ p = File->Current16Ptr;
+ if (p >= File->End16Ptr)
+ return NULL;
+
+ LineStart = p;
+ for (; p < File->End16Ptr; p++)
+ if (*p == 13 || *p == 10)
+ break;
+ LineEnd = p;
+ for (; p < File->End16Ptr; p++)
+ if (*p != 13 && *p != 10)
+ break;
+ File->Current16Ptr = p;
+
+ LineLength = (UINTN)(LineEnd - LineStart) + 1;
+ Line = AllocatePool(LineLength * sizeof(CHAR16));
+ if (Line == NULL)
+ return NULL;
+
+ for (p = LineStart, q = Line; p < LineEnd; )
+ *q++ = *p++;
+ *q = 0;
+
+ } else
+ return NULL; // unsupported encoding
+
+ return Line;
+}
+
+//
+// get a line of tokens from a file
+//
+
+UINTN ReadTokenLine(IN REFIT_FILE *File, OUT CHAR16 ***TokenList)
+{
+ BOOLEAN LineFinished, IsQuoted = FALSE;
+ CHAR16 *Line, *Token, *p;
+ UINTN TokenCount = 0;
+
+ *TokenList = NULL;
+
+ while (TokenCount == 0) {
+ Line = ReadLine(File);
+ if (Line == NULL)
+ return(0);
+
+ p = Line;
+ LineFinished = FALSE;
+ while (!LineFinished) {
+ // skip whitespace
+ while ((*p == ' ' || *p == '\t' || *p == '=' || *p == ',') && !IsQuoted)
+ p++;
+ if (*p == 0 || *p == '#')
+ break;
+
+ if (*p == '"') {
+ IsQuoted = !IsQuoted;
+ p++;
+ } // if
+ Token = p;
+
+ // find end of token
+ while (*p && *p != '"' && ((*p != ' ' && *p != '\t' && *p != '=' && *p != '#' && *p != ',') || IsQuoted)) {
+ if ((*p == '/') && !IsQuoted) // Switch Unix-style to DOS-style directory separators
+ *p = '\\';
+ p++;
+ } // if
+ if (*p == '"')
+ IsQuoted = !IsQuoted;
+ if (*p == 0 || *p == '#')
+ LineFinished = TRUE;
+ *p++ = 0;
+
+ AddListElement((VOID ***)TokenList, &TokenCount, (VOID *)StrDuplicate(Token));
+ }
+
+ FreePool(Line);
+ }
+ return (TokenCount);
+} /* ReadTokenLine() */
+
+VOID FreeTokenLine(IN OUT CHAR16 ***TokenList, IN OUT UINTN *TokenCount)
+{
+ // TODO: also free the items
+ FreeList((VOID ***)TokenList, TokenCount);
+}
+
+//
+// handle a parameter with a single integer argument
+//
+
+static VOID HandleInt(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT UINTN *Value)
+{
+ if (TokenCount < 2) {
+ return;
+ }
+ if (TokenCount > 2) {
+ return;
+ }
+ *Value = Atoi(TokenList[1]);
+}
+
+//
+// handle a parameter with a single string argument
+//
+
+static VOID HandleString(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT CHAR16 **Value)
+{
+ if (TokenCount < 2) {
+ return;
+ }
+ if (TokenCount > 2) {
+ return;
+ }
+ *Value = StrDuplicate(TokenList[1]);
+}
+
+//
+// read config file
+//
+
+VOID ReadConfig(VOID)
+{
+ EFI_STATUS Status;
+ REFIT_FILE File;
+ CHAR16 **TokenList;
+ CHAR16 *FlagName;
+ UINTN TokenCount, i;
+
+ if (!FileExists(SelfDir, CONFIG_FILE_NAME)) {
+ Print(L"Configuration file missing!\n");
+ return;
+ }
+
+ Status = ReadFile(SelfDir, CONFIG_FILE_NAME, &File);
+ if (EFI_ERROR(Status))
+ return;
+
+ for (;;) {
+ TokenCount = ReadTokenLine(&File, &TokenList);
+ if (TokenCount == 0)
+ break;
+
+ if (StriCmp(TokenList[0], L"timeout") == 0) {
+ HandleInt(TokenList, TokenCount, &(GlobalConfig.Timeout));
+
+ } else if (StriCmp(TokenList[0], L"disable") == 0) {
+ for (i = 1; i < TokenCount; i++) {
+ FlagName = TokenList[i];
+ if (StriCmp(FlagName, L"shell") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_SHELL;
+ } else if (StriCmp(FlagName, L"tools") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_TOOLS;
+ } else if (StriCmp(FlagName, L"singleuser") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_SINGLEUSER;
+ } else if (StriCmp(FlagName, L"hwtest") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_HWTEST;
+ } else if (StriCmp(FlagName, L"all") == 0) {
+ GlobalConfig.DisableFlags = DISABLE_ALL;
+ } else {
+ Print(L" unknown disable flag: '%s'\n", FlagName);
+ }
+ }
+
+ } else if (StriCmp(TokenList[0], L"scanfor") == 0) {
+ for (i = 0; i < NUM_SCAN_OPTIONS; i++) {
+ if (i < TokenCount)
+ GlobalConfig.ScanFor[i] = TokenList[i][0];
+ else
+ GlobalConfig.ScanFor[i] = ' ';
+ }
+ } else if (StriCmp(TokenList[0], L"hideui") == 0) {
+ for (i = 1; i < TokenCount; i++) {
+ FlagName = TokenList[i];
+ if (StriCmp(FlagName, L"banner") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_BANNER;
+ } else if (StriCmp(FlagName, L"shell") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_SHELL;
+ } else if (StriCmp(FlagName, L"tools") == 0) {
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_TOOLS;
+ } else if (StriCmp(FlagName, L"funcs") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_FUNCS;
+ } else if (StriCmp(FlagName, L"label") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_LABEL;
+ } else if (StriCmp(FlagName, L"all") == 0) {
+ GlobalConfig.HideUIFlags = HIDEUI_ALL;
+ GlobalConfig.DisableFlags |= DISABLE_FLAG_SHELL | DISABLE_FLAG_TOOLS;
+ } else {
+ Print(L" unknown hideui flag: '%s'\n", FlagName);
+ }
+ }
+
+ } else if (StriCmp(TokenList[0], L"banner") == 0) {
+ HandleString(TokenList, TokenCount, &(GlobalConfig.BannerFileName));
+
+ } else if (StriCmp(TokenList[0], L"selection_small") == 0) {
+ HandleString(TokenList, TokenCount, &(GlobalConfig.SelectionSmallFileName));
+
+ } else if (StriCmp(TokenList[0], L"selection_big") == 0) {
+ HandleString(TokenList, TokenCount, &(GlobalConfig.SelectionBigFileName));
+
+ } else if (StriCmp(TokenList[0], L"default_selection") == 0) {
+ HandleString(TokenList, TokenCount, &(GlobalConfig.DefaultSelection));
+
+ } else if (StriCmp(TokenList[0], L"textonly") == 0) {
+ GlobalConfig.TextOnly = TRUE;
+
+ } else if ((StriCmp(TokenList[0], L"}") == 0) || (StriCmp(TokenList[0], L"loader") == 0) ||
+ (StriCmp(TokenList[0], L"icon") == 0) || (StriCmp(TokenList[0], L"options") == 0)) {
+ // Do nothing; handled by ScanUserConfigured()
+ }
+
+ FreeTokenLine(&TokenList, &TokenCount);
+ }
+
+ FreePool(File.Buffer);
+} /* VOID ReadConfig() */
+
+static VOID AddSubmenu(LOADER_ENTRY *Entry, REFIT_FILE *File, REFIT_VOLUME *Volume, CHAR16 *Title) {
+ REFIT_MENU_SCREEN *SubScreen;
+ LOADER_ENTRY *SubEntry;
+ UINTN TokenCount;
+ CHAR16 **TokenList;
+
+ SubScreen = InitializeSubScreen(Entry);
+
+ // Set defaults for the new entry; will be modified based on lines read from the config. file....
+ SubEntry = InitializeLoaderEntry(Entry);
+
+ if ((SubEntry == NULL) || (SubScreen == NULL))
+ return;
+ SubEntry->me.Title = StrDuplicate(Title);
+
+ while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StriCmp(TokenList[0], L"}") != 0)) {
+ if ((StriCmp(TokenList[0], L"loader") == 0) && (TokenCount > 1)) { // set the boot loader filename
+ if (SubEntry->LoaderPath != NULL)
+ FreePool(SubEntry->LoaderPath);
+ SubEntry->LoaderPath = StrDuplicate(TokenList[1]);
+ SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath);
+ } else if (StriCmp(TokenList[0], L"initrd") == 0) {
+ if (SubEntry->InitrdPath != NULL)
+ FreePool(SubEntry->InitrdPath);
+ SubEntry->InitrdPath = NULL;
+ if (TokenCount > 1) {
+ SubEntry->InitrdPath = StrDuplicate(TokenList[1]);
+ }
+ } else if (StriCmp(TokenList[0], L"options") == 0) {
+ if (SubEntry->LoadOptions != NULL)
+ FreePool(SubEntry->LoadOptions);
+ SubEntry->LoadOptions = NULL;
+ if (TokenCount > 1) {
+ SubEntry->LoadOptions = StrDuplicate(TokenList[1]);
+ } // if/else
+ } else if ((StriCmp(TokenList[0], L"add_options") == 0) && (TokenCount > 1)) {
+ MergeStrings(&SubEntry->LoadOptions, TokenList[1], L' ');
+ } else if ((StriCmp(TokenList[0], L"graphics") == 0) && (TokenCount > 1)) {
+ SubEntry->UseGraphicsMode = (StriCmp(TokenList[1], L"on") == 0);
+ } else if (StriCmp(TokenList[0], L"disabled") == 0) {
+ SubEntry->Enabled = FALSE;
+ } // ief/elseif
+ FreeTokenLine(&TokenList, &TokenCount);
+ } // while()
+ if (SubEntry->InitrdPath != NULL) {
+ MergeStrings(&SubEntry->LoadOptions, L"initrd=", L' ');
+ MergeStrings(&SubEntry->LoadOptions, SubEntry->InitrdPath, 0);
+ FreePool(SubEntry->InitrdPath);
+ SubEntry->InitrdPath = NULL;
+ } // if
+ if (SubEntry->Enabled == TRUE) {
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+ Entry->me.SubScreen = SubScreen;
+} // VOID AddSubmenu()
+
+// Adds the options from a SINGLE loaders.conf stanza to a new loader entry and returns
+// that entry. The calling function is then responsible for adding the entry to the
+// list of entries.
+static LOADER_ENTRY * AddStanzaEntries(REFIT_FILE *File, REFIT_VOLUME *Volume, CHAR16 *Title) {
+ CHAR16 **TokenList;
+ UINTN TokenCount;
+ LOADER_ENTRY *Entry;
+ BOOLEAN DefaultsSet = FALSE, AddedSubmenu = FALSE;
+
+ // prepare the menu entry
+ Entry = InitializeLoaderEntry(NULL);
+ if (Entry == NULL)
+ return NULL;
+
+ Entry->Title = StrDuplicate(Title);
+ Entry->me.Title = PoolPrint(L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
+ Entry->me.Row = 0;
+ Entry->me.BadgeImage = Volume->VolBadgeImage;
+ Entry->VolName = Volume->VolName;
+
+ // Parse the config file to add options for a single stanza, terminating when the token
+ // is "}" or when the end of file is reached.
+ while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StriCmp(TokenList[0], L"}") != 0)) {
+ if ((StriCmp(TokenList[0], L"loader") == 0) && (TokenCount > 1)) { // set the boot loader filename
+ Entry->LoaderPath = StrDuplicate(TokenList[1]);
+ Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath);
+ SetLoaderDefaults(Entry, TokenList[1], Volume);
+ FreePool(Entry->LoadOptions);
+ Entry->LoadOptions = NULL; // Discard default options, if any
+ DefaultsSet = TRUE;
+ } else if ((StriCmp(TokenList[0], L"icon") == 0) && (TokenCount > 1)) {
+ FreePool(Entry->me.Image);
+ Entry->me.Image = LoadIcns(Volume->RootDir, TokenList[1], 128);
+ if (Entry->me.Image == NULL) {
+ Entry->me.Image = DummyImage(128);
+ }
+ } else if ((StriCmp(TokenList[0], L"initrd") == 0) && (TokenCount > 1)) {
+ if (Entry->InitrdPath)
+ FreePool(Entry->InitrdPath);
+ Entry->InitrdPath = StrDuplicate(TokenList[1]);
+ } else if ((StriCmp(TokenList[0], L"options") == 0) && (TokenCount > 1)) {
+ if (Entry->LoadOptions)
+ FreePool(Entry->LoadOptions);
+ Entry->LoadOptions = StrDuplicate(TokenList[1]);
+ } else if ((StriCmp(TokenList[0], L"ostype") == 0) && (TokenCount > 1)) {
+ if (TokenCount > 1) {
+ Entry->OSType = TokenList[1][0];
+ }
+ } else if ((StriCmp(TokenList[0], L"graphics") == 0) && (TokenCount > 1)) {
+ Entry->UseGraphicsMode = (StriCmp(TokenList[1], L"on") == 0);
+ } else if (StriCmp(TokenList[0], L"disabled") == 0) {
+ Entry->Enabled = FALSE;
+ } else if ((StriCmp(TokenList[0], L"submenuentry") == 0) && (TokenCount > 1)) {
+ AddSubmenu(Entry, File, Volume, TokenList[1]);
+ AddedSubmenu = TRUE;
+ } // set options to pass to the loader program
+ FreeTokenLine(&TokenList, &TokenCount);
+ } // while()
+
+ if (AddedSubmenu)
+ AddMenuEntry(Entry->me.SubScreen, &MenuEntryReturn);
+
+ if (Entry->InitrdPath) {
+ MergeStrings(&Entry->LoadOptions, L"initrd=", L' ');
+ MergeStrings(&Entry->LoadOptions, Entry->InitrdPath, 0);
+ FreePool(Entry->InitrdPath);
+ Entry->InitrdPath = NULL;
+ } // if
+
+ if (!DefaultsSet)
+ SetLoaderDefaults(Entry, L"\\EFI\\BOOT\\nemo.efi", Volume); // user included no entry; use bogus one
+
+ return(Entry);
+} // static VOID AddStanzaEntries()
+
+// Read the user-configured loaders file, loaders.conf, and add or delete
+// entries based on the contents of that file....
+VOID ScanUserConfigured(VOID)
+{
+ EFI_STATUS Status;
+ REFIT_FILE File;
+ REFIT_VOLUME *Volume;
+ CHAR16 **TokenList;
+ CHAR16 *Title = NULL;
+ UINTN TokenCount;
+ LOADER_ENTRY *Entry;
+
+ if (FileExists(SelfDir, CONFIG_FILE_NAME)) {
+ Status = ReadFile(SelfDir, CONFIG_FILE_NAME, &File);
+ if (EFI_ERROR(Status))
+ return;
+
+ Volume = SelfVolume;
+ // TODO: Figure out how to set volumes (on per-image basis, preferably)
+
+ while ((TokenCount = ReadTokenLine(&File, &TokenList)) > 0) {
+ if ((StriCmp(TokenList[0], L"menuentry") == 0) && (TokenCount > 1)) {
+ Title = StrDuplicate(TokenList[1]);
+ Entry = AddStanzaEntries(&File, Volume, TokenList[1]);
+ if (Entry->Enabled) {
+ if (Entry->me.SubScreen == NULL)
+ GenerateSubScreen(Entry, Volume);
+ AddPreparedLoaderEntry(Entry);
+ } else {
+ FreePool(Entry);
+ } // if/else
+ FreePool(Title);
+ } // if
+ FreeTokenLine(&TokenList, &TokenCount);
+ } // while()
+ } // if()
+} // VOID ScanUserConfigured()
+
+// Read a Linux kernel options file for a Linux boot loader into memory. The LoaderPath
+// and Volume variables identify the location of the options file, but not its name --
+// you pass this function the filename of the Linux kernel, initial RAM disk, or other
+// file in the target directory, and this function finds the file with the name
+// LINUX_OPTIONS_FILENAME within that directory and loads it.
+// The return value is a pointer to the REFIT_FILE handle for the file, or NULL if
+// it wasn't found.
+REFIT_FILE * ReadLinuxOptionsFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
+ CHAR16 *OptionsFilename = NULL;
+ REFIT_FILE *File = NULL;
+ EFI_STATUS Status;
+
+ OptionsFilename = FindPath(LoaderPath);
+ MergeStrings(&OptionsFilename, LINUX_OPTIONS_FILENAME, L'\\');
+ if (FileExists(Volume->RootDir, OptionsFilename)) {
+ File = AllocateZeroPool(sizeof(REFIT_FILE));
+ Status = ReadFile(Volume->RootDir, OptionsFilename, File);
+ if (CheckError(Status, L"while loading the Linux options file"))
+ File = NULL;
+ }
+ if (OptionsFilename != NULL)
+ FreePool(OptionsFilename);
+ return (File);
+} // static REFIT_FILE * FindLinuxOptionsFile()
+
+// Retrieve a single line of options from a Linux kernel options file
+CHAR16 * GetFirstOptionsFromFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
+ UINTN TokenCount;
+ CHAR16 *Options = NULL;
+ CHAR16 **TokenList;
+ REFIT_FILE *File;
+
+ File = ReadLinuxOptionsFile(LoaderPath, Volume);
+ if (File != NULL) {
+ TokenCount = ReadTokenLine(File, &TokenList);
+ if (TokenCount > 1)
+ Options = StrDuplicate(TokenList[1]);
+ FreeTokenLine(&TokenList, &TokenCount);
+ FreePool(File);
+ }
+ return Options;
+} // static CHAR16 * GetOptionsFile()
+
--- /dev/null
+/*
+ * refit/config.h
+ * General header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#ifndef __CONFIG_H_
+#define __CONFIG_H_
+
+#include "efi.h"
+#include "global.h"
+
+//
+// config module
+//
+
+typedef struct {
+ UINT8 *Buffer;
+ UINTN BufferSize;
+ UINTN Encoding;
+ CHAR8 *Current8Ptr;
+ CHAR8 *End8Ptr;
+ CHAR16 *Current16Ptr;
+ CHAR16 *End16Ptr;
+} REFIT_FILE;
+
+#define DISABLE_FLAG_SHELL (0x0001)
+#define DISABLE_FLAG_TOOLS (0x0002)
+#define DISABLE_FLAG_SINGLEUSER (0x0004)
+#define DISABLE_FLAG_HWTEST (0x0008)
+#define DISABLE_ALL ((0xffff))
+
+#define HIDEUI_FLAG_BANNER (0x0001)
+#define HIDEUI_FLAG_FUNCS (0x0002)
+#define HIDEUI_FLAG_LABEL (0x0004)
+#define HIDEUI_ALL (0xffff)
+
+VOID ReadConfig(VOID);
+VOID ScanUserConfigured(VOID);
+UINTN ReadTokenLine(IN REFIT_FILE *File, OUT CHAR16 ***TokenList);
+VOID FreeTokenLine(IN OUT CHAR16 ***TokenList, IN OUT UINTN *TokenCount);
+REFIT_FILE * ReadLinuxOptionsFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume);
+CHAR16 * GetFirstOptionsFromFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume);
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * refit/global.h
+ * Global header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#ifndef __GLOBAL_H_
+#define __GLOBAL_H_
+
+#include "efi.h"
+#include "efilib.h"
+
+#include "libeg.h"
+
+#define REFIT_DEBUG (0)
+
+#define TAG_ABOUT (1)
+#define TAG_RESET (2)
+#define TAG_SHUTDOWN (3)
+#define TAG_TOOL (4)
+#define TAG_LOADER (5)
+#define TAG_LEGACY (6)
+
+#define NUM_SCAN_OPTIONS 10
+
+//
+// global definitions
+//
+
+// global types
+
+typedef struct {
+ UINT8 Flags;
+ UINT8 StartCHS1;
+ UINT8 StartCHS2;
+ UINT8 StartCHS3;
+ UINT8 Type;
+ UINT8 EndCHS1;
+ UINT8 EndCHS2;
+ UINT8 EndCHS3;
+ UINT32 StartLBA;
+ UINT32 Size;
+} MBR_PARTITION_INFO;
+
+typedef struct {
+ EFI_DEVICE_PATH *DevicePath;
+ EFI_HANDLE DeviceHandle;
+ EFI_FILE *RootDir;
+ CHAR16 *VolName;
+ EG_IMAGE *VolBadgeImage;
+ UINTN DiskKind;
+ BOOLEAN IsAppleLegacy;
+ BOOLEAN HasBootCode;
+ CHAR16 *OSIconName;
+ CHAR16 *OSName;
+ BOOLEAN IsMbrPartition;
+ UINTN MbrPartitionIndex;
+ EFI_BLOCK_IO *BlockIO;
+ UINT64 BlockIOOffset;
+ EFI_BLOCK_IO *WholeDiskBlockIO;
+ EFI_DEVICE_PATH *WholeDiskDevicePath;
+ MBR_PARTITION_INFO *MbrPartitionTable;
+} REFIT_VOLUME;
+
+typedef struct _refit_menu_entry {
+ CHAR16 *Title;
+ UINTN Tag;
+ UINTN Row;
+ CHAR16 ShortcutDigit;
+ CHAR16 ShortcutLetter;
+ EG_IMAGE *Image;
+ EG_IMAGE *BadgeImage;
+ struct _refit_menu_screen *SubScreen;
+} REFIT_MENU_ENTRY;
+
+typedef struct _refit_menu_screen {
+ CHAR16 *Title;
+ EG_IMAGE *TitleImage;
+ UINTN InfoLineCount;
+ CHAR16 **InfoLines;
+ UINTN EntryCount; // total number of entries registered
+ REFIT_MENU_ENTRY **Entries;
+ UINTN TimeoutSeconds;
+ CHAR16 *TimeoutText;
+} REFIT_MENU_SCREEN;
+
+typedef struct {
+ REFIT_MENU_ENTRY me;
+ CHAR16 *Title;
+ CHAR16 *LoaderPath;
+ CHAR16 *VolName;
+ EFI_DEVICE_PATH *DevicePath;
+ BOOLEAN UseGraphicsMode;
+ BOOLEAN Enabled;
+ CHAR16 *LoadOptions;
+ CHAR16 *InitrdPath; // Linux stub loader only
+ CHAR8 OSType;
+} LOADER_ENTRY;
+
+typedef struct {
+ REFIT_MENU_ENTRY me;
+ REFIT_VOLUME *Volume;
+ CHAR16 *LoadOptions;
+ BOOLEAN Enabled;
+} LEGACY_ENTRY;
+
+typedef struct {
+ BOOLEAN TextOnly;
+ UINTN Timeout;
+ UINTN DisableFlags;
+ UINTN HideUIFlags;
+ BOOLEAN Quiet;
+ CHAR16 *BannerFileName;
+ CHAR16 *SelectionSmallFileName;
+ CHAR16 *SelectionBigFileName;
+ CHAR16 *DefaultSelection;
+ CHAR8 ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan
+} REFIT_CONFIG;
+
+// Global variables
+
+extern EFI_HANDLE SelfImageHandle;
+extern EFI_LOADED_IMAGE *SelfLoadedImage;
+extern EFI_FILE *SelfRootDir;
+extern EFI_FILE *SelfDir;
+extern CHAR16 *SelfDirPath;
+
+extern REFIT_VOLUME *SelfVolume;
+extern REFIT_VOLUME **Volumes;
+extern UINTN VolumesCount;
+
+extern REFIT_CONFIG GlobalConfig;
+
+LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry);
+REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry);
+VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume);
+LOADER_ENTRY * MakeGenericLoaderEntry(VOID);
+LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume);
+VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume);
+LOADER_ENTRY * AddPreparedLoaderEntry(LOADER_ENTRY *Entry);
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * refit/icns.c
+ * Loader for .icns icon files
+ *
+ * Copyright (c) 2006-2007 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "global.h"
+#include "lib.h"
+#include "icns.h"
+#include "config.h"
+
+//
+// well-known icons
+//
+
+typedef struct {
+ EG_IMAGE *Image;
+ CHAR16 *Path;
+ UINTN PixelSize;
+} BUILTIN_ICON;
+
+BUILTIN_ICON BuiltinIconTable[BUILTIN_ICON_COUNT] = {
+ { NULL, L"icons\\func_about.icns", 48 },
+ { NULL, L"icons\\func_reset.icns", 48 },
+ { NULL, L"icons\\func_shutdown.icns", 48 },
+ { NULL, L"icons\\tool_shell.icns", 48 },
+ { NULL, L"icons\\tool_part.icns", 48 },
+ { NULL, L"icons\\tool_rescue.icns", 48 },
+ { NULL, L"icons\\vol_internal.icns", 32 },
+ { NULL, L"icons\\vol_external.icns", 32 },
+ { NULL, L"icons\\vol_optical.icns", 32 },
+};
+
+EG_IMAGE * BuiltinIcon(IN UINTN Id)
+{
+ if (Id >= BUILTIN_ICON_COUNT)
+ return NULL;
+
+ if (BuiltinIconTable[Id].Image == NULL)
+ BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, BuiltinIconTable[Id].Path, BuiltinIconTable[Id].PixelSize);
+
+ return BuiltinIconTable[Id].Image;
+}
+
+//
+// Load an icon for an operating system
+//
+
+EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo)
+{
+ EG_IMAGE *Image;
+ CHAR16 CutoutName[16];
+ CHAR16 FileName[256];
+ UINTN StartIndex, Index, NextIndex;
+
+ if (GlobalConfig.TextOnly) // skip loading if it's not used anyway
+ return NULL;
+ Image = NULL;
+
+ // try the names from OSIconName
+ for (StartIndex = 0; OSIconName != NULL && OSIconName[StartIndex]; StartIndex = NextIndex) {
+ // find the next name in the list
+ NextIndex = 0;
+ for (Index = StartIndex; OSIconName[Index]; Index++) {
+ if (OSIconName[Index] == ',') {
+ NextIndex = Index + 1;
+ break;
+ }
+ }
+ if (OSIconName[Index] == 0)
+ NextIndex = Index;
+
+ // construct full path
+ if (Index > StartIndex + 15) // prevent buffer overflow
+ continue;
+ CopyMem(CutoutName, OSIconName + StartIndex, (Index - StartIndex) * sizeof(CHAR16));
+ CutoutName[Index - StartIndex] = 0;
+ SPrint(FileName, 255, L"icons\\%s_%s.icns",
+ BootLogo ? L"boot" : L"os", CutoutName);
+
+ // try to load it
+ Image = egLoadIcon(SelfDir, FileName, 128);
+ if (Image != NULL)
+ return Image;
+ }
+
+ // try the fallback name
+ SPrint(FileName, 255, L"icons\\%s_%s.icns",
+ BootLogo ? L"boot" : L"os", FallbackIconName);
+ Image = egLoadIcon(SelfDir, FileName, 128);
+ if (Image != NULL)
+ return Image;
+
+ // try the fallback name with os_ instead of boot_
+ if (BootLogo)
+ return LoadOSIcon(NULL, FallbackIconName, FALSE);
+
+ return DummyImage(128);
+}
+
+//
+// Load an image from a .icns file
+//
+
+EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize)
+{
+ if (GlobalConfig.TextOnly) // skip loading if it's not used anyway
+ return NULL;
+ return egLoadIcon(BaseDir, FileName, PixelSize);
+}
+
+static EG_PIXEL BlackPixel = { 0x00, 0x00, 0x00, 0 };
+//static EG_PIXEL YellowPixel = { 0x00, 0xff, 0xff, 0 };
+
+EG_IMAGE * DummyImage(IN UINTN PixelSize)
+{
+ EG_IMAGE *Image;
+ UINTN x, y, LineOffset;
+ CHAR8 *Ptr, *YPtr;
+
+ Image = egCreateFilledImage(PixelSize, PixelSize, TRUE, &BlackPixel);
+
+ LineOffset = PixelSize * 4;
+
+ YPtr = (CHAR8 *)Image->PixelData + ((PixelSize - 32) >> 1) * (LineOffset + 4);
+ for (y = 0; y < 32; y++) {
+ Ptr = YPtr;
+ for (x = 0; x < 32; x++) {
+ if (((x + y) % 12) < 6) {
+ *Ptr++ = 0;
+ *Ptr++ = 0;
+ *Ptr++ = 0;
+ } else {
+ *Ptr++ = 0;
+ *Ptr++ = 255;
+ *Ptr++ = 255;
+ }
+ *Ptr++ = 144;
+ }
+ YPtr += LineOffset;
+ }
+
+ return Image;
+}
+
+EG_IMAGE * LoadIcnsFallback(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize)
+{
+ EG_IMAGE *Image;
+ if (GlobalConfig.TextOnly) // skip loading if it's not used anyway
+ return NULL;
+
+ Image = LoadIcns(BaseDir, FileName, PixelSize);
+ if (Image == NULL) {
+ Image = DummyImage(PixelSize);
+ }
+ return Image;
+}
--- /dev/null
+/*
+ * refit/icns.h
+ * Icon management header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#ifndef __ICNS_H_
+#define __ICNS_H_
+
+//
+// icns loader module
+//
+
+EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo);
+
+EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize);
+EG_IMAGE * LoadIcnsFallback(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize);
+EG_IMAGE * DummyImage(IN UINTN PixelSize);
+
+EG_IMAGE * BuiltinIcon(IN UINTN Id);
+
+#define BUILTIN_ICON_FUNC_ABOUT (0)
+#define BUILTIN_ICON_FUNC_RESET (1)
+#define BUILTIN_ICON_FUNC_SHUTDOWN (2)
+#define BUILTIN_ICON_TOOL_SHELL (3)
+#define BUILTIN_ICON_TOOL_PART (4)
+#define BUILTIN_ICON_TOOL_RESCUE (5)
+#define BUILTIN_ICON_VOL_INTERNAL (6)
+#define BUILTIN_ICON_VOL_EXTERNAL (7)
+#define BUILTIN_ICON_VOL_OPTICAL (8)
+#define BUILTIN_ICON_COUNT (9)
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * refit/lib.c
+ * General library functions
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#include "global.h"
+#include "lib.h"
+#include "icns.h"
+#include "screen.h"
+#include "refit_call_wrapper.h"
+
+// variables
+
+EFI_HANDLE SelfImageHandle;
+EFI_LOADED_IMAGE *SelfLoadedImage;
+EFI_FILE *SelfRootDir;
+EFI_FILE *SelfDir;
+CHAR16 *SelfDirPath;
+
+REFIT_VOLUME *SelfVolume = NULL;
+REFIT_VOLUME **Volumes = NULL;
+UINTN VolumesCount = 0;
+
+// Maximum size for disk sectors
+#define SECTOR_SIZE 4096
+
+// functions
+
+static EFI_STATUS FinishInitRefitLib(VOID);
+
+static VOID UninitVolumes(VOID);
+
+//
+// self recognition stuff
+//
+
+EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle)
+{
+ EFI_STATUS Status;
+ CHAR16 *DevicePathAsString;
+ CHAR16 BaseDirectory[256];
+ UINTN i;
+
+ SelfImageHandle = ImageHandle;
+ Status = refit_call3_wrapper(BS->HandleProtocol, SelfImageHandle, &LoadedImageProtocol, (VOID **) &SelfLoadedImage);
+ if (CheckFatalError(Status, L"while getting a LoadedImageProtocol handle"))
+ return EFI_LOAD_ERROR;
+
+ // find the current directory
+ DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath);
+ if (DevicePathAsString != NULL) {
+ StrCpy(BaseDirectory, DevicePathAsString);
+ FreePool(DevicePathAsString);
+ for (i = StrLen(BaseDirectory); i > 0 && BaseDirectory[i] != '\\'; i--) ;
+ BaseDirectory[i] = 0;
+ } else
+ BaseDirectory[0] = 0;
+ SelfDirPath = StrDuplicate(BaseDirectory);
+
+ return FinishInitRefitLib();
+}
+
+// called before running external programs to close open file handles
+VOID UninitRefitLib(VOID)
+{
+ UninitVolumes();
+
+ if (SelfDir != NULL) {
+ refit_call1_wrapper(SelfDir->Close, SelfDir);
+ SelfDir = NULL;
+ }
+
+ if (SelfRootDir != NULL) {
+ refit_call1_wrapper(SelfRootDir->Close, SelfRootDir);
+ SelfRootDir = NULL;
+ }
+}
+
+// called after running external programs to re-open file handles
+EFI_STATUS ReinitRefitLib(VOID)
+{
+ ReinitVolumes();
+
+ if (SelfVolume != NULL && SelfVolume->RootDir != NULL)
+ SelfRootDir = SelfVolume->RootDir;
+
+ return FinishInitRefitLib();
+}
+
+static EFI_STATUS FinishInitRefitLib(VOID)
+{
+ EFI_STATUS Status;
+
+ if (SelfRootDir == NULL) {
+ SelfRootDir = LibOpenRoot(SelfLoadedImage->DeviceHandle);
+ if (SelfRootDir == NULL) {
+ CheckError(EFI_LOAD_ERROR, L"while (re)opening our installation volume");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Status = refit_call5_wrapper(SelfRootDir->Open, SelfRootDir, &SelfDir, SelfDirPath, EFI_FILE_MODE_READ, 0);
+ if (CheckFatalError(Status, L"while opening our installation directory"))
+ return EFI_LOAD_ERROR;
+
+ return EFI_SUCCESS;
+}
+
+//
+// list functions
+//
+
+VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount)
+{
+ UINTN AllocateCount;
+
+ *ElementCount = InitialElementCount;
+ if (*ElementCount > 0) {
+ AllocateCount = (*ElementCount + 7) & ~7; // next multiple of 8
+ *ListPtr = AllocatePool(sizeof(VOID *) * AllocateCount);
+ } else {
+ *ListPtr = NULL;
+ }
+}
+
+VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement)
+{
+ UINTN AllocateCount;
+
+ if ((*ElementCount & 7) == 0) {
+ AllocateCount = *ElementCount + 8;
+ if (*ElementCount == 0)
+ *ListPtr = AllocatePool(sizeof(VOID *) * AllocateCount);
+ else
+ *ListPtr = ReallocatePool(*ListPtr, sizeof(VOID *) * (*ElementCount), sizeof(VOID *) * AllocateCount);
+ }
+ (*ListPtr)[*ElementCount] = NewElement;
+ (*ElementCount)++;
+} /* VOID AddListElement() */
+
+VOID FreeList(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount)
+{
+ UINTN i;
+
+ if (*ElementCount > 0) {
+ for (i = 0; i < *ElementCount; i++) {
+ // TODO: call a user-provided routine for each element here
+ FreePool((*ListPtr)[i]);
+ }
+ FreePool(*ListPtr);
+ }
+}
+
+//
+// firmware device path discovery
+//
+
+static UINT8 LegacyLoaderMediaPathData[] = {
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+static EFI_DEVICE_PATH *LegacyLoaderMediaPath = (EFI_DEVICE_PATH *)LegacyLoaderMediaPathData;
+
+VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DEVICE_PATH **HardcodedPathList)
+{
+ EFI_STATUS Status;
+ UINTN HandleCount = 0;
+ UINTN HandleIndex, HardcodedIndex;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE Handle;
+ UINTN PathCount = 0;
+ UINTN PathIndex;
+ EFI_LOADED_IMAGE *LoadedImage;
+ EFI_DEVICE_PATH *DevicePath;
+ BOOLEAN Seen;
+
+ MaxPaths--; // leave space for the terminating NULL pointer
+
+ // get all LoadedImage handles
+ Status = LibLocateHandle(ByProtocol, &LoadedImageProtocol, NULL,
+ &HandleCount, &Handles);
+ if (CheckError(Status, L"while listing LoadedImage handles")) {
+ if (HardcodedPathList) {
+ for (HardcodedIndex = 0; HardcodedPathList[HardcodedIndex] && PathCount < MaxPaths; HardcodedIndex++)
+ PathList[PathCount++] = HardcodedPathList[HardcodedIndex];
+ }
+ PathList[PathCount] = NULL;
+ return;
+ }
+ for (HandleIndex = 0; HandleIndex < HandleCount && PathCount < MaxPaths; HandleIndex++) {
+ Handle = Handles[HandleIndex];
+
+ Status = refit_call3_wrapper(BS->HandleProtocol, Handle, &LoadedImageProtocol, (VOID **) &LoadedImage);
+ if (EFI_ERROR(Status))
+ continue; // This can only happen if the firmware scewed up, ignore it.
+
+ Status = refit_call3_wrapper(BS->HandleProtocol, LoadedImage->DeviceHandle, &DevicePathProtocol, (VOID **) &DevicePath);
+ if (EFI_ERROR(Status))
+ continue; // This happens, ignore it.
+
+ // Only grab memory range nodes
+ if (DevicePathType(DevicePath) != HARDWARE_DEVICE_PATH || DevicePathSubType(DevicePath) != HW_MEMMAP_DP)
+ continue;
+
+ // Check if we have this device path in the list already
+ // WARNING: This assumes the first node in the device path is unique!
+ Seen = FALSE;
+ for (PathIndex = 0; PathIndex < PathCount; PathIndex++) {
+ if (DevicePathNodeLength(DevicePath) != DevicePathNodeLength(PathList[PathIndex]))
+ continue;
+ if (CompareMem(DevicePath, PathList[PathIndex], DevicePathNodeLength(DevicePath)) == 0) {
+ Seen = TRUE;
+ break;
+ }
+ }
+ if (Seen)
+ continue;
+
+ PathList[PathCount++] = AppendDevicePath(DevicePath, LegacyLoaderMediaPath);
+ }
+ FreePool(Handles);
+
+ if (HardcodedPathList) {
+ for (HardcodedIndex = 0; HardcodedPathList[HardcodedIndex] && PathCount < MaxPaths; HardcodedIndex++)
+ PathList[PathCount++] = HardcodedPathList[HardcodedIndex];
+ }
+ PathList[PathCount] = NULL;
+}
+
+//
+// volume functions
+//
+
+static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootable)
+{
+ EFI_STATUS Status;
+ UINT8 SectorBuffer[SECTOR_SIZE];
+ UINTN i;
+ MBR_PARTITION_INFO *MbrTable;
+ BOOLEAN MbrTableFound;
+
+ Volume->HasBootCode = FALSE;
+ Volume->OSIconName = NULL;
+ Volume->OSName = NULL;
+ *Bootable = FALSE;
+
+ if (Volume->BlockIO == NULL)
+ return;
+ if (Volume->BlockIO->Media->BlockSize > SECTOR_SIZE)
+ return; // our buffer is too small...
+
+ // look at the boot sector (this is used for both hard disks and El Torito images!)
+ Status = refit_call5_wrapper(Volume->BlockIO->ReadBlocks,
+ Volume->BlockIO, Volume->BlockIO->Media->MediaId,
+ Volume->BlockIOOffset, SECTOR_SIZE, SectorBuffer);
+ if (!EFI_ERROR(Status)) {
+
+ if (*((UINT16 *)(SectorBuffer + 510)) == 0xaa55 && SectorBuffer[0] != 0) {
+ *Bootable = TRUE;
+ Volume->HasBootCode = TRUE;
+ }
+
+ // detect specific boot codes
+ if (CompareMem(SectorBuffer + 2, "LILO", 4) == 0 ||
+ CompareMem(SectorBuffer + 6, "LILO", 4) == 0 ||
+ CompareMem(SectorBuffer + 3, "SYSLINUX", 8) == 0 ||
+ FindMem(SectorBuffer, SECTOR_SIZE, "ISOLINUX", 8) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"linux";
+ Volume->OSName = L"Linux";
+
+ } else if (FindMem(SectorBuffer, 512, "Geom\0Hard Disk\0Read\0 Error", 26) >= 0) { // GRUB
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"grub,linux";
+ Volume->OSName = L"Linux";
+
+ } else if ((*((UINT32 *)(SectorBuffer + 502)) == 0 &&
+ *((UINT32 *)(SectorBuffer + 506)) == 50000 &&
+ *((UINT16 *)(SectorBuffer + 510)) == 0xaa55) ||
+ FindMem(SectorBuffer, SECTOR_SIZE, "Starting the BTX loader", 23) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"freebsd";
+ Volume->OSName = L"FreeBSD";
+
+ } else if (FindMem(SectorBuffer, 512, "!Loading", 8) >= 0 ||
+ FindMem(SectorBuffer, SECTOR_SIZE, "/cdboot\0/CDBOOT\0", 16) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"openbsd";
+ Volume->OSName = L"OpenBSD";
+
+ } else if (FindMem(SectorBuffer, 512, "Not a bootxx image", 18) >= 0 ||
+ *((UINT32 *)(SectorBuffer + 1028)) == 0x7886b6d1) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"netbsd";
+ Volume->OSName = L"NetBSD";
+
+ } else if (FindMem(SectorBuffer, SECTOR_SIZE, "NTLDR", 5) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"win";
+ Volume->OSName = L"Windows";
+
+ } else if (FindMem(SectorBuffer, SECTOR_SIZE, "BOOTMGR", 7) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"winvista,win";
+ Volume->OSName = L"Windows";
+
+ } else if (FindMem(SectorBuffer, 512, "CPUBOOT SYS", 11) >= 0 ||
+ FindMem(SectorBuffer, 512, "KERNEL SYS", 11) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"freedos";
+ Volume->OSName = L"FreeDOS";
+
+ } else if (FindMem(SectorBuffer, 512, "OS2LDR", 6) >= 0 ||
+ FindMem(SectorBuffer, 512, "OS2BOOT", 7) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"ecomstation";
+ Volume->OSName = L"eComStation";
+
+ } else if (FindMem(SectorBuffer, 512, "Be Boot Loader", 14) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"beos";
+ Volume->OSName = L"BeOS";
+
+ } else if (FindMem(SectorBuffer, 512, "yT Boot Loader", 14) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"zeta,beos";
+ Volume->OSName = L"ZETA";
+
+ } else if (FindMem(SectorBuffer, 512, "\x04" "beos\x06" "system\x05" "zbeos", 18) >= 0 ||
+ FindMem(SectorBuffer, 512, "\x06" "system\x0c" "haiku_loader", 20) >= 0) {
+ Volume->HasBootCode = TRUE;
+ Volume->OSIconName = L"haiku,beos";
+ Volume->OSName = L"Haiku";
+
+ }
+
+ // NOTE: If you add an operating system with a name that starts with 'W' or 'L', you
+ // need to fix AddLegacyEntry in main.c.
+
+#if REFIT_DEBUG > 0
+ Print(L" Result of bootcode detection: %s %s (%s)\n",
+ Volume->HasBootCode ? L"bootable" : L"non-bootable",
+ Volume->OSName, Volume->OSIconName);
+#endif
+
+ if (FindMem(SectorBuffer, 512, "Non-system disk", 15) >= 0) // dummy FAT boot sector
+ Volume->HasBootCode = FALSE;
+
+ // check for MBR partition table
+ if (*((UINT16 *)(SectorBuffer + 510)) == 0xaa55) {
+ MbrTableFound = FALSE;
+ MbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446);
+ for (i = 0; i < 4; i++)
+ if (MbrTable[i].StartLBA && MbrTable[i].Size)
+ MbrTableFound = TRUE;
+ for (i = 0; i < 4; i++)
+ if (MbrTable[i].Flags != 0x00 && MbrTable[i].Flags != 0x80)
+ MbrTableFound = FALSE;
+ if (MbrTableFound) {
+ Volume->MbrPartitionTable = AllocatePool(4 * 16);
+ CopyMem(Volume->MbrPartitionTable, MbrTable, 4 * 16);
+ }
+ }
+
+ } else {
+#if REFIT_DEBUG > 0
+ CheckError(Status, L"while reading boot sector");
+#endif
+ }
+}
+
+// default volume icon based on disk kind
+static VOID ScanVolumeDefaultIcon(IN OUT REFIT_VOLUME *Volume)
+{
+ switch (Volume->DiskKind) {
+ case DISK_KIND_INTERNAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_INTERNAL);
+ break;
+ case DISK_KIND_EXTERNAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_EXTERNAL);
+ break;
+ case DISK_KIND_OPTICAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_OPTICAL);
+ break;
+ } // switch()
+}
+
+static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH *DevicePath, *NextDevicePath;
+ EFI_DEVICE_PATH *DiskDevicePath, *RemainingDevicePath;
+ EFI_HANDLE WholeDiskHandle;
+ UINTN PartialLength;
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr;
+ BOOLEAN Bootable;
+
+ // get device path
+ Volume->DevicePath = DuplicateDevicePath(DevicePathFromHandle(Volume->DeviceHandle));
+#if REFIT_DEBUG > 0
+ if (Volume->DevicePath != NULL) {
+ Print(L"* %s\n", DevicePathToStr(Volume->DevicePath));
+#if REFIT_DEBUG >= 2
+ DumpHex(1, 0, DevicePathSize(Volume->DevicePath), Volume->DevicePath);
+#endif
+ }
+#endif
+
+ Volume->DiskKind = DISK_KIND_INTERNAL; // default
+
+ // get block i/o
+ Status = refit_call3_wrapper(BS->HandleProtocol, Volume->DeviceHandle, &BlockIoProtocol, (VOID **) &(Volume->BlockIO));
+ if (EFI_ERROR(Status)) {
+ Volume->BlockIO = NULL;
+ Print(L"Warning: Can't get BlockIO protocol.\n");
+ } else {
+ if (Volume->BlockIO->Media->BlockSize == 2048)
+ Volume->DiskKind = DISK_KIND_OPTICAL;
+ }
+
+ // scan for bootcode and MBR table
+ Bootable = FALSE;
+ ScanVolumeBootcode(Volume, &Bootable);
+
+ // detect device type
+ DevicePath = Volume->DevicePath;
+ while (DevicePath != NULL && !IsDevicePathEndType(DevicePath)) {
+ NextDevicePath = NextDevicePathNode(DevicePath);
+
+ if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH &&
+ (DevicePathSubType(DevicePath) == MSG_USB_DP ||
+ DevicePathSubType(DevicePath) == MSG_USB_CLASS_DP ||
+ DevicePathSubType(DevicePath) == MSG_1394_DP ||
+ DevicePathSubType(DevicePath) == MSG_FIBRECHANNEL_DP))
+ Volume->DiskKind = DISK_KIND_EXTERNAL; // USB/FireWire/FC device -> external
+ if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(DevicePath) == MEDIA_CDROM_DP) {
+ Volume->DiskKind = DISK_KIND_OPTICAL; // El Torito entry -> optical disk
+ Bootable = TRUE;
+ }
+
+ if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType(DevicePath) == MEDIA_VENDOR_DP) {
+ Volume->IsAppleLegacy = TRUE; // legacy BIOS device entry
+ // TODO: also check for Boot Camp GUID
+ Bootable = FALSE; // this handle's BlockIO is just an alias for the whole device
+ }
+
+ if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH) {
+ // make a device path for the whole device
+ PartialLength = (UINT8 *)NextDevicePath - (UINT8 *)(Volume->DevicePath);
+ DiskDevicePath = (EFI_DEVICE_PATH *)AllocatePool(PartialLength + sizeof(EFI_DEVICE_PATH));
+ CopyMem(DiskDevicePath, Volume->DevicePath, PartialLength);
+ CopyMem((UINT8 *)DiskDevicePath + PartialLength, EndDevicePath, sizeof(EFI_DEVICE_PATH));
+
+ // get the handle for that path
+ RemainingDevicePath = DiskDevicePath;
+ //Print(L" * looking at %s\n", DevicePathToStr(RemainingDevicePath));
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &WholeDiskHandle);
+ //Print(L" * remaining: %s\n", DevicePathToStr(RemainingDevicePath));
+ FreePool(DiskDevicePath);
+
+ if (!EFI_ERROR(Status)) {
+ //Print(L" - original handle: %08x - disk handle: %08x\n", (UINT32)DeviceHandle, (UINT32)WholeDiskHandle);
+
+ // get the device path for later
+ Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &DevicePathProtocol, (VOID **) &DiskDevicePath);
+ if (!EFI_ERROR(Status)) {
+ Volume->WholeDiskDevicePath = DuplicateDevicePath(DiskDevicePath);
+ }
+
+ // look at the BlockIO protocol
+ Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol, (VOID **) &Volume->WholeDiskBlockIO);
+ if (!EFI_ERROR(Status)) {
+
+ // check the media block size
+ if (Volume->WholeDiskBlockIO->Media->BlockSize == 2048)
+ Volume->DiskKind = DISK_KIND_OPTICAL;
+
+ } else {
+ Volume->WholeDiskBlockIO = NULL;
+ //CheckError(Status, L"from HandleProtocol");
+ }
+ } //else
+ // CheckError(Status, L"from LocateDevicePath");
+ }
+
+ DevicePath = NextDevicePath;
+ } // while
+
+ if (!Bootable) {
+#if REFIT_DEBUG > 0
+ if (Volume->HasBootCode)
+ Print(L" Volume considered non-bootable, but boot code is present\n");
+#endif
+ Volume->HasBootCode = FALSE;
+ }
+
+ // default volume icon based on disk kind
+ ScanVolumeDefaultIcon(Volume);
+
+ // open the root directory of the volume
+ Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
+ if (Volume->RootDir == NULL) {
+ return;
+ }
+
+ // get volume name
+ FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
+ if (FileSystemInfoPtr != NULL) {
+ Volume->VolName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
+ FreePool(FileSystemInfoPtr);
+ }
+
+ // TODO: if no official volume name is found or it is empty, use something else, e.g.:
+ // - name from bytes 3 to 10 of the boot sector
+ // - partition number
+ // - name derived from file system type or partition type
+
+ // get custom volume icon if present
+ if (FileExists(Volume->RootDir, L".VolumeIcon.icns"))
+ Volume->VolBadgeImage = LoadIcns(Volume->RootDir, L".VolumeIcon.icns", 32);
+}
+
+static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_INFO *MbrEntry)
+{
+ EFI_STATUS Status;
+ REFIT_VOLUME *Volume;
+ UINT32 ExtBase, ExtCurrent, NextExtCurrent;
+ UINTN i;
+ UINTN LogicalPartitionIndex = 4;
+ UINT8 SectorBuffer[512];
+ BOOLEAN Bootable;
+ MBR_PARTITION_INFO *EMbrTable;
+
+ ExtBase = MbrEntry->StartLBA;
+
+ for (ExtCurrent = ExtBase; ExtCurrent; ExtCurrent = NextExtCurrent) {
+ // read current EMBR
+ Status = refit_call5_wrapper(WholeDiskVolume->BlockIO->ReadBlocks,
+ WholeDiskVolume->BlockIO,
+ WholeDiskVolume->BlockIO->Media->MediaId,
+ ExtCurrent, 512, SectorBuffer);
+ if (EFI_ERROR(Status))
+ break;
+ if (*((UINT16 *)(SectorBuffer + 510)) != 0xaa55)
+ break;
+ EMbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446);
+
+ // scan logical partitions in this EMBR
+ NextExtCurrent = 0;
+ for (i = 0; i < 4; i++) {
+ if ((EMbrTable[i].Flags != 0x00 && EMbrTable[i].Flags != 0x80) ||
+ EMbrTable[i].StartLBA == 0 || EMbrTable[i].Size == 0)
+ break;
+ if (IS_EXTENDED_PART_TYPE(EMbrTable[i].Type)) {
+ // set next ExtCurrent
+ NextExtCurrent = ExtBase + EMbrTable[i].StartLBA;
+ break;
+ } else {
+
+ // found a logical partition
+ Volume = AllocateZeroPool(sizeof(REFIT_VOLUME));
+ Volume->DiskKind = WholeDiskVolume->DiskKind;
+ Volume->IsMbrPartition = TRUE;
+ Volume->MbrPartitionIndex = LogicalPartitionIndex++;
+ Volume->VolName = PoolPrint(L"Partition %d", Volume->MbrPartitionIndex + 1);
+ Volume->BlockIO = WholeDiskVolume->BlockIO;
+ Volume->BlockIOOffset = ExtCurrent + EMbrTable[i].StartLBA;
+ Volume->WholeDiskBlockIO = WholeDiskVolume->BlockIO;
+
+ Bootable = FALSE;
+ ScanVolumeBootcode(Volume, &Bootable);
+ if (!Bootable)
+ Volume->HasBootCode = FALSE;
+
+ ScanVolumeDefaultIcon(Volume);
+
+ AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
+
+ }
+ }
+ }
+}
+
+VOID ScanVolumes(VOID)
+{
+ EFI_STATUS Status;
+ UINTN HandleCount = 0;
+ UINTN HandleIndex;
+ EFI_HANDLE *Handles;
+ REFIT_VOLUME *Volume, *WholeDiskVolume;
+ UINTN VolumeIndex, VolumeIndex2;
+ MBR_PARTITION_INFO *MbrTable;
+ UINTN PartitionIndex;
+ UINT8 *SectorBuffer1, *SectorBuffer2;
+ UINTN SectorSum, i;
+
+ FreePool(Volumes);
+ Volumes = NULL;
+ VolumesCount = 0;
+
+ // get all filesystem handles
+ Status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL, &HandleCount, &Handles);
+ // was: &FileSystemProtocol
+ if (Status == EFI_NOT_FOUND)
+ return; // no filesystems. strange, but true...
+ if (CheckError(Status, L"while listing all file systems"))
+ return;
+
+ // first pass: collect information about all handles
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Volume = AllocateZeroPool(sizeof(REFIT_VOLUME));
+ Volume->DeviceHandle = Handles[HandleIndex];
+ ScanVolume(Volume);
+
+ AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
+
+ if (Volume->DeviceHandle == SelfLoadedImage->DeviceHandle)
+ SelfVolume = Volume;
+ }
+ FreePool(Handles);
+
+ if (SelfVolume == NULL)
+ Print(L"WARNING: SelfVolume not found");
+
+ // second pass: relate partitions and whole disk devices
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+ // check MBR partition table for extended partitions
+ if (Volume->BlockIO != NULL && Volume->WholeDiskBlockIO != NULL &&
+ Volume->BlockIO == Volume->WholeDiskBlockIO && Volume->BlockIOOffset == 0 &&
+ Volume->MbrPartitionTable != NULL) {
+ MbrTable = Volume->MbrPartitionTable;
+ for (PartitionIndex = 0; PartitionIndex < 4; PartitionIndex++) {
+ if (IS_EXTENDED_PART_TYPE(MbrTable[PartitionIndex].Type)) {
+ ScanExtendedPartition(Volume, MbrTable + PartitionIndex);
+ }
+ }
+ }
+
+ // search for corresponding whole disk volume entry
+ WholeDiskVolume = NULL;
+ if (Volume->BlockIO != NULL && Volume->WholeDiskBlockIO != NULL &&
+ Volume->BlockIO != Volume->WholeDiskBlockIO) {
+ for (VolumeIndex2 = 0; VolumeIndex2 < VolumesCount; VolumeIndex2++) {
+ if (Volumes[VolumeIndex2]->BlockIO == Volume->WholeDiskBlockIO &&
+ Volumes[VolumeIndex2]->BlockIOOffset == 0)
+ WholeDiskVolume = Volumes[VolumeIndex2];
+ }
+ }
+
+ if (WholeDiskVolume != NULL && WholeDiskVolume->MbrPartitionTable != NULL) {
+ // check if this volume is one of the partitions in the table
+ MbrTable = WholeDiskVolume->MbrPartitionTable;
+ SectorBuffer1 = AllocatePool(512);
+ SectorBuffer2 = AllocatePool(512);
+ for (PartitionIndex = 0; PartitionIndex < 4; PartitionIndex++) {
+ // check size
+ if ((UINT64)(MbrTable[PartitionIndex].Size) != Volume->BlockIO->Media->LastBlock + 1)
+ continue;
+
+ // compare boot sector read through offset vs. directly
+ Status = refit_call5_wrapper(Volume->BlockIO->ReadBlocks,
+ Volume->BlockIO, Volume->BlockIO->Media->MediaId,
+ Volume->BlockIOOffset, 512, SectorBuffer1);
+ if (EFI_ERROR(Status))
+ break;
+ Status = refit_call5_wrapper(Volume->WholeDiskBlockIO->ReadBlocks,
+ Volume->WholeDiskBlockIO, Volume->WholeDiskBlockIO->Media->MediaId,
+ MbrTable[PartitionIndex].StartLBA, 512, SectorBuffer2);
+ if (EFI_ERROR(Status))
+ break;
+ if (CompareMem(SectorBuffer1, SectorBuffer2, 512) != 0)
+ continue;
+ SectorSum = 0;
+ for (i = 0; i < 512; i++)
+ SectorSum += SectorBuffer1[i];
+ if (SectorSum < 1000)
+ continue;
+
+ // TODO: mark entry as non-bootable if it is an extended partition
+
+ // now we're reasonably sure the association is correct...
+ Volume->IsMbrPartition = TRUE;
+ Volume->MbrPartitionIndex = PartitionIndex;
+ if (Volume->VolName == NULL)
+ Volume->VolName = PoolPrint(L"Partition %d", PartitionIndex + 1);
+ break;
+ }
+
+ FreePool(SectorBuffer1);
+ FreePool(SectorBuffer2);
+ }
+
+ }
+} /* VOID ScanVolumes() */
+
+static VOID UninitVolumes(VOID)
+{
+ REFIT_VOLUME *Volume;
+ UINTN VolumeIndex;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+
+ if (Volume->RootDir != NULL) {
+ refit_call1_wrapper(Volume->RootDir->Close, Volume->RootDir);
+ Volume->RootDir = NULL;
+ }
+
+ Volume->DeviceHandle = NULL;
+ Volume->BlockIO = NULL;
+ Volume->WholeDiskBlockIO = NULL;
+ }
+}
+
+VOID ReinitVolumes(VOID)
+{
+ EFI_STATUS Status;
+ REFIT_VOLUME *Volume;
+ UINTN VolumeIndex;
+ EFI_DEVICE_PATH *RemainingDevicePath;
+ EFI_HANDLE DeviceHandle, WholeDiskHandle;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+
+ if (Volume->DevicePath != NULL) {
+ // get the handle for that path
+ RemainingDevicePath = Volume->DevicePath;
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &DeviceHandle);
+
+ if (!EFI_ERROR(Status)) {
+ Volume->DeviceHandle = DeviceHandle;
+
+ // get the root directory
+ Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
+
+ } else
+ CheckError(Status, L"from LocateDevicePath");
+ }
+
+ if (Volume->WholeDiskDevicePath != NULL) {
+ // get the handle for that path
+ RemainingDevicePath = Volume->WholeDiskDevicePath;
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &WholeDiskHandle);
+
+ if (!EFI_ERROR(Status)) {
+ // get the BlockIO protocol
+ Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol, (VOID **) &Volume->WholeDiskBlockIO);
+ if (EFI_ERROR(Status)) {
+ Volume->WholeDiskBlockIO = NULL;
+ CheckError(Status, L"from HandleProtocol");
+ }
+ } else
+ CheckError(Status, L"from LocateDevicePath");
+ }
+ }
+}
+
+//
+// file and dir functions
+//
+
+BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath)
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE TestFile;
+
+ Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &TestFile, RelativePath, EFI_FILE_MODE_READ, 0);
+ if (Status == EFI_SUCCESS) {
+ refit_call1_wrapper(TestFile->Close, TestFile);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, IN UINTN FilterMode)
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+ UINTN LastBufferSize, BufferSize;
+ INTN IterCount;
+
+ for (;;) {
+
+ // free pointer from last call
+ if (*DirEntry != NULL) {
+ FreePool(*DirEntry);
+ *DirEntry = NULL;
+ }
+
+ // read next directory entry
+ LastBufferSize = BufferSize = 256;
+ Buffer = AllocatePool(BufferSize);
+ for (IterCount = 0; ; IterCount++) {
+ Status = refit_call3_wrapper(Directory->Read, Directory, &BufferSize, Buffer);
+ if (Status != EFI_BUFFER_TOO_SMALL || IterCount >= 4)
+ break;
+ if (BufferSize <= LastBufferSize) {
+ Print(L"FS Driver requests bad buffer size %d (was %d), using %d instead\n", BufferSize, LastBufferSize, LastBufferSize * 2);
+ BufferSize = LastBufferSize * 2;
+#if REFIT_DEBUG > 0
+ } else {
+ Print(L"Reallocating buffer from %d to %d\n", LastBufferSize, BufferSize);
+#endif
+ }
+ Buffer = ReallocatePool(Buffer, LastBufferSize, BufferSize);
+ LastBufferSize = BufferSize;
+ }
+ if (EFI_ERROR(Status)) {
+ FreePool(Buffer);
+ break;
+ }
+
+ // check for end of listing
+ if (BufferSize == 0) { // end of directory listing
+ FreePool(Buffer);
+ break;
+ }
+
+ // entry is ready to be returned
+ *DirEntry = (EFI_FILE_INFO *)Buffer;
+
+ // filter results
+ if (FilterMode == 1) { // only return directories
+ if (((*DirEntry)->Attribute & EFI_FILE_DIRECTORY))
+ break;
+ } else if (FilterMode == 2) { // only return files
+ if (((*DirEntry)->Attribute & EFI_FILE_DIRECTORY) == 0)
+ break;
+ } else // no filter or unknown filter -> return everything
+ break;
+
+ }
+ return Status;
+}
+
+VOID DirIterOpen(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath OPTIONAL, OUT REFIT_DIR_ITER *DirIter)
+{
+ if (RelativePath == NULL) {
+ DirIter->LastStatus = EFI_SUCCESS;
+ DirIter->DirHandle = BaseDir;
+ DirIter->CloseDirHandle = FALSE;
+ } else {
+ DirIter->LastStatus = refit_call5_wrapper(BaseDir->Open, BaseDir, &(DirIter->DirHandle), RelativePath, EFI_FILE_MODE_READ, 0);
+ DirIter->CloseDirHandle = EFI_ERROR(DirIter->LastStatus) ? FALSE : TRUE;
+ }
+ DirIter->LastFileInfo = NULL;
+}
+
+BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR16 *FilePattern OPTIONAL,
+ OUT EFI_FILE_INFO **DirEntry)
+{
+ if (DirIter->LastFileInfo != NULL) {
+ FreePool(DirIter->LastFileInfo);
+ DirIter->LastFileInfo = NULL;
+ }
+
+ if (EFI_ERROR(DirIter->LastStatus))
+ return FALSE; // stop iteration
+
+ for (;;) {
+ DirIter->LastStatus = DirNextEntry(DirIter->DirHandle, &(DirIter->LastFileInfo), FilterMode);
+ if (EFI_ERROR(DirIter->LastStatus))
+ return FALSE;
+ if (DirIter->LastFileInfo == NULL) // end of listing
+ return FALSE;
+ if (FilePattern != NULL) {
+ if ((DirIter->LastFileInfo->Attribute & EFI_FILE_DIRECTORY))
+ break;
+ if (MetaiMatch(DirIter->LastFileInfo->FileName, FilePattern))
+ break;
+ // else continue loop
+ } else
+ break;
+ }
+
+ *DirEntry = DirIter->LastFileInfo;
+ return TRUE;
+}
+
+EFI_STATUS DirIterClose(IN OUT REFIT_DIR_ITER *DirIter)
+{
+ if (DirIter->LastFileInfo != NULL) {
+ FreePool(DirIter->LastFileInfo);
+ DirIter->LastFileInfo = NULL;
+ }
+ if (DirIter->CloseDirHandle)
+ refit_call1_wrapper(DirIter->DirHandle->Close, DirIter->DirHandle);
+ return DirIter->LastStatus;
+}
+
+//
+// file name manipulation
+//
+
+// Returns the filename portion (minus path name) of the
+// specified file
+CHAR16 * Basename(IN CHAR16 *Path)
+{
+ CHAR16 *FileName;
+ UINTN i;
+
+ FileName = Path;
+
+ if (Path != NULL) {
+ for (i = StrLen(Path); i > 0; i--) {
+ if (Path[i-1] == '\\' || Path[i-1] == '/') {
+ FileName = Path + i;
+ break;
+ }
+ }
+ }
+
+ return FileName;
+}
+
+VOID ReplaceExtension(IN OUT CHAR16 *Path, IN CHAR16 *Extension)
+{
+ UINTN i;
+
+ for (i = StrLen(Path); i >= 0; i--) {
+ if (Path[i] == '.') {
+ Path[i] = 0;
+ break;
+ }
+ if (Path[i] == '\\' || Path[i] == '/')
+ break;
+ }
+ StrCat(Path, Extension);
+}
+
+//
+// memory string search
+//
+
+INTN FindMem(IN VOID *Buffer, IN UINTN BufferLength, IN VOID *SearchString, IN UINTN SearchStringLength)
+{
+ UINT8 *BufferPtr;
+ UINTN Offset;
+
+ BufferPtr = Buffer;
+ BufferLength -= SearchStringLength;
+ for (Offset = 0; Offset < BufferLength; Offset++, BufferPtr++) {
+ if (CompareMem(BufferPtr, SearchString, SearchStringLength) == 0)
+ return (INTN)Offset;
+ }
+
+ return -1;
+}
+
+// Performs a case-insensitive search of BigStr for SmallStr.
+// Returns TRUE if found, FALSE if not.
+BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) {
+ CHAR16 *SmallCopy, *BigCopy;
+ BOOLEAN Found = FALSE;
+ UINTN StartPoint = 0, NumCompares = 0, SmallLen = 0;
+
+ if ((SmallStr != NULL) && (BigStr != NULL) && (StrLen(BigStr) >= StrLen(SmallStr))) {
+ SmallCopy = StrDuplicate(SmallStr);
+ BigCopy = StrDuplicate(BigStr);
+ StrLwr(SmallCopy);
+ StrLwr(BigCopy);
+ SmallLen = StrLen(SmallCopy);
+ NumCompares = StrLen(BigCopy) - SmallLen + 1;
+ while ((!Found) && (StartPoint < NumCompares)) {
+ Found = (StrnCmp(SmallCopy, &BigCopy[StartPoint++], SmallLen) == 0);
+ } // while
+ FreePool(SmallCopy);
+ FreePool(BigCopy);
+ } // if
+
+ return (Found);
+} // BOOLEAN StriSubCmp()
+
+// Merges two strings, creating a new one and returning a pointer to it.
+// If AddChar != 0, the specified character is placed between the two original
+// strings (unless the first string is NULL). The original input string
+// *First is de-allocated and replaced by the new merged string.
+// This is similar to StrCat, but safer and more flexible because
+// MergeStrings allocates memory that's the correct size for the
+// new merged string, so it can take a NULL *First and it cleans
+// up the old memory. It should *NOT* be used with a constant
+// *First, though....
+VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
+ UINTN Length1 = 0, Length2 = 0;
+ CHAR16* NewString;
+
+ if (*First != NULL)
+ Length1 = StrLen(*First);
+ if (Second != NULL)
+ Length2 = StrLen(Second);
+ NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2));
+ NewString[0] = 0;
+ if (NewString != NULL) {
+ if (*First != NULL) {
+ StrCat(NewString, *First);
+ if (AddChar) {
+ NewString[Length1] = AddChar;
+ NewString[Length1 + 1] = 0;
+ } // if (AddChar)
+ } // if (First != NULL)
+ if (First != NULL)
+ StrCat(NewString, Second);
+ FreePool(*First);
+ *First = NewString;
+ } else {
+ Print(L"Error! Unable to allocate memory in MergeStrings()!\n");
+ } // if/else
+} // static CHAR16* MergeStrings()
+
+// Takes an input pathname (*Path) and locates the final directory component
+// of that name. For instance, if the input path is 'EFI\foo\bar.efi', this
+// function returns the string 'foo'.
+// Assumes the pathname is separated with backslashes.
+CHAR16 *FindLastDirName(IN CHAR16 *Path) {
+ UINTN i, StartOfElement = 0, EndOfElement = 0, PathLength, CopyLength;
+ CHAR16 *Found = NULL;
+
+ PathLength = StrLen(Path);
+ // Find start & end of target element
+ for (i = 0; i < PathLength; i++) {
+ if (Path[i] == '\\') {
+ StartOfElement = EndOfElement;
+ EndOfElement = i;
+ } // if
+ } // for
+ // Extract the target element
+ if (EndOfElement > 0) {
+ while ((StartOfElement < PathLength) && (Path[StartOfElement] == '\\')) {
+ StartOfElement++;
+ } // while
+ EndOfElement--;
+ if (EndOfElement >= StartOfElement) {
+ CopyLength = EndOfElement - StartOfElement + 1;
+ Found = StrDuplicate(&Path[StartOfElement]);
+ if (Found != NULL)
+ Found[CopyLength] = 0;
+ } // if (EndOfElement >= StartOfElement)
+ } // if (EndOfElement > 0)
+ return (Found);
+} // CHAR16 *FindLastDirName
+
+// Returns the directory portion of a pathname. For instance,
+// if FullPath is 'EFI\foo\bar.efi', this function returns the
+// string 'EFI\foo'.
+CHAR16 *FindPath(IN CHAR16* FullPath) {
+ UINTN i, LastBackslash = 0;
+ CHAR16 *PathOnly;
+
+ for (i = 0; i < StrLen(FullPath); i++) {
+ if (FullPath[i] == '\\')
+ LastBackslash = i;
+ } // for
+ PathOnly = StrDuplicate(FullPath);
+ PathOnly[LastBackslash] = 0;
+ return (PathOnly);
+}
+
+// Returns all the digits in the input string, including intervening
+// non-digit characters. For instance, if InString is "foo-3.3.4-7.img",
+// this function returns "3.3.4-7". If InString contains no digits,
+// the return value is NULL.
+CHAR16 *FindNumbers(IN CHAR16 *InString) {
+ UINTN i, StartOfElement, EndOfElement = 0, InLength, CopyLength;
+ CHAR16 *Found = NULL;
+
+ InLength = StartOfElement = StrLen(InString);
+ // Find start & end of target element
+ for (i = 0; i < InLength; i++) {
+ if ((InString[i] >= '0') && (InString[i] <= '9')) {
+ if (StartOfElement > i)
+ StartOfElement = i;
+ if (EndOfElement < i)
+ EndOfElement = i;
+ } // if
+ } // for
+ // Extract the target element
+ if (EndOfElement > 0) {
+ if (EndOfElement >= StartOfElement) {
+ CopyLength = EndOfElement - StartOfElement + 1;
+ Found = StrDuplicate(&InString[StartOfElement]);
+ if (Found != NULL)
+ Found[CopyLength] = 0;
+ } // if (EndOfElement >= StartOfElement)
+ } // if (EndOfElement > 0)
+ return (Found);
+} // CHAR16 *FindNumbers()
--- /dev/null
+/*
+ * refit/lib.h
+ * General header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#ifndef __LIB_H_
+#define __LIB_H_
+
+#include "efi.h"
+#include "efilib.h"
+
+#include "libeg.h"
+
+//
+// lib module
+//
+
+// types
+
+typedef struct {
+ EFI_STATUS LastStatus;
+ EFI_FILE_HANDLE DirHandle;
+ BOOLEAN CloseDirHandle;
+ EFI_FILE_INFO *LastFileInfo;
+} REFIT_DIR_ITER;
+
+#define DISK_KIND_INTERNAL (0)
+#define DISK_KIND_EXTERNAL (1)
+#define DISK_KIND_OPTICAL (2)
+
+#define IS_EXTENDED_PART_TYPE(type) ((type) == 0x05 || (type) == 0x0f || (type) == 0x85)
+
+EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle);
+VOID UninitRefitLib(VOID);
+EFI_STATUS ReinitRefitLib(VOID);
+
+VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount);
+VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement);
+VOID FreeList(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount /*, IN Callback*/);
+
+VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DEVICE_PATH **HardcodedPathList);
+
+VOID ScanVolumes(VOID);
+
+BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath);
+
+EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, IN UINTN FilterMode);
+
+VOID DirIterOpen(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath OPTIONAL, OUT REFIT_DIR_ITER *DirIter);
+BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR16 *FilePattern OPTIONAL, OUT EFI_FILE_INFO **DirEntry);
+EFI_STATUS DirIterClose(IN OUT REFIT_DIR_ITER *DirIter);
+
+CHAR16 * Basename(IN CHAR16 *Path);
+VOID ReplaceExtension(IN OUT CHAR16 *Path, IN CHAR16 *Extension);
+
+INTN FindMem(IN VOID *Buffer, IN UINTN BufferLength, IN VOID *SearchString, IN UINTN SearchStringLength);
+VOID ReinitVolumes(VOID);
+
+BOOLEAN StriSubCmp(IN CHAR16 *TargetStr, IN CHAR16 *BigStr);
+VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar);
+CHAR16 *FindLastDirName(IN CHAR16 *Path);
+CHAR16 *FindPath(IN CHAR16* FullPath);
+CHAR16 *FindNumbers(IN CHAR16 *InString);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * refind/main.c
+ * Main code for the boot menu
+ *
+ * Copyright (c) 2006-2010 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#include "global.h"
+#include "config.h"
+#include "screen.h"
+#include "lib.h"
+#include "icns.h"
+#include "menu.h"
+#include "refit_call_wrapper.h"
+#include "../include/syslinux_mbr.h"
+
+//
+// variables
+
+#define MACOSX_LOADER_PATH L"\\System\\Library\\CoreServices\\boot.efi"
+
+static REFIT_MENU_ENTRY MenuEntryAbout = { L"About rEFInd", TAG_ABOUT, 1, 0, 'A', NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryReset = { L"Restart Computer", TAG_RESET, 1, 0, 'R', NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
+
+static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot" };
+static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL };
+
+REFIT_CONFIG GlobalConfig = { FALSE, 20, 0, 0, FALSE, NULL, NULL, NULL, NULL };
+
+//
+// misc functions
+//
+
+static VOID AboutrEFInd(VOID)
+{
+ if (AboutMenu.EntryCount == 0) {
+ AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.2");
+ AddMenuInfoLine(&AboutMenu, L"");
+ AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
+ AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
+ AddMenuInfoLine(&AboutMenu, L"Portions Copyright (c) Intel Corporation and others");
+ AddMenuInfoLine(&AboutMenu, L"");
+ AddMenuInfoLine(&AboutMenu, L"Running on:");
+ AddMenuInfoLine(&AboutMenu, PoolPrint(L" EFI Revision %d.%02d",
+ ST->Hdr.Revision >> 16, ST->Hdr.Revision & ((1 << 16) - 1)));
+#if defined(EFI32)
+ AddMenuInfoLine(&AboutMenu, L" Platform: x86 (32 bit)");
+#elif defined(EFIX64)
+ AddMenuInfoLine(&AboutMenu, L" Platform: x86_64 (64 bit)");
+#else
+ AddMenuInfoLine(&AboutMenu, L" Platform: unknown");
+#endif
+ AddMenuInfoLine(&AboutMenu, PoolPrint(L" Firmware: %s %d.%02d",
+ ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & ((1 << 16) - 1)));
+ AddMenuInfoLine(&AboutMenu, PoolPrint(L" Screen Output: %s", egScreenDescription()));
+ AddMenuInfoLine(&AboutMenu, L"");
+ AddMenuInfoLine(&AboutMenu, L"For more information, see the rEFInd Web site:");
+ AddMenuInfoLine(&AboutMenu, L"http://www.rodsbooks.com/refind/");
+ AddMenuEntry(&AboutMenu, &MenuEntryReturn);
+ }
+
+ RunMenu(&AboutMenu, NULL);
+} /* VOID AboutrEFInd() */
+
+static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
+ IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix,
+ IN CHAR16 *ImageTitle,
+ OUT UINTN *ErrorInStep)
+{
+ EFI_STATUS Status, ReturnStatus;
+ EFI_HANDLE ChildImageHandle;
+ EFI_LOADED_IMAGE *ChildLoadedImage;
+ UINTN DevicePathIndex;
+ CHAR16 ErrorInfo[256];
+ CHAR16 *FullLoadOptions = NULL;
+
+ Print(L"Starting %s\n", ImageTitle);
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 0;
+
+ // load the image into memory
+ ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty
+ for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) {
+ ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], NULL, 0, &ChildImageHandle);
+ if (ReturnStatus != EFI_NOT_FOUND)
+ break;
+ }
+ SPrint(ErrorInfo, 255, L"while loading %s", ImageTitle);
+ if (CheckError(Status, ErrorInfo)) {
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 1;
+ goto bailout;
+ }
+
+ // set load options
+ if (LoadOptions != NULL) {
+ ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, (VOID **) &ChildLoadedImage);
+ if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) {
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 2;
+ goto bailout_unload;
+ }
+
+ if (LoadOptionsPrefix != NULL) {
+ FullLoadOptions = PoolPrint(L"%s %s ", LoadOptionsPrefix, LoadOptions);
+ // NOTE: That last space is also added by the EFI shell and seems to be significant
+ // when passing options to Apple's boot.efi...
+ LoadOptions = FullLoadOptions;
+ }
+ // NOTE: We also include the terminating null in the length for safety.
+ ChildLoadedImage->LoadOptions = (VOID *)LoadOptions;
+ ChildLoadedImage->LoadOptionsSize = ((UINT32)StrLen(LoadOptions) + 1) * sizeof(CHAR16);
+ Print(L"Using load options '%s'\n", LoadOptions);
+ }
+
+ // close open file handles
+ UninitRefitLib();
+
+ // turn control over to the image
+ // TODO: (optionally) re-enable the EFI watchdog timer!
+ ReturnStatus = Status = refit_call3_wrapper(BS->StartImage, ChildImageHandle, NULL, NULL);
+ // control returns here when the child image calls Exit()
+ SPrint(ErrorInfo, 255, L"returned from %s", ImageTitle);
+ if (CheckError(Status, ErrorInfo)) {
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 3;
+ }
+
+ // re-open file handles
+ ReinitRefitLib();
+
+bailout_unload:
+ // unload the image, we don't care if it works or not...
+ Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle);
+bailout:
+ if (FullLoadOptions != NULL)
+ FreePool(FullLoadOptions);
+ return ReturnStatus;
+} /* static EFI_STATUS StartEFIImageList() */
+
+static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
+ IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix,
+ IN CHAR16 *ImageTitle,
+ OUT UINTN *ErrorInStep)
+{
+ EFI_DEVICE_PATH *DevicePaths[2];
+
+ DevicePaths[0] = DevicePath;
+ DevicePaths[1] = NULL;
+ return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, ErrorInStep);
+} /* static EFI_STATUS StartEFIImage() */
+
+//
+// EFI OS loader functions
+//
+
+static VOID StartLoader(IN LOADER_ENTRY *Entry)
+{
+ BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS");
+ StartEFIImage(Entry->DevicePath, Entry->LoadOptions,
+ Basename(Entry->LoaderPath), Basename(Entry->LoaderPath), NULL);
+ FinishExternalScreen();
+}
+
+// Locate an initrd or initramfs file that matches the kernel specified by LoaderPath.
+// The matching file has a name that begins with "init" and includes the same version
+// number string as is found in LoaderPath -- but not a longer version number string.
+// For instance, if LoaderPath is \EFI\kernels\bzImage-3.3.0.efi, and if \EFI\kernels
+// has a file called initramfs-3.3.0.img, this function will return the string
+// '\EFI\kernels\initramfs-3.3.0.img'. If the directory ALSO contains the file
+// initramfs-3.3.0-rc7.img or initramfs-13.3.0.img, those files will NOT match;
+// however, initmine-3.3.0.img might match. (FindInitrd() returns the first match it
+// finds). Thus, care should be taken to avoid placing duplicate matching files in
+// the kernel's directory.
+// If no matching init file can be found, returns NULL.
+static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
+ CHAR16 *InitrdName = NULL, *FileName, *KernelVersion, *InitrdVersion, *Path;
+ REFIT_DIR_ITER DirIter;
+ EFI_FILE_INFO *DirEntry;
+
+ FileName = Basename(LoaderPath);
+ KernelVersion = FindNumbers(FileName);
+ Path = FindPath(LoaderPath);
+
+ DirIterOpen(Volume->RootDir, Path, &DirIter);
+ while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) {
+ InitrdVersion = FindNumbers(DirEntry->FileName);
+ if (KernelVersion != NULL) {
+// if (StriSubCmp(KernelVersion, DirEntry->FileName)) {
+ if (StriCmp(InitrdVersion, KernelVersion) == 0)
+ InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
+// } // if match found
+ } else {
+ if (InitrdVersion == NULL)
+ InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
+ } // if/else
+ if (InitrdVersion != NULL)
+ FreePool(InitrdVersion);
+ } // while
+ DirIterClose(&DirIter);
+
+ // Note: Don't FreePool(FileName), since Basename returns a pointer WITHIN the string it's passed.
+ FreePool(KernelVersion);
+ FreePool(Path);
+ return (InitrdName);
+} // static CHAR16 * FindInitrd()
+
+LOADER_ENTRY * AddPreparedLoaderEntry(LOADER_ENTRY *Entry) {
+ AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
+
+ return(Entry);
+} // LOADER_ENTRY * AddPreparedLoaderEntry()
+
+// Creates a new LOADER_ENTRY data structure and populates it with
+// default values from the specified Entry, or NULL values if Entry
+// is unspecified (NULL).
+// Returns a pointer to the new data structure, or NULL if it
+// couldn't be allocated
+LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) {
+ LOADER_ENTRY *NewEntry = NULL;
+
+ NewEntry = AllocateZeroPool(sizeof(LOADER_ENTRY));
+ if (NewEntry != NULL) {
+ NewEntry->me.Title = NULL;
+ NewEntry->me.Tag = TAG_LOADER;
+ NewEntry->Enabled = TRUE;
+ NewEntry->UseGraphicsMode = FALSE;
+ NewEntry->OSType = 0;
+ if (Entry != NULL) {
+ NewEntry->LoaderPath = StrDuplicate(Entry->LoaderPath);
+ NewEntry->VolName = StrDuplicate(Entry->VolName);
+ NewEntry->DevicePath = Entry->DevicePath;
+ NewEntry->UseGraphicsMode = Entry->UseGraphicsMode;
+ NewEntry->LoadOptions = StrDuplicate(Entry->LoadOptions);
+ NewEntry->InitrdPath = StrDuplicate(Entry->InitrdPath);
+ }
+ } // if
+ return (NewEntry);
+} // LOADER_ENTRY *InitializeLoaderEntry()
+
+// Prepare a REFIT_MENU_SCREEN data structure for a subscreen entry. This sets up
+// the default entry that launches the boot loader using the same options as the
+// main Entry does. Subsequent options can be added by the calling function.
+// If a subscreen already exists in the Entry that's passed to this function,
+// it's left unchanged and a pointer to it is returned.
+// Returns a pointer to the new subscreen data structure, or NULL if there
+// were problems allocating memory.
+REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) {
+ CHAR16 *FileName, *Temp;
+ REFIT_MENU_SCREEN *SubScreen = NULL;
+ LOADER_ENTRY *SubEntry;
+
+ FileName = Basename(Entry->LoaderPath);
+ if (Entry->me.SubScreen == NULL) { // No subscreen yet; initialize default entry....
+ SubScreen = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN));
+ if (SubScreen != NULL) {
+ SubScreen->Title = PoolPrint(L"Boot Options for %s on %s", (Entry->Title != NULL) ? Entry->Title : FileName, Entry->VolName);
+ SubScreen->TitleImage = Entry->me.Image;
+ // default entry
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot using default options";
+// SubEntry->me.Title = (Entry->OSType == 'M') ? L"Boot Mac OS X" : PoolPrint(L"Run %s", FileName);
+ if ((SubEntry->InitrdPath != NULL) && (StrLen(SubEntry->InitrdPath) > 0) && (!StriSubCmp(L"initrd", SubEntry->LoadOptions))) {
+ Temp = PoolPrint(L"initrd=%s", SubEntry->InitrdPath);
+ MergeStrings(&SubEntry->LoadOptions, Temp, L' ');
+ FreePool(Temp);
+ } // if
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if (SubEntry != NULL)
+ } // if (SubScreen != NULL)
+ } else { // existing subscreen; less initialization, and just add new entry later....
+ SubScreen = Entry->me.SubScreen;
+ } // if/else
+ return SubScreen;
+} // REFIT_MENU_SCREEN *InitializeSubScreen()
+
+VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) {
+ REFIT_MENU_SCREEN *SubScreen;
+ LOADER_ENTRY *SubEntry;
+ CHAR16 *FileName, *InitrdOption = NULL, *Temp;
+ CHAR16 DiagsFileName[256];
+ REFIT_FILE *File;
+ UINTN TokenCount;
+ CHAR16 **TokenList;
+
+ FileName = Basename(Entry->LoaderPath);
+ // create the submenu
+ if (StrLen(Entry->Title) == 0) {
+ FreePool(Entry->Title);
+ Entry->Title = NULL;
+ }
+ SubScreen = InitializeSubScreen(Entry);
+
+ // loader-specific submenu entries
+ if (Entry->OSType == 'M') { // entries for Mac OS X
+#if defined(EFIX64)
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X with a 64-bit kernel";
+ SubEntry->LoadOptions = L"arch=x86_64";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X with a 32-bit kernel";
+ SubEntry->LoadOptions = L"arch=i386";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if
+#endif
+
+ if (!(GlobalConfig.DisableFlags & DISABLE_FLAG_SINGLEUSER)) {
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X in verbose mode";
+ SubEntry->UseGraphicsMode = FALSE;
+ SubEntry->LoadOptions = L"-v";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if
+
+#if defined(EFIX64)
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X in verbose mode (64-bit)";
+ SubEntry->UseGraphicsMode = FALSE;
+ SubEntry->LoadOptions = L"-v arch=x86_64";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X in verbose mode (32-bit)";
+ SubEntry->UseGraphicsMode = FALSE;
+ SubEntry->LoadOptions = L"-v arch=i386";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+#endif
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Mac OS X in single user mode";
+ SubEntry->UseGraphicsMode = FALSE;
+ SubEntry->LoadOptions = L"-v -s";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if
+ } // not single-user
+
+ // check for Apple hardware diagnostics
+ StrCpy(DiagsFileName, L"\\System\\Library\\CoreServices\\.diagnostics\\diags.efi");
+ if (FileExists(Volume->RootDir, DiagsFileName) && !(GlobalConfig.DisableFlags & DISABLE_FLAG_HWTEST)) {
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Run Apple Hardware Test";
+ FreePool(SubEntry->LoaderPath);
+ SubEntry->LoaderPath = StrDuplicate(DiagsFileName);
+ SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath);
+ SubEntry->UseGraphicsMode = TRUE;
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // if
+ } // if diagnostics entry found
+
+ } else if (Entry->OSType == 'L') { // entries for Linux kernels with EFI stub loaders
+ File = ReadLinuxOptionsFile(Entry->LoaderPath, Volume);
+ if (File != NULL) {
+ if ((Temp = FindInitrd(Entry->LoaderPath, Volume)) != NULL)
+ InitrdOption = PoolPrint(L"initrd=%s", Temp);
+ TokenCount = ReadTokenLine(File, &TokenList); // read and discard first entry, since it's
+ FreeTokenLine(&TokenList, &TokenCount); // set up by InitializeSubScreen(), earlier....
+ while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) {
+ SubEntry = InitializeLoaderEntry(Entry);
+ SubEntry->me.Title = StrDuplicate(TokenList[0]);
+ if (SubEntry->LoadOptions != NULL)
+ FreePool(SubEntry->LoadOptions);
+ SubEntry->LoadOptions = StrDuplicate(TokenList[1]);
+ MergeStrings(&SubEntry->LoadOptions, InitrdOption, L' ');
+ FreeTokenLine(&TokenList, &TokenCount);
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ } // while
+ if (InitrdOption)
+ FreePool(InitrdOption);
+ if (Temp)
+ FreePool(Temp);
+ FreePool(File);
+ } // if Linux options file exists
+
+ } else if (Entry->OSType == 'E') { // entries for ELILO
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = PoolPrint(L"Run %s in interactive mode", FileName);
+ SubEntry->LoadOptions = L"-p";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Linux for a 17\" iMac or a 15\" MacBook Pro (*)";
+ SubEntry->UseGraphicsMode = TRUE;
+ SubEntry->LoadOptions = L"-d 0 i17";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Linux for a 20\" iMac (*)";
+ SubEntry->UseGraphicsMode = TRUE;
+ SubEntry->LoadOptions = L"-d 0 i20";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Linux for a Mac Mini (*)";
+ SubEntry->UseGraphicsMode = TRUE;
+ SubEntry->LoadOptions = L"-d 0 mini";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ AddMenuInfoLine(SubScreen, L"NOTE: This is an example. Entries");
+ AddMenuInfoLine(SubScreen, L"marked with (*) may not work.");
+
+ } else if (Entry->OSType == 'X') { // entries for xom.efi
+ // by default, skip the built-in selection and boot from hard disk only
+ Entry->LoadOptions = L"-s -h";
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Windows from Hard Disk";
+ SubEntry->LoadOptions = L"-s -h";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = L"Boot Windows from CD-ROM";
+ SubEntry->LoadOptions = L"-s -c";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+
+ SubEntry = InitializeLoaderEntry(Entry);
+ if (SubEntry != NULL) {
+ SubEntry->me.Title = PoolPrint(L"Run %s in text mode", FileName);
+ SubEntry->UseGraphicsMode = FALSE;
+ SubEntry->LoadOptions = L"-v";
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+ }
+ } // entries for xom.efi
+ AddMenuEntry(SubScreen, &MenuEntryReturn);
+ Entry->me.SubScreen = SubScreen;
+} // VOID GenerateSubScreen()
+
+// Returns options for a Linux kernel. Reads them from an options file in the
+// kernel's directory; and if present, adds an initrd= option for an initial
+// RAM disk file with the same version number as the kernel file.
+static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Volume) {
+ CHAR16 *Options = NULL, *InitrdName, *InitrdOption = NULL;
+
+ Options = GetFirstOptionsFromFile(LoaderPath, Volume);
+ InitrdName = FindInitrd(LoaderPath, Volume);
+ if (InitrdName != NULL)
+ InitrdOption = PoolPrint(L"initrd=%s", InitrdName);
+ MergeStrings(&Options, InitrdOption, ' ');
+ if (InitrdOption != NULL)
+ FreePool(InitrdOption);
+ if (InitrdName != NULL)
+ FreePool(InitrdName);
+ return (Options);
+} // static CHAR16 * GetMainLinuxOptions()
+
+// Sets a few defaults for a loader entry -- mainly the icon, but also the OS type
+// code and shortcut letter. For Linux EFI stub loaders, also sets kernel options
+// that will (with luck) work fairly automatically.
+VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
+ CHAR16 IconFileName[256];
+ CHAR16 *FileName, *OSIconName = NULL, *Temp;
+ CHAR16 ShortcutLetter = 0;
+
+ FileName = Basename(LoaderPath);
+
+ // locate a custom icon for the loader
+ StrCpy(IconFileName, LoaderPath);
+ ReplaceExtension(IconFileName, L".icns");
+ if (FileExists(Volume->RootDir, IconFileName)) {
+ Entry->me.Image = LoadIcns(Volume->RootDir, IconFileName, 128);
+ } // if
+
+ Temp = FindLastDirName(LoaderPath);
+ MergeStrings(&OSIconName, Temp, L',');
+ FreePool(Temp);
+ if (OSIconName != NULL) {
+ ShortcutLetter = OSIconName[0];
+ }
+
+ // detect specific loaders
+ if (StriSubCmp(L"bzImage", LoaderPath) || StriSubCmp(L"vmlinuz", LoaderPath)) {
+ MergeStrings(&OSIconName, L"linux", L',');
+ Entry->OSType = 'L';
+ if (ShortcutLetter == 0)
+ ShortcutLetter = 'L';
+ Entry->LoadOptions = GetMainLinuxOptions(LoaderPath, Volume);
+ } else if (StriSubCmp(L"refit", LoaderPath)) {
+ MergeStrings(&OSIconName, L"refit", L',');
+ Entry->OSType = 'R';
+ ShortcutLetter = 'R';
+ } else if (StriCmp(LoaderPath, MACOSX_LOADER_PATH) == 0) {
+ MergeStrings(&OSIconName, L"mac", L',');
+ Entry->UseGraphicsMode = TRUE;
+ Entry->OSType = 'M';
+ ShortcutLetter = 'M';
+ } else if (StriCmp(FileName, L"diags.efi") == 0) {
+ MergeStrings(&OSIconName, L"hwtest", L',');
+ } else if (StriCmp(FileName, L"e.efi") == 0 || StriCmp(FileName, L"elilo.efi") == 0) {
+ MergeStrings(&OSIconName, L"elilo,linux", L',');
+ Entry->OSType = 'E';
+ if (ShortcutLetter == 0)
+ ShortcutLetter = 'L';
+ } else if (StriCmp(FileName, L"cdboot.efi") == 0 ||
+ StriCmp(FileName, L"bootmgr.efi") == 0 ||
+ StriCmp(FileName, L"Bootmgfw.efi") == 0) {
+ MergeStrings(&OSIconName, L"win", L',');
+ Entry->OSType = 'W';
+ ShortcutLetter = 'W';
+ } else if (StriCmp(FileName, L"xom.efi") == 0) {
+ MergeStrings(&OSIconName, L"xom,win", L',');
+ Entry->UseGraphicsMode = TRUE;
+ Entry->OSType = 'X';
+ ShortcutLetter = 'W';
+ }
+
+ if ((ShortcutLetter >= 'a') && (ShortcutLetter <= 'z'))
+ ShortcutLetter = ShortcutLetter - 'a' + 'A'; // convert lowercase to uppercase
+ Entry->me.ShortcutLetter = ShortcutLetter;
+ if (Entry->me.Image == NULL)
+ Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE);
+} // VOID SetLoaderDefaults()
+
+// Add a specified EFI boot loader to the list, using automatic settings
+// for icons, options, etc.
+LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) {
+ LOADER_ENTRY *Entry;
+
+ Entry = InitializeLoaderEntry(NULL);
+ if (Entry != NULL) {
+ Entry->Title = StrDuplicate(LoaderTitle);
+ Entry->me.Title = PoolPrint(L"Boot %s from %s", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath + 1, Volume->VolName);
+ Entry->me.Row = 0;
+ Entry->me.BadgeImage = Volume->VolBadgeImage;
+ Entry->LoaderPath = StrDuplicate(LoaderPath);
+ Entry->VolName = Volume->VolName;
+ Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath);
+ SetLoaderDefaults(Entry, LoaderPath, Volume);
+ GenerateSubScreen(Entry, Volume);
+ AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
+ }
+
+ return(Entry);
+} // LOADER_ENTRY * AddLoaderEntry()
+
+// Scan an individual directory for EFI boot loader files and, if found,
+// add them to the list.
+static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path)
+{
+ EFI_STATUS Status;
+ REFIT_DIR_ITER DirIter;
+ EFI_FILE_INFO *DirEntry;
+ CHAR16 FileName[256];
+
+ // Note: SelfDirPath includes a leading backslash ('\'), but Path
+ // doesn't, so we rejigger the string to compensate....
+ if (!SelfDirPath || !Path || ((StriCmp(Path, &SelfDirPath[1]) == 0) && Volume != SelfVolume) ||
+ (StriCmp(Path, &SelfDirPath[1]) != 0)) {
+ // look through contents of the directory
+ DirIterOpen(Volume->RootDir, Path, &DirIter);
+ while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) {
+ if (DirEntry->FileName[0] == '.' ||
+ StriCmp(DirEntry->FileName, L"TextMode.efi") == 0 ||
+ StriCmp(DirEntry->FileName, L"ebounce.efi") == 0 ||
+ StriCmp(DirEntry->FileName, L"GraphicsConsole.efi") == 0)
+ continue; // skip this
+
+ if (Path)
+ SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName);
+ else
+ SPrint(FileName, 255, L"\\%s", DirEntry->FileName);
+ AddLoaderEntry(FileName, NULL, Volume);
+ }
+ Status = DirIterClose(&DirIter);
+ if (Status != EFI_NOT_FOUND) {
+ if (Path)
+ SPrint(FileName, 255, L"while scanning the %s directory", Path);
+ else
+ StrCpy(FileName, L"while scanning the root directory");
+ CheckError(Status, FileName);
+ } // if (Status != EFI_NOT_FOUND)
+ } // if not scanning our own directory
+} /* static VOID ScanLoaderDir() */
+
+static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
+ EFI_STATUS Status;
+ REFIT_DIR_ITER EfiDirIter;
+ EFI_FILE_INFO *EfiDirEntry;
+ CHAR16 FileName[256];
+// LOADER_ENTRY *Entry;
+
+ if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) {
+ // check for Mac OS X boot loader
+ StrCpy(FileName, MACOSX_LOADER_PATH);
+ if (FileExists(Volume->RootDir, FileName)) {
+ AddLoaderEntry(FileName, L"Mac OS X", Volume);
+ }
+
+ // check for XOM
+ StrCpy(FileName, L"\\System\\Library\\CoreServices\\xom.efi");
+ if (FileExists(Volume->RootDir, FileName)) {
+ AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume);
+ }
+
+ // check for Microsoft boot loader/menu
+ StrCpy(FileName, L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi");
+ if (FileExists(Volume->RootDir, FileName)) {
+ AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume);
+ }
+
+ // scan the root directory for EFI executables
+ ScanLoaderDir(Volume, NULL);
+ // scan the elilo directory (as used on gimli's first Live CD)
+ ScanLoaderDir(Volume, L"elilo");
+ // scan the boot directory
+ ScanLoaderDir(Volume, L"boot");
+
+ // scan subdirectories of the EFI directory (as per the standard)
+ DirIterOpen(Volume->RootDir, L"EFI", &EfiDirIter);
+ while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) {
+ if (StriCmp(EfiDirEntry->FileName, L"TOOLS") == 0 || EfiDirEntry->FileName[0] == '.')
+ continue; // skip this, doesn't contain boot loaders
+ SPrint(FileName, 255, L"EFI\\%s", EfiDirEntry->FileName);
+ ScanLoaderDir(Volume, FileName);
+ } // while()
+ Status = DirIterClose(&EfiDirIter);
+ if (Status != EFI_NOT_FOUND)
+ CheckError(Status, L"while scanning the EFI directory");
+ } // if
+} // static VOID ScanEfiFiles()
+
+// Scan internal disks for valid EFI boot loaders....
+static VOID ScanInternal(VOID) {
+ UINTN VolumeIndex;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_INTERNAL) {
+ ScanEfiFiles(Volumes[VolumeIndex]);
+ }
+ } // for
+} // static VOID ScanInternal()
+
+// Scan external disks for valid EFI boot loaders....
+static VOID ScanExternal(VOID) {
+ UINTN VolumeIndex;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_EXTERNAL) {
+ ScanEfiFiles(Volumes[VolumeIndex]);
+ }
+ } // for
+} // static VOID ScanExternal()
+
+// Scan internal disks for valid EFI boot loaders....
+static VOID ScanOptical(VOID) {
+ UINTN VolumeIndex;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_OPTICAL) {
+ ScanEfiFiles(Volumes[VolumeIndex]);
+ }
+ } // for
+} // static VOID ScanOptical()
+
+//
+// legacy boot functions
+//
+
+static EFI_STATUS ActivateMbrPartition(IN EFI_BLOCK_IO *BlockIO, IN UINTN PartitionIndex)
+{
+ EFI_STATUS Status;
+ UINT8 SectorBuffer[512];
+ MBR_PARTITION_INFO *MbrTable, *EMbrTable;
+ UINT32 ExtBase, ExtCurrent, NextExtCurrent;
+ UINTN LogicalPartitionIndex = 4;
+ UINTN i;
+ BOOLEAN HaveBootCode;
+
+ // read MBR
+ Status = refit_call5_wrapper(BlockIO->ReadBlocks, BlockIO, BlockIO->Media->MediaId, 0, 512, SectorBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+ if (*((UINT16 *)(SectorBuffer + 510)) != 0xaa55)
+ return EFI_NOT_FOUND; // safety measure #1
+
+ // add boot code if necessary
+ HaveBootCode = FALSE;
+ for (i = 0; i < MBR_BOOTCODE_SIZE; i++) {
+ if (SectorBuffer[i] != 0) {
+ HaveBootCode = TRUE;
+ break;
+ }
+ }
+ if (!HaveBootCode) {
+ // no boot code found in the MBR, add the syslinux MBR code
+ SetMem(SectorBuffer, MBR_BOOTCODE_SIZE, 0);
+ CopyMem(SectorBuffer, syslinux_mbr, SYSLINUX_MBR_SIZE);
+ }
+
+ // set the partition active
+ MbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446);
+ ExtBase = 0;
+ for (i = 0; i < 4; i++) {
+ if (MbrTable[i].Flags != 0x00 && MbrTable[i].Flags != 0x80)
+ return EFI_NOT_FOUND; // safety measure #2
+ if (i == PartitionIndex)
+ MbrTable[i].Flags = 0x80;
+ else if (PartitionIndex >= 4 && IS_EXTENDED_PART_TYPE(MbrTable[i].Type)) {
+ MbrTable[i].Flags = 0x80;
+ ExtBase = MbrTable[i].StartLBA;
+ } else
+ MbrTable[i].Flags = 0x00;
+ }
+
+ // write MBR
+ Status = refit_call5_wrapper(BlockIO->WriteBlocks, BlockIO, BlockIO->Media->MediaId, 0, 512, SectorBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ if (PartitionIndex >= 4) {
+ // we have to activate a logical partition, so walk the EMBR chain
+
+ // NOTE: ExtBase was set above while looking at the MBR table
+ for (ExtCurrent = ExtBase; ExtCurrent; ExtCurrent = NextExtCurrent) {
+ // read current EMBR
+ Status = refit_call5_wrapper(BlockIO->ReadBlocks, BlockIO, BlockIO->Media->MediaId, ExtCurrent, 512, SectorBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+ if (*((UINT16 *)(SectorBuffer + 510)) != 0xaa55)
+ return EFI_NOT_FOUND; // safety measure #3
+
+ // scan EMBR, set appropriate partition active
+ EMbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446);
+ NextExtCurrent = 0;
+ for (i = 0; i < 4; i++) {
+ if (EMbrTable[i].Flags != 0x00 && EMbrTable[i].Flags != 0x80)
+ return EFI_NOT_FOUND; // safety measure #4
+ if (EMbrTable[i].StartLBA == 0 || EMbrTable[i].Size == 0)
+ break;
+ if (IS_EXTENDED_PART_TYPE(EMbrTable[i].Type)) {
+ // link to next EMBR
+ NextExtCurrent = ExtBase + EMbrTable[i].StartLBA;
+ EMbrTable[i].Flags = (PartitionIndex >= LogicalPartitionIndex) ? 0x80 : 0x00;
+ break;
+ } else {
+ // logical partition
+ EMbrTable[i].Flags = (PartitionIndex == LogicalPartitionIndex) ? 0x80 : 0x00;
+ LogicalPartitionIndex++;
+ }
+ }
+
+ // write current EMBR
+ Status = refit_call5_wrapper(BlockIO->WriteBlocks, BlockIO, BlockIO->Media->MediaId, ExtCurrent, 512, SectorBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ if (PartitionIndex < LogicalPartitionIndex)
+ break; // stop the loop, no need to touch further EMBRs
+ }
+
+ }
+
+ return EFI_SUCCESS;
+} /* static EFI_STATUS ActivateMbrPartition() */
+
+// early 2006 Core Duo / Core Solo models
+static UINT8 LegacyLoaderDevicePath1Data[] = {
+ 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+// mid-2006 Mac Pro (and probably other Core 2 models)
+static UINT8 LegacyLoaderDevicePath2Data[] = {
+ 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+// mid-2007 MBP ("Santa Rosa" based models)
+static UINT8 LegacyLoaderDevicePath3Data[] = {
+ 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+// early-2008 MBA
+static UINT8 LegacyLoaderDevicePath4Data[] = {
+ 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+// late-2008 MB/MBP (NVidia chipset)
+static UINT8 LegacyLoaderDevicePath5Data[] = {
+ 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0xCB, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xBF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+ 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+ 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+static EFI_DEVICE_PATH *LegacyLoaderList[] = {
+ (EFI_DEVICE_PATH *)LegacyLoaderDevicePath1Data,
+ (EFI_DEVICE_PATH *)LegacyLoaderDevicePath2Data,
+ (EFI_DEVICE_PATH *)LegacyLoaderDevicePath3Data,
+ (EFI_DEVICE_PATH *)LegacyLoaderDevicePath4Data,
+ (EFI_DEVICE_PATH *)LegacyLoaderDevicePath5Data,
+ NULL
+};
+
+#define MAX_DISCOVERED_PATHS (16)
+
+static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
+{
+ EFI_STATUS Status;
+ EG_IMAGE *BootLogoImage;
+ UINTN ErrorInStep = 0;
+ EFI_DEVICE_PATH *DiscoveredPathList[MAX_DISCOVERED_PATHS];
+
+ BeginExternalScreen(TRUE, L"Booting Legacy OS");
+
+ BootLogoImage = LoadOSIcon(Entry->Volume->OSIconName, L"legacy", TRUE);
+ if (BootLogoImage != NULL)
+ BltImageAlpha(BootLogoImage,
+ (UGAWidth - BootLogoImage->Width ) >> 1,
+ (UGAHeight - BootLogoImage->Height) >> 1,
+ &StdBackgroundPixel);
+
+ if (Entry->Volume->IsMbrPartition)
+ ActivateMbrPartition(Entry->Volume->WholeDiskBlockIO, Entry->Volume->MbrPartitionIndex);
+
+ ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList);
+
+ Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, NULL, L"legacy loader", &ErrorInStep);
+ if (Status == EFI_NOT_FOUND) {
+ if (ErrorInStep == 1) {
+ Print(L"\nPlease make sure that you have the latest firmware update installed.\n");
+ } else if (ErrorInStep == 3) {
+ Print(L"\nThe firmware refused to boot from the selected volume. Note that external\n"
+ L"hard drives are not well-supported by Apple's firmware for legacy OS booting.\n");
+ }
+ }
+ FinishExternalScreen();
+} /* static VOID StartLegacy() */
+
+static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume)
+{
+ LEGACY_ENTRY *Entry, *SubEntry;
+ REFIT_MENU_SCREEN *SubScreen;
+ CHAR16 *VolDesc;
+ CHAR16 ShortcutLetter = 0;
+
+ if (LoaderTitle == NULL) {
+ if (Volume->OSName != NULL) {
+ LoaderTitle = Volume->OSName;
+ if (LoaderTitle[0] == 'W' || LoaderTitle[0] == 'L')
+ ShortcutLetter = LoaderTitle[0];
+ } else
+ LoaderTitle = L"Legacy OS";
+ }
+ if (Volume->VolName != NULL)
+ VolDesc = Volume->VolName;
+ else
+ VolDesc = (Volume->DiskKind == DISK_KIND_OPTICAL) ? L"CD" : L"HD";
+
+ // prepare the menu entry
+ Entry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
+ Entry->me.Title = PoolPrint(L"Boot %s from %s", LoaderTitle, VolDesc);
+ Entry->me.Tag = TAG_LEGACY;
+ Entry->me.Row = 0;
+ Entry->me.ShortcutLetter = ShortcutLetter;
+ Entry->me.Image = LoadOSIcon(Volume->OSIconName, L"legacy", FALSE);
+ Entry->me.BadgeImage = Volume->VolBadgeImage;
+ Entry->Volume = Volume;
+ Entry->LoadOptions = (Volume->DiskKind == DISK_KIND_OPTICAL) ? L"CD" :
+ ((Volume->DiskKind == DISK_KIND_EXTERNAL) ? L"USB" : L"HD");
+ Entry->Enabled = TRUE;
+
+ // create the submenu
+ SubScreen = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN));
+ SubScreen->Title = PoolPrint(L"Boot Options for %s on %s", LoaderTitle, VolDesc);
+ SubScreen->TitleImage = Entry->me.Image;
+
+ // default entry
+ SubEntry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
+ SubEntry->me.Title = PoolPrint(L"Boot %s", LoaderTitle);
+ SubEntry->me.Tag = TAG_LEGACY;
+ SubEntry->Volume = Entry->Volume;
+ SubEntry->LoadOptions = Entry->LoadOptions;
+ AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+
+ AddMenuEntry(SubScreen, &MenuEntryReturn);
+ Entry->me.SubScreen = SubScreen;
+ AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
+ return Entry;
+} /* static LEGACY_ENTRY * AddLegacyEntry() */
+
+static VOID ScanLegacyVolume(REFIT_VOLUME *Volume, UINTN VolumeIndex) {
+ UINTN VolumeIndex2;
+ BOOLEAN ShowVolume, HideIfOthersFound;
+
+ ShowVolume = FALSE;
+ HideIfOthersFound = FALSE;
+ if (Volume->IsAppleLegacy) {
+ ShowVolume = TRUE;
+ HideIfOthersFound = TRUE;
+ } else if (Volume->HasBootCode) {
+ ShowVolume = TRUE;
+ if (Volume->BlockIO == Volume->WholeDiskBlockIO &&
+ Volume->BlockIOOffset == 0 &&
+ Volume->OSName == NULL)
+ // this is a whole disk (MBR) entry; hide if we have entries for partitions
+ HideIfOthersFound = TRUE;
+ }
+ if (HideIfOthersFound) {
+ // check for other bootable entries on the same disk
+ for (VolumeIndex2 = 0; VolumeIndex2 < VolumesCount; VolumeIndex2++) {
+ if (VolumeIndex2 != VolumeIndex && Volumes[VolumeIndex2]->HasBootCode &&
+ Volumes[VolumeIndex2]->WholeDiskBlockIO == Volume->WholeDiskBlockIO)
+ ShowVolume = FALSE;
+ }
+ }
+
+ if (ShowVolume)
+ AddLegacyEntry(NULL, Volume);
+} // static VOID ScanLegacyVolume()
+
+// Scan attached optical discs for legacy (BIOS) boot code
+// and add anything found to the list....
+static VOID ScanLegacyDisc(VOID)
+{
+ UINTN VolumeIndex;
+ REFIT_VOLUME *Volume;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+ if (Volume->DiskKind == DISK_KIND_OPTICAL)
+ ScanLegacyVolume(Volume, VolumeIndex);
+ } // for
+} /* static VOID ScanLegacyDisc() */
+
+// Scan internal hard disks for legacy (BIOS) boot code
+// and add anything found to the list....
+static VOID ScanLegacyInternal(VOID)
+{
+ UINTN VolumeIndex;
+ REFIT_VOLUME *Volume;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+ if (Volume->DiskKind == DISK_KIND_INTERNAL)
+ ScanLegacyVolume(Volume, VolumeIndex);
+ } // for
+} /* static VOID ScanLegacyInternal() */
+
+// Scan external disks for legacy (BIOS) boot code
+// and add anything found to the list....
+static VOID ScanLegacyExternal(VOID)
+{
+ UINTN VolumeIndex;
+ REFIT_VOLUME *Volume;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+ if (Volume->DiskKind == DISK_KIND_EXTERNAL)
+ ScanLegacyVolume(Volume, VolumeIndex);
+ } // for
+} /* static VOID ScanLegacyExternal() */
+
+//
+// pre-boot tool functions
+//
+
+static VOID StartTool(IN LOADER_ENTRY *Entry)
+{
+ BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start <title>" as assigned below
+ StartEFIImage(Entry->DevicePath, Entry->LoadOptions, Basename(Entry->LoaderPath),
+ Basename(Entry->LoaderPath), NULL);
+ FinishExternalScreen();
+} /* static VOID StartTool() */
+
+static LOADER_ENTRY * AddToolEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image,
+ IN CHAR16 ShortcutLetter, IN BOOLEAN UseGraphicsMode)
+{
+ LOADER_ENTRY *Entry;
+
+ Entry = AllocateZeroPool(sizeof(LOADER_ENTRY));
+
+ Entry->me.Title = PoolPrint(L"Start %s", LoaderTitle);
+ Entry->me.Tag = TAG_TOOL;
+ Entry->me.Row = 1;
+ Entry->me.ShortcutLetter = ShortcutLetter;
+ Entry->me.Image = Image;
+ Entry->LoaderPath = StrDuplicate(LoaderPath);
+ Entry->DevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, Entry->LoaderPath);
+ Entry->UseGraphicsMode = UseGraphicsMode;
+
+ AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
+ return Entry;
+} /* static LOADER_ENTRY * AddToolEntry() */
+
+static VOID ScanTool(VOID)
+{
+ CHAR16 FileName[256];
+ LOADER_ENTRY *Entry;
+
+ if (GlobalConfig.DisableFlags & DISABLE_FLAG_TOOLS)
+ return;
+
+ // look for the EFI shell
+ if (!(GlobalConfig.DisableFlags & DISABLE_FLAG_SHELL)) {
+ SPrint(FileName, 255, L"%s\\apps\\shell.efi", SelfDirPath);
+ if (FileExists(SelfRootDir, FileName)) {
+ AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'E', FALSE);
+ } else {
+ StrCpy(FileName, L"\\efi\\tools\\shell.efi");
+ if (FileExists(SelfRootDir, FileName)) {
+ AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'E', FALSE);
+ }
+ }
+ }
+
+ // look for the GPT/MBR sync tool
+ StrCpy(FileName, L"\\efi\\tools\\gptsync.efi");
+ if (FileExists(SelfRootDir, FileName)) {
+ AddToolEntry(FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE);
+ }
+
+ // look for rescue Linux
+ StrCpy(FileName, L"\\efi\\rescue\\elilo.efi");
+ if (SelfVolume != NULL && FileExists(SelfRootDir, FileName)) {
+ Entry = AddToolEntry(FileName, L"Rescue Linux", BuiltinIcon(BUILTIN_ICON_TOOL_RESCUE), '0', FALSE);
+
+ if (UGAWidth == 1440 && UGAHeight == 900)
+ Entry->LoadOptions = L"-d 0 i17";
+ else if (UGAWidth == 1680 && UGAHeight == 1050)
+ Entry->LoadOptions = L"-d 0 i20";
+ else
+ Entry->LoadOptions = L"-d 0 mini";
+ }
+}
+
+
+#ifdef DEBIAN_ENABLE_EFI110
+//
+// pre-boot driver functions
+//
+
+static VOID ScanDriverDir(IN CHAR16 *Path)
+{
+ EFI_STATUS Status;
+ REFIT_DIR_ITER DirIter;
+ EFI_FILE_INFO *DirEntry;
+ CHAR16 FileName[256];
+
+ // look through contents of the directory
+ DirIterOpen(SelfRootDir, Path, &DirIter);
+ while (DirIterNext(&DirIter, 2, L"*.EFI", &DirEntry)) {
+ if (DirEntry->FileName[0] == '.')
+ continue; // skip this
+
+ SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName);
+ Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName),
+ L"", DirEntry->FileName, DirEntry->FileName, NULL);
+ }
+ Status = DirIterClose(&DirIter);
+ if (Status != EFI_NOT_FOUND) {
+ SPrint(FileName, 255, L"while scanning the %s directory", Path);
+ CheckError(Status, FileName);
+ }
+}
+
+static EFI_STATUS ConnectAllDriversToAllControllers(VOID)
+{
+ EFI_STATUS Status;
+ UINTN AllHandleCount;
+ EFI_HANDLE *AllHandleBuffer;
+ UINTN Index;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINT32 *HandleType;
+ UINTN HandleIndex;
+ BOOLEAN Parent;
+ BOOLEAN Device;
+
+ Status = LibLocateHandle(AllHandles,
+ NULL,
+ NULL,
+ &AllHandleCount,
+ &AllHandleBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ for (Index = 0; Index < AllHandleCount; Index++) {
+ //
+ // Scan the handle database
+ //
+ Status = LibScanHandleDatabase(NULL,
+ NULL,
+ AllHandleBuffer[Index],
+ NULL,
+ &HandleCount,
+ &HandleBuffer,
+ &HandleType);
+ if (EFI_ERROR (Status))
+ goto Done;
+
+ Device = TRUE;
+ if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
+ Device = FALSE;
+ if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE)
+ Device = FALSE;
+
+ if (Device) {
+ Parent = FALSE;
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE)
+ Parent = TRUE;
+ }
+
+ if (!Parent) {
+ if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) {
+ Status = refit_call4_wrapper(BS->ConnectController,
+ AllHandleBuffer[Index],
+ NULL,
+ NULL,
+ TRUE);
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+ FreePool (HandleType);
+ }
+
+Done:
+ FreePool (AllHandleBuffer);
+ return Status;
+}
+
+static VOID LoadDrivers(VOID)
+{
+ CHAR16 DirName[256];
+
+ // load drivers from /efi/refind/drivers
+ SPrint(DirName, 255, L"%s\\drivers", SelfDirPath);
+ ScanDriverDir(DirName);
+
+ // load drivers from /efi/tools/drivers
+ ScanDriverDir(L"\\efi\\tools\\drivers");
+
+ // connect all devices
+ ConnectAllDriversToAllControllers();
+}
+#endif /* DEBIAN_ENABLE_EFI110 */
+
+static VOID ScanForBootloaders(VOID) {
+ UINTN i;
+
+ ScanVolumes();
+ // Commented-out below: Was part of an attempt to get rEFInd to
+ // re-scan disk devices on pressing Esc; but doesn't work (yet), so
+ // removed....
+// MainMenu.Title = StrDuplicate(L"Main Menu 2");
+// MainMenu.TitleImage = NULL;
+// MainMenu.InfoLineCount = 0;
+// MainMenu.InfoLines = NULL;
+// MainMenu.EntryCount = 0;
+// MainMenu.Entries = NULL;
+// MainMenu.TimeoutSeconds = 20;
+// MainMenu.TimeoutText = StrDuplicate(L"Automatic boot");
+ // DebugPause();
+
+ // scan for loaders and tools, add them to the menu
+ for (i = 0; i < NUM_SCAN_OPTIONS; i++) {
+ switch(GlobalConfig.ScanFor[i]) {
+ case 'c': case 'C':
+ ScanLegacyDisc();
+ break;
+ case 'h': case 'H':
+ ScanLegacyInternal();
+ break;
+ case 'b': case 'B':
+ ScanLegacyExternal();
+ break;
+ case 'm': case 'M':
+ ScanUserConfigured();
+ break;
+ case 'e': case 'E':
+ ScanExternal();
+ break;
+ case 'i': case 'I':
+ ScanInternal();
+ break;
+ case 'o': case 'O':
+ ScanOptical();
+ break;
+ } // switch()
+ } // for
+ ScanTool();
+
+ // fixed other menu entries
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_FUNCS)) {
+ MenuEntryAbout.Image = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
+ AddMenuEntry(&MainMenu, &MenuEntryAbout);
+ }
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_FUNCS) || MainMenu.EntryCount == 0) {
+ MenuEntryShutdown.Image = BuiltinIcon(BUILTIN_ICON_FUNC_SHUTDOWN);
+ AddMenuEntry(&MainMenu, &MenuEntryShutdown);
+ MenuEntryReset.Image = BuiltinIcon(BUILTIN_ICON_FUNC_RESET);
+ AddMenuEntry(&MainMenu, &MenuEntryReset);
+ }
+
+ // assign shortcut keys
+ for (i = 0; i < MainMenu.EntryCount && MainMenu.Entries[i]->Row == 0 && i < 9; i++)
+ MainMenu.Entries[i]->ShortcutDigit = (CHAR16)('1' + i);
+
+ // wait for user ACK when there were errors
+ FinishTextScreen(FALSE);
+} // static VOID ScanForBootloaders()
+
+//
+// main entry point
+//
+
+EFI_STATUS
+EFIAPI
+efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ BOOLEAN MainLoopRunning = TRUE;
+ REFIT_MENU_ENTRY *ChosenEntry;
+ UINTN MenuExit;
+
+ // bootstrap
+ InitializeLib(ImageHandle, SystemTable);
+ InitScreen();
+ Status = InitRefitLib(ImageHandle);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ // read configuration
+ CopyMem(GlobalConfig.ScanFor, "ieo ", NUM_SCAN_OPTIONS);
+ ReadConfig();
+ MainMenu.TimeoutSeconds = GlobalConfig.Timeout;
+
+ // disable EFI watchdog timer
+ refit_call4_wrapper(BS->SetWatchdogTimer, 0x0000, 0x0000, 0x0000, NULL);
+
+ // further bootstrap (now with config available)
+ SetupScreen();
+#ifdef DEBIAN_ENABLE_EFI110
+ LoadDrivers();
+#endif /* DEBIAN_ENABLE_EFI110 */
+ ScanForBootloaders();
+
+ while (MainLoopRunning) {
+ MenuExit = RunMainMenu(&MainMenu, GlobalConfig.DefaultSelection, &ChosenEntry);
+
+ // We don't allow exiting the main menu with the Escape key.
+ if (MenuExit == MENU_EXIT_ESCAPE) {
+ // Commented-out below: Was part of an attempt to get rEFInd to
+ // re-scan disk devices on pressing Esc; but doesn't work (yet), so
+ // removed....
+// ReadConfig();
+// ScanForBootloaders();
+// SetupScreen();
+ continue;
+ }
+
+ switch (ChosenEntry->Tag) {
+
+ case TAG_RESET: // Restart
+ TerminateScreen();
+ refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL);
+ MainLoopRunning = FALSE; // just in case we get this far
+ break;
+
+ case TAG_SHUTDOWN: // Shut Down
+ TerminateScreen();
+ refit_call4_wrapper(RT->ResetSystem, EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ MainLoopRunning = FALSE; // just in case we get this far
+ break;
+
+ case TAG_ABOUT: // About rEFInd
+ AboutrEFInd();
+ break;
+
+ case TAG_LOADER: // Boot OS via .EFI loader
+ StartLoader((LOADER_ENTRY *)ChosenEntry);
+ break;
+
+ case TAG_LEGACY: // Boot legacy OS
+ StartLegacy((LEGACY_ENTRY *)ChosenEntry);
+ break;
+
+ case TAG_TOOL: // Start a EFI tool
+ StartTool((LOADER_ENTRY *)ChosenEntry);
+ break;
+
+ }
+ }
+
+ // If we end up here, things have gone wrong. Try to reboot, and if that
+ // fails, go into an endless loop.
+ refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL);
+ EndlessIdleLoop();
+
+ return EFI_SUCCESS;
+} /* efi_main() */
--- /dev/null
+/*
+ * refit/menu.c
+ * Menu functions
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#include "global.h"
+#include "screen.h"
+#include "lib.h"
+#include "menu.h"
+#include "config.h"
+#include "libeg.h"
+#include "refit_call_wrapper.h"
+
+#include "egemb_back_selected_small.h"
+#include "egemb_arrow_left.h"
+#include "egemb_arrow_right.h"
+
+// other menu definitions
+
+#define MENU_FUNCTION_INIT (0)
+#define MENU_FUNCTION_CLEANUP (1)
+#define MENU_FUNCTION_PAINT_ALL (2)
+#define MENU_FUNCTION_PAINT_SELECTION (3)
+#define MENU_FUNCTION_PAINT_TIMEOUT (4)
+
+typedef VOID (*MENU_STYLE_FUNC)(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText);
+
+static CHAR16 ArrowUp[2] = { ARROW_UP, 0 };
+static CHAR16 ArrowDown[2] = { ARROW_DOWN, 0 };
+
+#define TEXT_YMARGIN (2)
+#define TEXT_XMARGIN (8)
+#define TEXT_LINE_HEIGHT (FONT_CELL_HEIGHT + TEXT_YMARGIN * 2)
+#define TITLEICON_SPACING (16)
+
+#define ROW0_TILESIZE (144)
+#define ROW1_TILESIZE (64)
+#define TILE_XSPACING (8)
+#define TILE_YSPACING (16)
+
+// Alignment values for PaintIcon()
+#define ALIGN_RIGHT 1
+#define ALIGN_LEFT 0
+
+static EG_IMAGE *SelectionImages[4] = { NULL, NULL, NULL, NULL };
+static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 };
+static EG_IMAGE *TextBuffer = NULL;
+
+// Used in MainMenuStyle(), but must be persistent....
+UINTN row0PosX = 0, row0PosXRunning = 0, row1PosY = 0, row0Loaders = 0;
+
+//
+// Graphics helper functions
+//
+
+static VOID InitSelection(VOID)
+{
+ UINTN x, y, src_x, src_y;
+ EG_PIXEL *DestPtr, *SrcPtr;
+
+ if (!AllowGraphicsMode)
+ return;
+ if (SelectionImages[0] != NULL)
+ return;
+
+ // load small selection image
+ if (GlobalConfig.SelectionSmallFileName != NULL) {
+ SelectionImages[2] = egLoadImage(SelfDir, GlobalConfig.SelectionSmallFileName, FALSE);
+ }
+ if (SelectionImages[2] == NULL)
+ SelectionImages[2] = egPrepareEmbeddedImage(&egemb_back_selected_small, FALSE);
+ SelectionImages[2] = egEnsureImageSize(SelectionImages[2],
+ ROW1_TILESIZE, ROW1_TILESIZE, &MenuBackgroundPixel);
+ if (SelectionImages[2] == NULL)
+ return;
+
+ // load big selection image
+ if (GlobalConfig.SelectionBigFileName != NULL) {
+ SelectionImages[0] = egLoadImage(SelfDir, GlobalConfig.SelectionBigFileName, FALSE);
+ SelectionImages[0] = egEnsureImageSize(SelectionImages[0],
+ ROW0_TILESIZE, ROW0_TILESIZE, &MenuBackgroundPixel);
+ }
+ if (SelectionImages[0] == NULL) {
+ // calculate big selection image from small one
+
+ SelectionImages[0] = egCreateImage(ROW0_TILESIZE, ROW0_TILESIZE, FALSE);
+ if (SelectionImages[0] == NULL) {
+ egFreeImage(SelectionImages[2]);
+ SelectionImages[2] = NULL;
+ return;
+ }
+
+ DestPtr = SelectionImages[0]->PixelData;
+ SrcPtr = SelectionImages[2]->PixelData;
+ for (y = 0; y < ROW0_TILESIZE; y++) {
+ if (y < (ROW1_TILESIZE >> 1))
+ src_y = y;
+ else if (y < (ROW0_TILESIZE - (ROW1_TILESIZE >> 1)))
+ src_y = (ROW1_TILESIZE >> 1);
+ else
+ src_y = y - (ROW0_TILESIZE - ROW1_TILESIZE);
+
+ for (x = 0; x < ROW0_TILESIZE; x++) {
+ if (x < (ROW1_TILESIZE >> 1))
+ src_x = x;
+ else if (x < (ROW0_TILESIZE - (ROW1_TILESIZE >> 1)))
+ src_x = (ROW1_TILESIZE >> 1);
+ else
+ src_x = x - (ROW0_TILESIZE - ROW1_TILESIZE);
+
+ *DestPtr++ = SrcPtr[src_y * ROW1_TILESIZE + src_x];
+ }
+ }
+ }
+
+ // non-selected background images
+ SelectionImages[1] = egCreateFilledImage(ROW0_TILESIZE, ROW0_TILESIZE, FALSE, &MenuBackgroundPixel);
+ SelectionImages[3] = egCreateFilledImage(ROW1_TILESIZE, ROW1_TILESIZE, FALSE, &MenuBackgroundPixel);
+}
+
+//
+// Scrolling functions
+//
+
+static VOID InitScroll(OUT SCROLL_STATE *State, IN UINTN ItemCount, IN UINTN VisibleSpace)
+{
+ State->LastSelection = State->CurrentSelection = 0;
+ State->MaxIndex = (INTN)ItemCount - 1;
+ State->FirstVisible = 0;
+ if (VisibleSpace == 0)
+ State->MaxVisible = UGAWidth / (ROW0_TILESIZE + TILE_XSPACING) - 1;
+ else
+ State->MaxVisible = (INTN)VisibleSpace;
+ State->PaintAll = TRUE;
+ State->PaintSelection = FALSE;
+
+ State->LastVisible = State->FirstVisible + State->MaxVisible - 1;
+}
+
+static VOID UpdateScroll(IN OUT SCROLL_STATE *State, IN UINTN Movement)
+{
+ State->LastSelection = State->CurrentSelection;
+
+ switch (Movement) {
+ case SCROLL_LINE_UP:
+ if (State->CurrentSelection > 0) {
+ State->CurrentSelection --;
+ }
+ break;
+
+ case SCROLL_LINE_DOWN:
+ if (State->CurrentSelection < State->MaxIndex) {
+ State->CurrentSelection ++;
+ }
+ break;
+
+ // TODO: Better handling of SCROLL_PAGE_UP & SCROLL_PAGE_DOWN
+ case SCROLL_PAGE_UP:
+ case SCROLL_FIRST:
+ if (State->CurrentSelection > 0) {
+ State->PaintAll = TRUE;
+ State->CurrentSelection = 0;
+ }
+ break;
+
+ case SCROLL_PAGE_DOWN:
+ case SCROLL_LAST:
+ if (State->CurrentSelection < State->MaxIndex) {
+ State->PaintAll = TRUE;
+ State->CurrentSelection = State->MaxIndex;
+ }
+ break;
+
+ case SCROLL_NONE:
+ break;
+
+ }
+
+ if (!State->PaintAll && State->CurrentSelection != State->LastSelection)
+ State->PaintSelection = TRUE;
+ State->LastVisible = State->FirstVisible + State->MaxVisible - 1;
+}
+
+//
+// menu helper functions
+//
+
+VOID AddMenuInfoLine(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *InfoLine)
+{
+ AddListElement((VOID ***) &(Screen->InfoLines), &(Screen->InfoLineCount), InfoLine);
+}
+
+VOID AddMenuEntry(IN REFIT_MENU_SCREEN *Screen, IN REFIT_MENU_ENTRY *Entry)
+{
+ AddListElement((VOID ***) &(Screen->Entries), &(Screen->EntryCount), Entry);
+}
+
+VOID FreeMenu(IN REFIT_MENU_SCREEN *Screen)
+{
+ if (Screen->Entries)
+ FreePool(Screen->Entries);
+}
+
+static INTN FindMenuShortcutEntry(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *Shortcut)
+{
+ UINTN i;
+
+ if (Shortcut == NULL)
+ return (-1);
+
+ if (StrLen(Shortcut) == 1) {
+ if (Shortcut[0] >= 'a' && Shortcut[0] <= 'z')
+ Shortcut[0] -= ('a' - 'A');
+ if (Shortcut[0]) {
+ for (i = 0; i < Screen->EntryCount; i++) {
+ if (Screen->Entries[i]->ShortcutDigit == Shortcut[0] ||
+ Screen->Entries[i]->ShortcutLetter == Shortcut[0]) {
+ return i;
+ } // if
+ } // for
+ } // if
+ } else if (StrLen(Shortcut) > 1) {
+ for (i = 0; i < Screen->EntryCount; i++) {
+ if (StriSubCmp(Shortcut, Screen->Entries[i]->Title))
+ return i;
+ } // for
+ }
+ return -1;
+}
+
+//
+// generic menu function
+//
+
+static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC StyleFunc, IN INTN DefaultEntryIndex, OUT REFIT_MENU_ENTRY **ChosenEntry)
+{
+ SCROLL_STATE State;
+ EFI_STATUS Status;
+ EFI_INPUT_KEY key;
+ UINTN index;
+ INTN ShortcutEntry;
+ BOOLEAN HaveTimeout = FALSE;
+ UINTN TimeoutCountdown = 0;
+ CHAR16 *TimeoutMessage;
+ CHAR16 KeyAsString[2];
+ UINTN MenuExit;
+
+ if (Screen->TimeoutSeconds > 0) {
+ HaveTimeout = TRUE;
+ TimeoutCountdown = Screen->TimeoutSeconds * 10;
+ }
+ MenuExit = 0;
+
+ StyleFunc(Screen, &State, MENU_FUNCTION_INIT, NULL);
+ // override the starting selection with the default index, if any
+ if (DefaultEntryIndex >= 0 && DefaultEntryIndex <= State.MaxIndex) {
+ State.CurrentSelection = DefaultEntryIndex;
+ UpdateScroll(&State, SCROLL_NONE);
+ }
+
+ while (!MenuExit) {
+ // update the screen
+ if (State.PaintAll) {
+ StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_ALL, NULL);
+ State.PaintAll = FALSE;
+ } else if (State.PaintSelection) {
+ StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_SELECTION, NULL);
+ State.PaintSelection = FALSE;
+ }
+
+ if (HaveTimeout) {
+ TimeoutMessage = PoolPrint(L"%s in %d seconds", Screen->TimeoutText, (TimeoutCountdown + 5) / 10);
+ StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_TIMEOUT, TimeoutMessage);
+ FreePool(TimeoutMessage);
+ }
+
+ // read key press (and wait for it if applicable)
+ Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key);
+ if (Status == EFI_NOT_READY) {
+ if (HaveTimeout && TimeoutCountdown == 0) {
+ // timeout expired
+ MenuExit = MENU_EXIT_TIMEOUT;
+ break;
+ } else if (HaveTimeout) {
+ refit_call1_wrapper(BS->Stall, 100000);
+ TimeoutCountdown--;
+ } else
+ refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index);
+ continue;
+ }
+ if (HaveTimeout) {
+ // the user pressed a key, cancel the timeout
+ StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_TIMEOUT, L"");
+ HaveTimeout = FALSE;
+ }
+
+ // react to key press
+ switch (key.ScanCode) {
+ case SCAN_UP:
+ case SCAN_LEFT:
+ UpdateScroll(&State, SCROLL_LINE_UP);
+ break;
+ case SCAN_DOWN:
+ case SCAN_RIGHT:
+ UpdateScroll(&State, SCROLL_LINE_DOWN);
+ break;
+ case SCAN_HOME:
+ UpdateScroll(&State, SCROLL_FIRST);
+ break;
+ case SCAN_END:
+ UpdateScroll(&State, SCROLL_LAST);
+ break;
+ case SCAN_PAGE_UP:
+ UpdateScroll(&State, SCROLL_PAGE_UP);
+ break;
+ case SCAN_PAGE_DOWN:
+ UpdateScroll(&State, SCROLL_PAGE_DOWN);
+ break;
+ case SCAN_ESC:
+ MenuExit = MENU_EXIT_ESCAPE;
+ break;
+ case SCAN_INSERT:
+ case SCAN_F2:
+ MenuExit = MENU_EXIT_DETAILS;
+ break;
+ case SCAN_F10:
+ egScreenShot();
+ break;
+ }
+ switch (key.UnicodeChar) {
+ case CHAR_LINEFEED:
+ case CHAR_CARRIAGE_RETURN:
+ case ' ':
+ MenuExit = MENU_EXIT_ENTER;
+ break;
+ case '+':
+ MenuExit = MENU_EXIT_DETAILS;
+ break;
+ default:
+ KeyAsString[0] = key.UnicodeChar;
+ KeyAsString[1] = 0;
+ ShortcutEntry = FindMenuShortcutEntry(Screen, KeyAsString);
+ if (ShortcutEntry >= 0) {
+ State.CurrentSelection = ShortcutEntry;
+ MenuExit = MENU_EXIT_ENTER;
+ }
+ break;
+ }
+ }
+
+ StyleFunc(Screen, &State, MENU_FUNCTION_CLEANUP, NULL);
+
+ if (ChosenEntry)
+ *ChosenEntry = Screen->Entries[State.CurrentSelection];
+ return MenuExit;
+} /* static UINTN RunGenericMenu( */
+
+//
+// text-mode generic style
+//
+
+static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText)
+{
+ INTN i;
+ UINTN MenuWidth, ItemWidth, MenuHeight;
+ static UINTN MenuPosY;
+ static CHAR16 **DisplayStrings;
+ CHAR16 *TimeoutMessage;
+
+ switch (Function) {
+
+ case MENU_FUNCTION_INIT:
+ // vertical layout
+ MenuPosY = 4;
+ if (Screen->InfoLineCount > 0)
+ MenuPosY += Screen->InfoLineCount + 1;
+ MenuHeight = ConHeight - MenuPosY;
+ if (Screen->TimeoutSeconds > 0)
+ MenuHeight -= 2;
+ InitScroll(State, Screen->EntryCount, MenuHeight);
+
+ // determine width of the menu
+ MenuWidth = 20; // minimum
+ for (i = 0; i <= State->MaxIndex; i++) {
+ ItemWidth = StrLen(Screen->Entries[i]->Title);
+ if (MenuWidth < ItemWidth)
+ MenuWidth = ItemWidth;
+ }
+ if (MenuWidth > ConWidth - 6)
+ MenuWidth = ConWidth - 6;
+
+ // prepare strings for display
+ DisplayStrings = AllocatePool(sizeof(CHAR16 *) * Screen->EntryCount);
+ for (i = 0; i <= State->MaxIndex; i++)
+ DisplayStrings[i] = PoolPrint(L" %-.*s ", MenuWidth, Screen->Entries[i]->Title);
+ // TODO: shorten strings that are too long (PoolPrint doesn't do that...)
+ // TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle)
+ // TODO: account for double-width characters
+
+ // initial painting
+ BeginTextScreen(Screen->Title);
+ if (Screen->InfoLineCount > 0) {
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ for (i = 0; i < (INTN)Screen->InfoLineCount; i++) {
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, 4 + i);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, Screen->InfoLines[i]);
+ }
+ }
+
+ break;
+
+ case MENU_FUNCTION_CLEANUP:
+ // release temporary memory
+ for (i = 0; i <= State->MaxIndex; i++)
+ FreePool(DisplayStrings[i]);
+ FreePool(DisplayStrings);
+ break;
+
+ case MENU_FUNCTION_PAINT_ALL:
+ // paint the whole screen (initially and after scrolling)
+ for (i = 0; i <= State->MaxIndex; i++) {
+ if (i >= State->FirstVisible && i <= State->LastVisible) {
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (i - State->FirstVisible));
+ if (i == State->CurrentSelection)
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT);
+ else
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_BASIC);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[i]);
+ }
+ }
+ // scrolling indicators
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_SCROLLARROW);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, MenuPosY);
+ if (State->FirstVisible > 0)
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, ArrowUp);
+ else
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" ");
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, MenuPosY + State->MaxVisible);
+ if (State->LastVisible < State->MaxIndex)
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, ArrowDown);
+ else
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" ");
+ break;
+
+ case MENU_FUNCTION_PAINT_SELECTION:
+ // redraw selection cursor
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (State->LastSelection - State->FirstVisible));
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_BASIC);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->LastSelection]);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (State->CurrentSelection - State->FirstVisible));
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->CurrentSelection]);
+ break;
+
+ case MENU_FUNCTION_PAINT_TIMEOUT:
+ if (ParamText[0] == 0) {
+ // clear message
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 1);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, BlankLine + 1);
+ } else {
+ // paint or update message
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, ConHeight - 1);
+ TimeoutMessage = PoolPrint(L"%s ", ParamText);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, TimeoutMessage);
+ FreePool(TimeoutMessage);
+ }
+ break;
+
+ }
+}
+
+//
+// graphical generic style
+//
+
+
+static VOID DrawMenuText(IN CHAR16 *Text, IN UINTN SelectedWidth, IN UINTN XPos, IN UINTN YPos)
+{
+// Print(L"Entering DrawMenuText(); Text is '%s', SelectedWidth is %d, XPos is %d, YPos is %d\n",
+// Text, SelectedWidth, XPos, YPos);
+ if (TextBuffer == NULL)
+ TextBuffer = egCreateImage(LAYOUT_TEXT_WIDTH, TEXT_LINE_HEIGHT, FALSE);
+
+ egFillImage(TextBuffer, &MenuBackgroundPixel);
+ if (SelectedWidth > 0) {
+ // draw selection bar background
+ egFillImageArea(TextBuffer, 0, 0, SelectedWidth, TextBuffer->Height,
+ &SelectionBackgroundPixel);
+ }
+
+ // render the text
+ egRenderText(Text, TextBuffer, TEXT_XMARGIN, TEXT_YMARGIN);
+ BltImage(TextBuffer, XPos, YPos);
+}
+
+// Displays sub-menus
+static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText)
+{
+ INTN i;
+ UINTN ItemWidth;
+ static UINTN MenuWidth, EntriesPosX, EntriesPosY, TimeoutPosY;
+
+ switch (Function) {
+
+ case MENU_FUNCTION_INIT:
+ InitScroll(State, Screen->EntryCount, 0);
+
+ // determine width of the menu
+ MenuWidth = 20; // minimum
+ for (i = 0; i < (INTN)Screen->InfoLineCount; i++) {
+ ItemWidth = StrLen(Screen->InfoLines[i]);
+ if (MenuWidth < ItemWidth)
+ MenuWidth = ItemWidth;
+ }
+ for (i = 0; i <= State->MaxIndex; i++) {
+ ItemWidth = StrLen(Screen->Entries[i]->Title);
+ if (MenuWidth < ItemWidth)
+ MenuWidth = ItemWidth;
+ }
+ MenuWidth = TEXT_XMARGIN * 2 + MenuWidth * FONT_CELL_WIDTH;
+ if (MenuWidth > LAYOUT_TEXT_WIDTH)
+ MenuWidth = LAYOUT_TEXT_WIDTH;
+
+ if (Screen->TitleImage)
+ EntriesPosX = (UGAWidth + (Screen->TitleImage->Width + TITLEICON_SPACING) - MenuWidth) >> 1;
+ else
+ EntriesPosX = (UGAWidth - MenuWidth) >> 1;
+ EntriesPosY = ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_YOFFSET + TEXT_LINE_HEIGHT * 2;
+ TimeoutPosY = EntriesPosY + (Screen->EntryCount + 1) * TEXT_LINE_HEIGHT;
+
+ // initial painting
+ SwitchToGraphicsAndClear();
+ egMeasureText(Screen->Title, &ItemWidth, NULL);
+ DrawMenuText(Screen->Title, 0, ((UGAWidth - ItemWidth) >> 1) - TEXT_XMARGIN, EntriesPosY - TEXT_LINE_HEIGHT * 2);
+ if (Screen->TitleImage)
+ BltImageAlpha(Screen->TitleImage,
+ EntriesPosX - (Screen->TitleImage->Width + TITLEICON_SPACING), EntriesPosY,
+ &MenuBackgroundPixel);
+ if (Screen->InfoLineCount > 0) {
+ for (i = 0; i < (INTN)Screen->InfoLineCount; i++) {
+ DrawMenuText(Screen->InfoLines[i], 0, EntriesPosX, EntriesPosY);
+ EntriesPosY += TEXT_LINE_HEIGHT;
+ }
+ EntriesPosY += TEXT_LINE_HEIGHT; // also add a blank line
+ }
+
+ break;
+
+ case MENU_FUNCTION_CLEANUP:
+ // nothing to do
+ break;
+
+ case MENU_FUNCTION_PAINT_ALL:
+ for (i = 0; i <= State->MaxIndex; i++) {
+ DrawMenuText(Screen->Entries[i]->Title, (i == State->CurrentSelection) ? MenuWidth : 0,
+ EntriesPosX, EntriesPosY + i * TEXT_LINE_HEIGHT);
+ }
+ break;
+
+ case MENU_FUNCTION_PAINT_SELECTION:
+ // redraw selection cursor
+ DrawMenuText(Screen->Entries[State->LastSelection]->Title, 0,
+ EntriesPosX, EntriesPosY + State->LastSelection * TEXT_LINE_HEIGHT);
+ DrawMenuText(Screen->Entries[State->CurrentSelection]->Title, MenuWidth,
+ EntriesPosX, EntriesPosY + State->CurrentSelection * TEXT_LINE_HEIGHT);
+ break;
+
+ case MENU_FUNCTION_PAINT_TIMEOUT:
+ DrawMenuText(ParamText, 0, EntriesPosX, TimeoutPosY);
+ break;
+
+ }
+}
+
+//
+// graphical main menu style
+//
+
+static VOID DrawMainMenuEntry(REFIT_MENU_ENTRY *Entry, BOOLEAN selected, UINTN XPos, UINTN YPos)
+{
+ UINTN ImageNum;
+
+ ImageNum = ((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1);
+ if (SelectionImages != NULL)
+ BltImageCompositeBadge(SelectionImages[ImageNum],
+ Entry->Image, Entry->BadgeImage, XPos, YPos);
+}
+
+static VOID DrawMainMenuText(IN CHAR16 *Text, IN UINTN XPos, IN UINTN YPos)
+{
+ UINTN TextWidth, TextPosX;
+
+ if (TextBuffer == NULL)
+ TextBuffer = egCreateImage(LAYOUT_TEXT_WIDTH, TEXT_LINE_HEIGHT, FALSE);
+
+ egFillImage(TextBuffer, &MenuBackgroundPixel);
+
+ // render the text
+ egMeasureText(Text, &TextWidth, NULL);
+ if (TextWidth > TextBuffer->Width)
+ TextPosX = 0;
+ else
+ TextPosX = (TextBuffer->Width - TextWidth) / 2;
+ egRenderText(Text, TextBuffer, TextPosX, 0);
+// egRenderText(Text, TextBuffer, (TextBuffer->Width - TextWidth) >> 1, 0);
+ BltImage(TextBuffer, XPos, YPos);
+}
+
+static VOID PaintAll(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *itemPosX,
+ UINTN row0PosY, UINTN row1PosY, UINTN textPosY) {
+ INTN i;
+
+ if (Screen->Entries[State->CurrentSelection]->Row == 0) {
+ if (State->CurrentSelection > State->LastVisible) {
+ State->LastVisible = State->CurrentSelection;
+ State->FirstVisible = 1 + State->CurrentSelection - State->MaxVisible;
+ if (State->FirstVisible < 0) // shouldn't happen, but just in case....
+ State->FirstVisible = 0;
+ } // Scroll forward
+ if (State->CurrentSelection < State->FirstVisible) {
+ State->FirstVisible = State->CurrentSelection;
+ State->LastVisible = State->CurrentSelection + State->MaxVisible - 1;
+ } // Scroll backward
+ }
+ for (i = State->FirstVisible; i <= State->MaxIndex; i++) {
+ if (Screen->Entries[i]->Row == 0) {
+ if (i <= State->LastVisible) {
+ DrawMainMenuEntry(Screen->Entries[i], (i == State->CurrentSelection) ? TRUE : FALSE,
+ itemPosX[i - State->FirstVisible], row0PosY);
+ } // if
+ } else {
+ DrawMainMenuEntry(Screen->Entries[i], (i == State->CurrentSelection) ? TRUE : FALSE,
+ itemPosX[i], row1PosY);
+ }
+ }
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
+ DrawMainMenuText(Screen->Entries[State->CurrentSelection]->Title,
+ (UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY);
+} // static VOID PaintAll()
+
+// Move the selection to State->CurrentSelection, adjusting icon row if necessary...
+static VOID PaintSelection(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *itemPosX,
+ UINTN row0PosY, UINTN row1PosY, UINTN textPosY) {
+ if ((State->CurrentSelection < State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) {
+ DrawMainMenuEntry(Screen->Entries[State->LastSelection], FALSE,
+ itemPosX[State->LastSelection - State->FirstVisible],
+ (Screen->Entries[State->LastSelection]->Row == 0) ? row0PosY : row1PosY);
+ DrawMainMenuEntry(Screen->Entries[State->CurrentSelection], TRUE,
+ itemPosX[State->CurrentSelection - State->FirstVisible],
+ (Screen->Entries[State->CurrentSelection]->Row == 0) ? row0PosY : row1PosY);
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
+ DrawMainMenuText(Screen->Entries[State->CurrentSelection]->Title,
+ (UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY);
+ } else {
+ MainMenuStyle(Screen, State, MENU_FUNCTION_PAINT_ALL, NULL);
+ }
+} // static VOID MoveSelection(VOID)
+
+// Display an icon at the specified location. Uses the image specified by
+// ExternalFilename if it's available, or BuiltInImage if it's not. The
+// Y position is specified as the center value, and so is adjusted by half
+// the icon's height. The X position is set along the icon's left
+// edge if Alignment == ALIGN_LEFT, and along the right edge if
+// Alignment == ALIGN_RIGHT
+static VOID PaintIcon(IN EG_EMBEDDED_IMAGE *BuiltInIcon, IN CHAR16 *ExternalFilename, UINTN PosX, UINTN PosY, UINTN Alignment) {
+ EG_IMAGE *Icon = NULL;
+
+ if (FileExists(SelfDir, ExternalFilename))
+ Icon = egLoadIcon(SelfDir, ExternalFilename, 48);
+ if (Icon == NULL)
+ Icon = egPrepareEmbeddedImage(BuiltInIcon, TRUE);
+ if (Icon != NULL) {
+ if (Alignment == ALIGN_RIGHT)
+ PosX -= Icon->Width;
+ BltImageAlpha(Icon, PosX, PosY - (Icon->Height / 2), &MenuBackgroundPixel);
+ }
+} // static VOID PaintArrow()
+
+// Display main menu in graphics mode
+VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText)
+{
+ INTN i;
+ extern UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders;
+ UINTN row0Count, row1Count, row1PosX, row1PosXRunning;
+ static UINTN *itemPosX;
+ static UINTN row0PosY, textPosY;
+
+ switch (Function) {
+
+ case MENU_FUNCTION_INIT:
+ InitScroll(State, Screen->EntryCount, 0);
+
+ // layout
+ row0Count = 0;
+ row1Count = 0;
+ row0Loaders = 0;
+ for (i = 0; i <= State->MaxIndex; i++) {
+ if (Screen->Entries[i]->Row == 1) {
+ row1Count++;
+ } else {
+ row0Loaders++;
+ if (row0Count < State->MaxVisible)
+ row0Count++;
+ }
+ }
+ row0PosX = (UGAWidth + TILE_XSPACING - (ROW0_TILESIZE + TILE_XSPACING) * row0Count) >> 1;
+ row0PosY = ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_YOFFSET;
+ row1PosX = (UGAWidth + TILE_XSPACING - (ROW1_TILESIZE + TILE_XSPACING) * row1Count) >> 1;
+ row1PosY = row0PosY + ROW0_TILESIZE + TILE_YSPACING;
+ if (row1Count > 0)
+ textPosY = row1PosY + ROW1_TILESIZE + TILE_YSPACING;
+ else
+ textPosY = row1PosY;
+
+ itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount);
+ row0PosXRunning = row0PosX;
+ row1PosXRunning = row1PosX;
+ for (i = 0; i <= State->MaxIndex; i++) {
+ if (Screen->Entries[i]->Row == 0) {
+ itemPosX[i] = row0PosXRunning;
+ row0PosXRunning += ROW0_TILESIZE + TILE_XSPACING;
+ } else {
+ itemPosX[i] = row1PosXRunning;
+ row1PosXRunning += ROW1_TILESIZE + TILE_XSPACING;
+ }
+ }
+ // initial painting
+ InitSelection();
+ SwitchToGraphicsAndClear();
+ break;
+
+ case MENU_FUNCTION_CLEANUP:
+ FreePool(itemPosX);
+ break;
+
+ case MENU_FUNCTION_PAINT_ALL:
+ BltClearScreen(TRUE);
+ PaintAll(Screen, State, itemPosX, row0PosY, row1PosY, textPosY);
+ // For PaintIcon() calls, the starting Y position is moved to the midpoint
+ // of the surrounding row; PaintIcon() adjusts this back up by half the
+ // icon's height to properly center it.
+ if (State->FirstVisible > 0)
+ PaintIcon(&egemb_arrow_left, L"icons\\arrow_left.icns", row0PosX - TILE_XSPACING,
+ row0PosY + (ROW0_TILESIZE / 2), ALIGN_RIGHT);
+ if (State->LastVisible < (row0Loaders - 1))
+ PaintIcon(&egemb_arrow_right, L"icons\\arrow_right.icns",
+ (UGAWidth + (ROW0_TILESIZE + TILE_XSPACING) * State->MaxVisible) / 2 + TILE_XSPACING,
+ row0PosY + (ROW0_TILESIZE / 2), ALIGN_LEFT);
+ break;
+
+ case MENU_FUNCTION_PAINT_SELECTION:
+ PaintSelection(Screen, State, itemPosX, row0PosY, row1PosY, textPosY);
+ break;
+
+ case MENU_FUNCTION_PAINT_TIMEOUT:
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
+ DrawMainMenuText(ParamText, (UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY + TEXT_LINE_HEIGHT);
+ break;
+
+ }
+}
+
+//
+// user-callable dispatcher functions
+//
+
+UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry)
+{
+ MENU_STYLE_FUNC Style = TextMenuStyle;
+
+ if (AllowGraphicsMode)
+ Style = GraphicsMenuStyle;
+
+ return RunGenericMenu(Screen, Style, -1, ChosenEntry);
+}
+
+UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry)
+{
+ MENU_STYLE_FUNC Style = TextMenuStyle;
+ MENU_STYLE_FUNC MainStyle = TextMenuStyle;
+ REFIT_MENU_ENTRY *TempChosenEntry;
+ UINTN MenuExit = 0;
+ UINTN DefaultEntryIndex = -1;
+
+ if (DefaultSelection != NULL) {
+ // Find a menu entry whose shortcut is the first character of DefaultSelection, or
+ // whose
+ DefaultEntryIndex = FindMenuShortcutEntry(Screen, DefaultSelection);
+ // If that didn't work, should we scan more characters? For now, no.
+ }
+
+ if (AllowGraphicsMode) {
+ Style = GraphicsMenuStyle;
+ MainStyle = MainMenuStyle;
+ }
+
+ while (!MenuExit) {
+ MenuExit = RunGenericMenu(Screen, MainStyle, DefaultEntryIndex, &TempChosenEntry);
+ Screen->TimeoutSeconds = 0;
+
+ if (MenuExit == MENU_EXIT_DETAILS && TempChosenEntry->SubScreen != NULL) {
+ MenuExit = RunGenericMenu(TempChosenEntry->SubScreen, Style, -1, &TempChosenEntry);
+ if (MenuExit == MENU_EXIT_ESCAPE || TempChosenEntry->Tag == TAG_RETURN)
+ MenuExit = 0;
+ }
+ }
+
+ if (ChosenEntry)
+ *ChosenEntry = TempChosenEntry;
+ return MenuExit;
+} /* UINTN RunMainMenu() */
--- /dev/null
+/*
+ * refind/menu.h
+ * menu functions header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
+
+#ifndef __REFIND_MENU_H_
+#define __REFIND_MENU_H_
+
+#include "efi.h"
+#include "efilib.h"
+
+#include "libeg.h"
+
+//
+// menu module
+//
+
+#define MENU_EXIT_ENTER (1)
+#define MENU_EXIT_ESCAPE (2)
+#define MENU_EXIT_DETAILS (3)
+#define MENU_EXIT_TIMEOUT (4)
+
+#define TAG_RETURN (99)
+
+// scrolling definitions
+
+typedef struct {
+ INTN CurrentSelection, LastSelection, MaxIndex;
+ INTN FirstVisible, LastVisible, MaxVisible;
+ BOOLEAN PaintAll, PaintSelection;
+} SCROLL_STATE;
+
+#define SCROLL_LINE_UP (0)
+#define SCROLL_LINE_DOWN (1)
+#define SCROLL_PAGE_UP (2)
+#define SCROLL_PAGE_DOWN (3)
+#define SCROLL_FIRST (4)
+#define SCROLL_LAST (5)
+#define SCROLL_NONE (6)
+
+struct _refit_menu_screen;
+
+VOID AddMenuInfoLine(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *InfoLine);
+VOID AddMenuEntry(IN REFIT_MENU_SCREEN *Screen, IN REFIT_MENU_ENTRY *Entry);
+VOID FreeMenu(IN REFIT_MENU_SCREEN *Screen);
+VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText);
+UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry);
+UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry);
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * refit/screen.c
+ * Screen handling functions
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "global.h"
+#include "screen.h"
+#include "config.h"
+#include "refit_call_wrapper.h"
+
+#include "egemb_refind_banner.h"
+
+// Console defines and variables
+
+UINTN ConWidth;
+UINTN ConHeight;
+CHAR16 *BlankLine;
+
+static VOID SwitchToText(IN BOOLEAN CursorEnabled);
+static VOID SwitchToGraphics(VOID);
+static VOID DrawScreenHeader(IN CHAR16 *Title);
+
+// UGA defines and variables
+
+UINTN UGAWidth;
+UINTN UGAHeight;
+BOOLEAN AllowGraphicsMode;
+
+EG_PIXEL StdBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 };
+EG_PIXEL MenuBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 };
+
+static BOOLEAN GraphicsScreenDirty;
+
+// general defines and variables
+
+static BOOLEAN haveError = FALSE;
+
+//
+// Screen initialization and switching
+//
+
+VOID InitScreen(VOID)
+{
+ UINTN i;
+
+ // initialize libeg
+ egInitScreen();
+
+ if (egHasGraphicsMode()) {
+ egGetScreenSize(&UGAWidth, &UGAHeight);
+ AllowGraphicsMode = TRUE;
+ } else {
+ AllowGraphicsMode = FALSE;
+ egSetGraphicsModeEnabled(FALSE); // just to be sure we are in text mode
+ }
+ GraphicsScreenDirty = TRUE;
+
+ // disable cursor
+ refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, FALSE);
+
+ // get size of text console
+ if (refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, ST->ConOut->Mode->Mode, &ConWidth, &ConHeight) != EFI_SUCCESS) {
+ // use default values on error
+ ConWidth = 80;
+ ConHeight = 25;
+ }
+
+ // make a buffer for a whole text line
+ BlankLine = AllocatePool((ConWidth + 1) * sizeof(CHAR16));
+ for (i = 0; i < ConWidth; i++)
+ BlankLine[i] = ' ';
+ BlankLine[i] = 0;
+
+ // show the banner (even when in graphics mode)
+ DrawScreenHeader(L"Initializing...");
+}
+
+VOID SetupScreen(VOID)
+{
+ if (GlobalConfig.TextOnly) {
+ // switch to text mode if requested
+ AllowGraphicsMode = FALSE;
+ SwitchToText(FALSE);
+
+ } else if (AllowGraphicsMode) {
+ // clear screen and show banner
+ // (now we know we'll stay in graphics mode)
+ SwitchToGraphics();
+ BltClearScreen(TRUE);
+ }
+}
+
+static VOID SwitchToText(IN BOOLEAN CursorEnabled)
+{
+ egSetGraphicsModeEnabled(FALSE);
+ refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, CursorEnabled);
+}
+
+static VOID SwitchToGraphics(VOID)
+{
+ if (AllowGraphicsMode && !egIsGraphicsModeEnabled()) {
+ egSetGraphicsModeEnabled(TRUE);
+ GraphicsScreenDirty = TRUE;
+ }
+}
+
+//
+// Screen control for running tools
+//
+
+VOID BeginTextScreen(IN CHAR16 *Title)
+{
+ DrawScreenHeader(Title);
+ SwitchToText(FALSE);
+
+ // reset error flag
+ haveError = FALSE;
+}
+
+VOID FinishTextScreen(IN BOOLEAN WaitAlways)
+{
+ if (haveError || WaitAlways) {
+ SwitchToText(FALSE);
+ PauseForKey();
+ }
+
+ // reset error flag
+ haveError = FALSE;
+}
+
+VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title)
+{
+ if (!AllowGraphicsMode)
+ UseGraphicsMode = FALSE;
+
+ if (UseGraphicsMode) {
+ SwitchToGraphics();
+ BltClearScreen(FALSE);
+ }
+
+ // show the header
+ DrawScreenHeader(Title);
+
+ if (!UseGraphicsMode)
+ SwitchToText(TRUE);
+
+ // reset error flag
+ haveError = FALSE;
+}
+
+VOID FinishExternalScreen(VOID)
+{
+ // make sure we clean up later
+ GraphicsScreenDirty = TRUE;
+
+ if (haveError) {
+ SwitchToText(FALSE);
+ PauseForKey();
+ }
+
+ // reset error flag
+ haveError = FALSE;
+}
+
+VOID TerminateScreen(VOID)
+{
+ // clear text screen
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut);
+
+ // enable cursor
+ refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, TRUE);
+}
+
+static VOID DrawScreenHeader(IN CHAR16 *Title)
+{
+ UINTN y;
+
+ // clear to black background
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut);
+
+ // paint header background
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BANNER);
+ for (y = 0; y < 3; y++) {
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, y);
+ Print(BlankLine);
+ }
+
+ // print header text
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, 1);
+ Print(L"rEFInd - %s", Title);
+
+ // reposition cursor
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, 4);
+}
+
+//
+// Keyboard input
+//
+
+static BOOLEAN ReadAllKeyStrokes(VOID)
+{
+ BOOLEAN GotKeyStrokes;
+ EFI_STATUS Status;
+ EFI_INPUT_KEY key;
+
+ GotKeyStrokes = FALSE;
+ for (;;) {
+ Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key);
+ if (Status == EFI_SUCCESS) {
+ GotKeyStrokes = TRUE;
+ continue;
+ }
+ break;
+ }
+ return GotKeyStrokes;
+}
+
+VOID PauseForKey(VOID)
+{
+ UINTN index;
+
+ Print(L"\n* Hit any key to continue *");
+
+ if (ReadAllKeyStrokes()) { // remove buffered key strokes
+ refit_call1_wrapper(BS->Stall, 5000000); // 5 seconds delay
+ ReadAllKeyStrokes(); // empty the buffer again
+ }
+
+ refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index);
+ ReadAllKeyStrokes(); // empty the buffer to protect the menu
+
+ Print(L"\n");
+}
+
+#if REFIT_DEBUG > 0
+VOID DebugPause(VOID)
+{
+ // show console and wait for key
+ SwitchToText(FALSE);
+ PauseForKey();
+
+ // reset error flag
+ haveError = FALSE;
+}
+#endif
+
+VOID EndlessIdleLoop(VOID)
+{
+ UINTN index;
+
+ for (;;) {
+ ReadAllKeyStrokes();
+ refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index);
+ }
+}
+
+//
+// Error handling
+//
+
+BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where)
+{
+ CHAR16 ErrorName[64];
+
+ if (!EFI_ERROR(Status))
+ return FALSE;
+
+ StatusToString(ErrorName, Status);
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
+ Print(L"Fatal Error: %s %s\n", ErrorName, where);
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ haveError = TRUE;
+
+ //BS->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData);
+
+ return TRUE;
+}
+
+BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where)
+{
+ CHAR16 ErrorName[64];
+
+ if (!EFI_ERROR(Status))
+ return FALSE;
+
+ StatusToString(ErrorName, Status);
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
+ Print(L"Error: %s %s\n", ErrorName, where);
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ haveError = TRUE;
+
+ return TRUE;
+}
+
+//
+// Graphics functions
+//
+
+VOID SwitchToGraphicsAndClear(VOID)
+{
+ SwitchToGraphics();
+ if (GraphicsScreenDirty)
+ BltClearScreen(TRUE);
+}
+
+VOID BltClearScreen(IN BOOLEAN ShowBanner)
+{
+ static EG_IMAGE *Banner = NULL;
+
+ if (ShowBanner && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_BANNER)) {
+ // load banner on first call
+ if (Banner == NULL) {
+ if (GlobalConfig.BannerFileName == NULL)
+ Banner = egPrepareEmbeddedImage(&egemb_refind_banner, FALSE);
+ else
+ Banner = egLoadImage(SelfDir, GlobalConfig.BannerFileName, FALSE);
+ if (Banner != NULL)
+ MenuBackgroundPixel = Banner->PixelData[0];
+ }
+
+ // clear and draw banner
+ egClearScreen(&MenuBackgroundPixel);
+ if (Banner != NULL)
+ BltImage(Banner, (UGAWidth - Banner->Width) >> 1,
+ ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_HEIGHT - Banner->Height);
+
+ } else {
+ // clear to standard background color
+ egClearScreen(&StdBackgroundPixel);
+ }
+
+ GraphicsScreenDirty = FALSE;
+}
+
+VOID BltImage(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos)
+{
+ egDrawImage(Image, XPos, YPos);
+ GraphicsScreenDirty = TRUE;
+}
+
+VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL *BackgroundPixel)
+{
+ EG_IMAGE *CompImage;
+
+ // compose on background
+ CompImage = egCreateFilledImage(Image->Width, Image->Height, FALSE, BackgroundPixel);
+ egComposeImage(CompImage, Image, 0, 0);
+
+ // blit to screen and clean up
+ egDrawImage(CompImage, XPos, YPos);
+ egFreeImage(CompImage);
+ GraphicsScreenDirty = TRUE;
+}
+
+// VOID BltImageComposite(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN UINTN XPos, IN UINTN YPos)
+// {
+// UINTN TotalWidth, TotalHeight, CompWidth, CompHeight, OffsetX, OffsetY;
+// EG_IMAGE *CompImage;
+//
+// // initialize buffer with base image
+// CompImage = egCopyImage(BaseImage);
+// TotalWidth = BaseImage->Width;
+// TotalHeight = BaseImage->Height;
+//
+// // place the top image
+// CompWidth = TopImage->Width;
+// if (CompWidth > TotalWidth)
+// CompWidth = TotalWidth;
+// OffsetX = (TotalWidth - CompWidth) >> 1;
+// CompHeight = TopImage->Height;
+// if (CompHeight > TotalHeight)
+// CompHeight = TotalHeight;
+// OffsetY = (TotalHeight - CompHeight) >> 1;
+// egComposeImage(CompImage, TopImage, OffsetX, OffsetY);
+//
+// // blit to screen and clean up
+// egDrawImage(CompImage, XPos, YPos);
+// egFreeImage(CompImage);
+// GraphicsScreenDirty = TRUE;
+// }
+
+VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG_IMAGE *BadgeImage, IN UINTN XPos, IN UINTN YPos)
+{
+ UINTN TotalWidth, TotalHeight, CompWidth = 0, CompHeight = 0, OffsetX = 0, OffsetY = 0;
+ EG_IMAGE *CompImage = NULL;
+
+ // initialize buffer with base image
+ if (BaseImage != NULL) {
+ CompImage = egCopyImage(BaseImage);
+ TotalWidth = BaseImage->Width;
+ TotalHeight = BaseImage->Height;
+ }
+
+ // place the top image
+ if ((TopImage != NULL) && (CompImage != NULL)) {
+ CompWidth = TopImage->Width;
+ if (CompWidth > TotalWidth)
+ CompWidth = TotalWidth;
+ OffsetX = (TotalWidth - CompWidth) >> 1;
+ CompHeight = TopImage->Height;
+ if (CompHeight > TotalHeight)
+ CompHeight = TotalHeight;
+ OffsetY = (TotalHeight - CompHeight) >> 1;
+ egComposeImage(CompImage, TopImage, OffsetX, OffsetY);
+ }
+
+ // place the badge image
+ if (BadgeImage != NULL && CompImage != NULL && (BadgeImage->Width + 8) < CompWidth && (BadgeImage->Height + 8) < CompHeight) {
+ OffsetX += CompWidth - 8 - BadgeImage->Width;
+ OffsetY += CompHeight - 8 - BadgeImage->Height;
+ egComposeImage(CompImage, BadgeImage, OffsetX, OffsetY);
+ }
+
+ // blit to screen and clean up
+ egDrawImage(CompImage, XPos, YPos);
+ egFreeImage(CompImage);
+ GraphicsScreenDirty = TRUE;
+}
--- /dev/null
+/*
+ * refit/screen.h
+ * Screen management header file
+ *
+ * Copyright (c) 2006-2009 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Christoph Pfisterer nor the names of the
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCREEN_H_
+#define __SCREEN_H_
+
+#include "efi.h"
+#include "efilib.h"
+
+#include "libeg.h"
+
+//
+// screen module
+//
+
+#define ATTR_BASIC (EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK)
+#define ATTR_ERROR (EFI_YELLOW | EFI_BACKGROUND_BLACK)
+#define ATTR_BANNER (EFI_WHITE | EFI_BACKGROUND_BLUE)
+#define ATTR_CHOICE_BASIC ATTR_BASIC
+#define ATTR_CHOICE_CURRENT (EFI_WHITE | EFI_BACKGROUND_GREEN)
+#define ATTR_SCROLLARROW (EFI_LIGHTGREEN | EFI_BACKGROUND_BLACK)
+
+//#define LAYOUT_TEXT_WIDTH (512)
+#define LAYOUT_TEXT_WIDTH (425)
+#define LAYOUT_TOTAL_HEIGHT (368)
+#define LAYOUT_BANNER_HEIGHT (32)
+#define LAYOUT_BANNER_YOFFSET (LAYOUT_BANNER_HEIGHT + 32)
+
+#define FONT_CELL_WIDTH (7)
+#define FONT_CELL_HEIGHT (12)
+
+extern UINTN ConWidth;
+extern UINTN ConHeight;
+extern CHAR16 *BlankLine;
+
+extern UINTN UGAWidth;
+extern UINTN UGAHeight;
+extern BOOLEAN AllowGraphicsMode;
+
+extern EG_PIXEL StdBackgroundPixel;
+extern EG_PIXEL MenuBackgroundPixel;
+
+VOID InitScreen(VOID);
+VOID SetupScreen(VOID);
+VOID BeginTextScreen(IN CHAR16 *Title);
+VOID FinishTextScreen(IN BOOLEAN WaitAlways);
+VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title);
+VOID FinishExternalScreen(VOID);
+VOID TerminateScreen(VOID);
+#if REFIT_DEBUG > 0
+VOID DebugPause(VOID);
+#else
+#define DebugPause()
+#endif
+VOID EndlessIdleLoop(VOID);
+VOID PauseForKey(VOID);
+
+BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where);
+BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where);
+
+VOID SwitchToGraphicsAndClear(VOID);
+VOID BltClearScreen(IN BOOLEAN ShowBanner);
+VOID BltImage(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos);
+VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL *BackgroundPixel);
+//VOID BltImageComposite(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN UINTN XPos, IN UINTN YPos);
+VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG_IMAGE *BadgeImage, IN UINTN XPos, IN UINTN YPos);
+
+#endif