From 8b473c647050fb7fc00b234b7d28e5fb8e291a1a Mon Sep 17 00:00:00 2001 From: vasilito Date: Tue, 30 Jun 2026 14:30:39 +0300 Subject: [PATCH] Add GRUB2 hiperiso module source (hiperiso_cmd.c, 7335 lines) Forked from Ventoy ventoy_cmd.c with full rename and net_dump support. --- src/grub2/Makefile.am | 507 ++ src/grub2/Makefile.core.def | 2586 ++++++ src/grub2/buildgrub.sh | 87 + src/grub2/grub/arm64-efi/command.lst | Bin 0 -> 1136 bytes src/grub2/grub/arm64-efi/crypto.lst | Bin 0 -> 424 bytes src/grub2/grub/arm64-efi/fdt.lst | Bin 0 -> 32 bytes src/grub2/grub/arm64-efi/fs.lst | Bin 0 -> 212 bytes src/grub2/grub/arm64-efi/moddep.lst | Bin 0 -> 1648 bytes src/grub2/grub/arm64-efi/partmap.lst | Bin 0 -> 124 bytes src/grub2/grub/arm64-efi/parttool.lst | Bin 0 -> 76 bytes src/grub2/grub/arm64-efi/terminal.lst | Bin 0 -> 104 bytes src/grub2/grub/arm64-efi/video.lst | Bin 0 -> 64 bytes src/grub2/grub/checksum.cfg | 96 + src/grub2/grub/debug.cfg | 294 + src/grub2/grub/distro/fwts.cfg | 15 + src/grub2/grub/fonts/ascii.pf2 | Bin 0 -> 1840 bytes src/grub2/grub/fonts/unicode.pf2 | Bin 0 -> 743668 bytes src/grub2/grub/grub.cfg | 473 ++ src/grub2/grub/help/ar_AR.txt | 18 + src/grub2/grub/help/bn_BN.txt | 19 + src/grub2/grub/help/cs_CZ.txt | 19 + src/grub2/grub/help/de_DE.txt | 19 + src/grub2/grub/help/el_GR.txt | 19 + src/grub2/grub/help/en_US.txt | 19 + src/grub2/grub/help/es_ES.txt | 19 + src/grub2/grub/help/fa_IR.txt | 19 + src/grub2/grub/help/fr_FR.txt | 19 + src/grub2/grub/help/hi_HI.txt | 19 + src/grub2/grub/help/hr_HR.txt | 19 + src/grub2/grub/help/hu_HU.txt | 19 + src/grub2/grub/help/id_ID.txt | 19 + src/grub2/grub/help/it_IT.txt | 19 + src/grub2/grub/help/ja_JP.txt | 19 + src/grub2/grub/help/ka_GE.txt | 19 + src/grub2/grub/help/ko_KR.txt | 19 + src/grub2/grub/help/lg_UG.txt | 19 + src/grub2/grub/help/pl_PL.txt | 19 + src/grub2/grub/help/pt_BR.txt | 19 + src/grub2/grub/help/pt_PT.txt | 18 + src/grub2/grub/help/ru_RU.txt | 19 + src/grub2/grub/help/sl_SI.txt | 19 + src/grub2/grub/help/sr_RS.txt | 19 + src/grub2/grub/help/ta_IN.txt | 19 + src/grub2/grub/help/tr_TR.txt | 19 + src/grub2/grub/help/uk_UA.txt | 19 + src/grub2/grub/help/vi_VN.txt | 19 + src/grub2/grub/help/zh_CN.txt | 18 + src/grub2/grub/help/zh_TW.txt | 18 + src/grub2/grub/hwinfo.cfg | 64 + src/grub2/grub/i386-efi/command.lst | 206 + src/grub2/grub/i386-efi/crypto.lst | 45 + src/grub2/grub/i386-efi/fdt.lst | 0 src/grub2/grub/i386-efi/fs.lst | 37 + src/grub2/grub/i386-efi/moddep.lst | 269 + src/grub2/grub/i386-efi/partmap.lst | 11 + src/grub2/grub/i386-efi/parttool.lst | 1 + src/grub2/grub/i386-efi/terminal.lst | 10 + src/grub2/grub/i386-efi/video.lst | 4 + src/grub2/grub/i386-pc/command.lst | 212 + src/grub2/grub/i386-pc/crypto.lst | 45 + src/grub2/grub/i386-pc/fdt.lst | 0 src/grub2/grub/i386-pc/fs.lst | 37 + src/grub2/grub/i386-pc/moddep.lst | 274 + src/grub2/grub/i386-pc/partmap.lst | 11 + src/grub2/grub/i386-pc/parttool.lst | 1 + src/grub2/grub/i386-pc/terminal.lst | 11 + src/grub2/grub/i386-pc/video.lst | 4 + src/grub2/grub/keyboard.cfg | 62 + src/grub2/grub/localboot.cfg | 222 + src/grub2/grub/menu/ar_AR.json | 98 + src/grub2/grub/menu/bn_BN.json | 99 + src/grub2/grub/menu/cs_CZ.json | 99 + src/grub2/grub/menu/de_DE.json | 99 + src/grub2/grub/menu/el_GR.json | 99 + src/grub2/grub/menu/en_US.json | 98 + src/grub2/grub/menu/es_ES.json | 99 + src/grub2/grub/menu/fa_IR.json | 99 + src/grub2/grub/menu/fr_FR.json | 99 + src/grub2/grub/menu/hi_HI.json | 99 + src/grub2/grub/menu/hr_HR.json | 99 + src/grub2/grub/menu/hu_HU.json | 99 + src/grub2/grub/menu/id_ID.json | 99 + src/grub2/grub/menu/it_IT.json | 99 + src/grub2/grub/menu/ja_JP.json | 99 + src/grub2/grub/menu/ka_GE.json | 99 + src/grub2/grub/menu/ko_KR.json | 99 + src/grub2/grub/menu/lg_UG.json | 99 + src/grub2/grub/menu/pl_PL.json | 99 + src/grub2/grub/menu/pt_BR.json | 99 + src/grub2/grub/menu/pt_PT.json | 99 + src/grub2/grub/menu/ru_RU.json | 99 + src/grub2/grub/menu/sl_si.json | 99 + src/grub2/grub/menu/sr_RS.json | 99 + src/grub2/grub/menu/ta_IN.json | 99 + src/grub2/grub/menu/tr_TR.json | 99 + src/grub2/grub/menu/uk_UA.json | 99 + src/grub2/grub/menu/vi_VN.json | 99 + src/grub2/grub/menu/zh_CN.json | 98 + src/grub2/grub/menu/zh_TW.json | 98 + src/grub2/grub/menulang.cfg | 149 + src/grub2/grub/mips64el-efi/command.lst | Bin 0 -> 1104 bytes src/grub2/grub/mips64el-efi/crypto.lst | Bin 0 -> 424 bytes src/grub2/grub/mips64el-efi/fdt.lst | Bin 0 -> 32 bytes src/grub2/grub/mips64el-efi/fs.lst | Bin 0 -> 212 bytes src/grub2/grub/mips64el-efi/moddep.lst | Bin 0 -> 1640 bytes src/grub2/grub/mips64el-efi/partmap.lst | Bin 0 -> 124 bytes src/grub2/grub/mips64el-efi/parttool.lst | Bin 0 -> 76 bytes src/grub2/grub/mips64el-efi/terminal.lst | Bin 0 -> 104 bytes src/grub2/grub/mips64el-efi/video.lst | Bin 0 -> 64 bytes src/grub2/grub/power.cfg | 25 + src/grub2/grub/themes/hiperiso/background.png | Bin 0 -> 262140 bytes src/grub2/grub/themes/hiperiso/menu_c.png | Bin 0 -> 152 bytes src/grub2/grub/themes/hiperiso/menu_e.png | Bin 0 -> 154 bytes src/grub2/grub/themes/hiperiso/menu_n.png | Bin 0 -> 157 bytes src/grub2/grub/themes/hiperiso/menu_ne.png | Bin 0 -> 178 bytes src/grub2/grub/themes/hiperiso/menu_nw.png | Bin 0 -> 178 bytes src/grub2/grub/themes/hiperiso/menu_s.png | Bin 0 -> 157 bytes src/grub2/grub/themes/hiperiso/menu_se.png | Bin 0 -> 181 bytes src/grub2/grub/themes/hiperiso/menu_sw.png | Bin 0 -> 181 bytes src/grub2/grub/themes/hiperiso/menu_w.png | Bin 0 -> 154 bytes src/grub2/grub/themes/hiperiso/select_c.png | Bin 0 -> 318 bytes src/grub2/grub/themes/hiperiso/slider_c.png | Bin 0 -> 99 bytes src/grub2/grub/themes/hiperiso/slider_n.png | Bin 0 -> 190 bytes src/grub2/grub/themes/hiperiso/slider_s.png | Bin 0 -> 184 bytes .../grub/themes/hiperiso/terminal_box_c.png | Bin 0 -> 976 bytes .../grub/themes/hiperiso/terminal_box_e.png | Bin 0 -> 952 bytes .../grub/themes/hiperiso/terminal_box_n.png | Bin 0 -> 963 bytes .../grub/themes/hiperiso/terminal_box_ne.png | Bin 0 -> 1115 bytes .../grub/themes/hiperiso/terminal_box_nw.png | Bin 0 -> 1094 bytes .../grub/themes/hiperiso/terminal_box_s.png | Bin 0 -> 963 bytes .../grub/themes/hiperiso/terminal_box_se.png | Bin 0 -> 1102 bytes .../grub/themes/hiperiso/terminal_box_sw.png | Bin 0 -> 1107 bytes .../grub/themes/hiperiso/terminal_box_w.png | Bin 0 -> 952 bytes src/grub2/grub/themes/hiperiso/theme.txt | 97 + src/grub2/grub/x86_64-efi/command.lst | 203 + src/grub2/grub/x86_64-efi/crypto.lst | 45 + src/grub2/grub/x86_64-efi/fdt.lst | 0 src/grub2/grub/x86_64-efi/fs.lst | 37 + src/grub2/grub/x86_64-efi/moddep.lst | 270 + src/grub2/grub/x86_64-efi/partmap.lst | 11 + src/grub2/grub/x86_64-efi/parttool.lst | 1 + src/grub2/grub/x86_64-efi/terminal.lst | 10 + src/grub2/grub/x86_64-efi/video.lst | 4 + src/grub2/hiperiso.c | 655 ++ src/grub2/hiperiso.h | 331 + src/grub2/hiperiso_browser.c | 652 ++ src/grub2/hiperiso_cmd.c | 7335 +++++++++++++++++ src/grub2/hiperiso_def.h | 1345 +++ src/grub2/hiperiso_json.c | 758 ++ src/grub2/hiperiso_linux.c | 2120 +++++ src/grub2/hiperiso_plugin.c | 3657 ++++++++ src/grub2/hiperiso_unix.c | 1245 +++ src/grub2/hiperiso_vhd.c | 754 ++ src/grub2/hiperiso_windows.c | 2781 +++++++ src/grub2/huffman.c | 207 + src/grub2/huffman.h | 108 + src/grub2/lzx.c | 668 ++ src/grub2/lzx.h | 179 + src/grub2/miniz.c | 2587 ++++++ src/grub2/miniz.h | 2 + src/grub2/wimboot.h | 65 + src/grub2/xpress.c | 157 + src/grub2/xpress.h | 87 + 163 files changed, 35661 insertions(+) create mode 100644 src/grub2/Makefile.am create mode 100644 src/grub2/Makefile.core.def create mode 100644 src/grub2/buildgrub.sh create mode 100644 src/grub2/grub/arm64-efi/command.lst create mode 100644 src/grub2/grub/arm64-efi/crypto.lst create mode 100644 src/grub2/grub/arm64-efi/fdt.lst create mode 100644 src/grub2/grub/arm64-efi/fs.lst create mode 100644 src/grub2/grub/arm64-efi/moddep.lst create mode 100644 src/grub2/grub/arm64-efi/partmap.lst create mode 100644 src/grub2/grub/arm64-efi/parttool.lst create mode 100644 src/grub2/grub/arm64-efi/terminal.lst create mode 100644 src/grub2/grub/arm64-efi/video.lst create mode 100644 src/grub2/grub/checksum.cfg create mode 100644 src/grub2/grub/debug.cfg create mode 100644 src/grub2/grub/distro/fwts.cfg create mode 100644 src/grub2/grub/fonts/ascii.pf2 create mode 100644 src/grub2/grub/fonts/unicode.pf2 create mode 100644 src/grub2/grub/grub.cfg create mode 100644 src/grub2/grub/help/ar_AR.txt create mode 100644 src/grub2/grub/help/bn_BN.txt create mode 100644 src/grub2/grub/help/cs_CZ.txt create mode 100644 src/grub2/grub/help/de_DE.txt create mode 100644 src/grub2/grub/help/el_GR.txt create mode 100644 src/grub2/grub/help/en_US.txt create mode 100644 src/grub2/grub/help/es_ES.txt create mode 100644 src/grub2/grub/help/fa_IR.txt create mode 100644 src/grub2/grub/help/fr_FR.txt create mode 100644 src/grub2/grub/help/hi_HI.txt create mode 100644 src/grub2/grub/help/hr_HR.txt create mode 100644 src/grub2/grub/help/hu_HU.txt create mode 100644 src/grub2/grub/help/id_ID.txt create mode 100644 src/grub2/grub/help/it_IT.txt create mode 100644 src/grub2/grub/help/ja_JP.txt create mode 100644 src/grub2/grub/help/ka_GE.txt create mode 100644 src/grub2/grub/help/ko_KR.txt create mode 100644 src/grub2/grub/help/lg_UG.txt create mode 100644 src/grub2/grub/help/pl_PL.txt create mode 100644 src/grub2/grub/help/pt_BR.txt create mode 100644 src/grub2/grub/help/pt_PT.txt create mode 100644 src/grub2/grub/help/ru_RU.txt create mode 100644 src/grub2/grub/help/sl_SI.txt create mode 100644 src/grub2/grub/help/sr_RS.txt create mode 100644 src/grub2/grub/help/ta_IN.txt create mode 100644 src/grub2/grub/help/tr_TR.txt create mode 100644 src/grub2/grub/help/uk_UA.txt create mode 100644 src/grub2/grub/help/vi_VN.txt create mode 100644 src/grub2/grub/help/zh_CN.txt create mode 100644 src/grub2/grub/help/zh_TW.txt create mode 100644 src/grub2/grub/hwinfo.cfg create mode 100644 src/grub2/grub/i386-efi/command.lst create mode 100644 src/grub2/grub/i386-efi/crypto.lst create mode 100644 src/grub2/grub/i386-efi/fdt.lst create mode 100644 src/grub2/grub/i386-efi/fs.lst create mode 100644 src/grub2/grub/i386-efi/moddep.lst create mode 100644 src/grub2/grub/i386-efi/partmap.lst create mode 100644 src/grub2/grub/i386-efi/parttool.lst create mode 100644 src/grub2/grub/i386-efi/terminal.lst create mode 100644 src/grub2/grub/i386-efi/video.lst create mode 100644 src/grub2/grub/i386-pc/command.lst create mode 100644 src/grub2/grub/i386-pc/crypto.lst create mode 100644 src/grub2/grub/i386-pc/fdt.lst create mode 100644 src/grub2/grub/i386-pc/fs.lst create mode 100644 src/grub2/grub/i386-pc/moddep.lst create mode 100644 src/grub2/grub/i386-pc/partmap.lst create mode 100644 src/grub2/grub/i386-pc/parttool.lst create mode 100644 src/grub2/grub/i386-pc/terminal.lst create mode 100644 src/grub2/grub/i386-pc/video.lst create mode 100644 src/grub2/grub/keyboard.cfg create mode 100644 src/grub2/grub/localboot.cfg create mode 100644 src/grub2/grub/menu/ar_AR.json create mode 100644 src/grub2/grub/menu/bn_BN.json create mode 100644 src/grub2/grub/menu/cs_CZ.json create mode 100644 src/grub2/grub/menu/de_DE.json create mode 100644 src/grub2/grub/menu/el_GR.json create mode 100644 src/grub2/grub/menu/en_US.json create mode 100644 src/grub2/grub/menu/es_ES.json create mode 100644 src/grub2/grub/menu/fa_IR.json create mode 100644 src/grub2/grub/menu/fr_FR.json create mode 100644 src/grub2/grub/menu/hi_HI.json create mode 100644 src/grub2/grub/menu/hr_HR.json create mode 100644 src/grub2/grub/menu/hu_HU.json create mode 100644 src/grub2/grub/menu/id_ID.json create mode 100644 src/grub2/grub/menu/it_IT.json create mode 100644 src/grub2/grub/menu/ja_JP.json create mode 100644 src/grub2/grub/menu/ka_GE.json create mode 100644 src/grub2/grub/menu/ko_KR.json create mode 100644 src/grub2/grub/menu/lg_UG.json create mode 100644 src/grub2/grub/menu/pl_PL.json create mode 100644 src/grub2/grub/menu/pt_BR.json create mode 100644 src/grub2/grub/menu/pt_PT.json create mode 100644 src/grub2/grub/menu/ru_RU.json create mode 100644 src/grub2/grub/menu/sl_si.json create mode 100644 src/grub2/grub/menu/sr_RS.json create mode 100644 src/grub2/grub/menu/ta_IN.json create mode 100644 src/grub2/grub/menu/tr_TR.json create mode 100644 src/grub2/grub/menu/uk_UA.json create mode 100644 src/grub2/grub/menu/vi_VN.json create mode 100644 src/grub2/grub/menu/zh_CN.json create mode 100644 src/grub2/grub/menu/zh_TW.json create mode 100644 src/grub2/grub/menulang.cfg create mode 100644 src/grub2/grub/mips64el-efi/command.lst create mode 100644 src/grub2/grub/mips64el-efi/crypto.lst create mode 100644 src/grub2/grub/mips64el-efi/fdt.lst create mode 100644 src/grub2/grub/mips64el-efi/fs.lst create mode 100644 src/grub2/grub/mips64el-efi/moddep.lst create mode 100644 src/grub2/grub/mips64el-efi/partmap.lst create mode 100644 src/grub2/grub/mips64el-efi/parttool.lst create mode 100644 src/grub2/grub/mips64el-efi/terminal.lst create mode 100644 src/grub2/grub/mips64el-efi/video.lst create mode 100644 src/grub2/grub/power.cfg create mode 100644 src/grub2/grub/themes/hiperiso/background.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_c.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_e.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_n.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_ne.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_nw.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_s.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_se.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_sw.png create mode 100644 src/grub2/grub/themes/hiperiso/menu_w.png create mode 100644 src/grub2/grub/themes/hiperiso/select_c.png create mode 100644 src/grub2/grub/themes/hiperiso/slider_c.png create mode 100644 src/grub2/grub/themes/hiperiso/slider_n.png create mode 100644 src/grub2/grub/themes/hiperiso/slider_s.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_c.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_e.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_n.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_ne.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_nw.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_s.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_se.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_sw.png create mode 100644 src/grub2/grub/themes/hiperiso/terminal_box_w.png create mode 100644 src/grub2/grub/themes/hiperiso/theme.txt create mode 100644 src/grub2/grub/x86_64-efi/command.lst create mode 100644 src/grub2/grub/x86_64-efi/crypto.lst create mode 100644 src/grub2/grub/x86_64-efi/fdt.lst create mode 100644 src/grub2/grub/x86_64-efi/fs.lst create mode 100644 src/grub2/grub/x86_64-efi/moddep.lst create mode 100644 src/grub2/grub/x86_64-efi/partmap.lst create mode 100644 src/grub2/grub/x86_64-efi/parttool.lst create mode 100644 src/grub2/grub/x86_64-efi/terminal.lst create mode 100644 src/grub2/grub/x86_64-efi/video.lst create mode 100644 src/grub2/hiperiso.c create mode 100644 src/grub2/hiperiso.h create mode 100644 src/grub2/hiperiso_browser.c create mode 100644 src/grub2/hiperiso_cmd.c create mode 100644 src/grub2/hiperiso_def.h create mode 100644 src/grub2/hiperiso_json.c create mode 100644 src/grub2/hiperiso_linux.c create mode 100644 src/grub2/hiperiso_plugin.c create mode 100644 src/grub2/hiperiso_unix.c create mode 100644 src/grub2/hiperiso_vhd.c create mode 100644 src/grub2/hiperiso_windows.c create mode 100644 src/grub2/huffman.c create mode 100644 src/grub2/huffman.h create mode 100644 src/grub2/lzx.c create mode 100644 src/grub2/lzx.h create mode 100644 src/grub2/miniz.c create mode 100644 src/grub2/miniz.h create mode 100644 src/grub2/wimboot.h create mode 100644 src/grub2/xpress.c create mode 100644 src/grub2/xpress.h diff --git a/src/grub2/Makefile.am b/src/grub2/Makefile.am new file mode 100644 index 0000000..d84c2ef --- /dev/null +++ b/src/grub2/Makefile.am @@ -0,0 +1,507 @@ +AUTOMAKE_OPTIONS = subdir-objects -Wno-portability + +DEPDIR=.deps-core + +include $(top_srcdir)/conf/Makefile.common + +CC=$(TARGET_CC) +CPP=$(TARGET_CC) +CCAS=$(TARGET_CC) +RANLIB=$(TARGET_RANLIB) +STRIP=$(TARGET_STRIP) + +MACHO2IMG=$(top_builddir)/grub-macho2img + +AM_CFLAGS = $(TARGET_CFLAGS) +AM_LDFLAGS = $(TARGET_LDFLAGS) +AM_CPPFLAGS = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT) +AM_CCASFLAGS = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT) + +CFLAGS_PROGRAM += $(CFLAGS_PLATFORM) +LDFLAGS_PROGRAM += $(LDFLAGS_PLATFORM) +CPPFLAGS_PROGRAM += $(CPPFLAGS_PLATFORM) +CCASFLAGS_PROGRAM += $(CCASFLAGS_PLATFORM) + +CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin +CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) +CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) + +build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^ +CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT) + +build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ +CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT) + +# gentrigtables +gentrigtables$(BUILD_EXEEXT): gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) +CLEANFILES += gentrigtables$(BUILD_EXEEXT) + +build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^ +CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT) + +# trigtables.c +trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac + ./gentrigtables$(BUILD_EXEEXT) > $@ +CLEANFILES += trigtables.c + +# XXX Use Automake's LEX & YACC support +grub_script.tab.h: script/parser.y + $(YACC) -d -p grub_script_yy -b grub_script $< +grub_script.tab.c: grub_script.tab.h +CLEANFILES += grub_script.tab.c grub_script.tab.h + +# For the lexer. +grub_script.yy.h: script/yylex.l + $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $< +grub_script.yy.c: grub_script.yy.h + +rs_decoder.h: $(srcdir)/lib/reed_solomon.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding + +CLEANFILES += grub_script.yy.c grub_script.yy.h + +include $(srcdir)/Makefile.core.am + +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h +if COND_emu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h +else +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h +endif +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h + +if COND_i386_pc +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_xen_pvh +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h +endif + +if COND_i386_efi +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h +endif + +if COND_i386_coreboot +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_i386_multiboot +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_i386_qemu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_ieee1275 +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_xen +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +endif + +if COND_x86_64_xen +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/x86_64/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +endif + +if COND_x86_64_efi +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h +endif + +if COND_ia64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h +endif + +if COND_mips_arc +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +endif + +if COND_mips_qemu_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_mips_loongson +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/time.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_mips_qemu_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +endif + +if COND_mips64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h +endif + +if COND_powerpc_ieee1275 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_sparc64_ieee1275 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_arm_uboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +endif + +if COND_arm_coreboot +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dma.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/coreboot/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdtbus.h +endif + +if COND_arm_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_arm64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_riscv32_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_riscv64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_emu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +if COND_GRUB_EMU_SDL +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h +endif +if COND_GRUB_EMU_PCI +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h +endif +endif + +symlist.h: $(top_builddir)/config.h $(KERNEL_HEADER_FILES) + @list='$^'; \ + for p in $$list; do \ + echo "#include <$$p>" >> $@ || (rm -f $@; exit 1); \ + done +CLEANFILES += symlist.h +BUILT_SOURCES += symlist.h + +symlist.c: symlist.h gensymlist.sh + $(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1) + cat symlist.p | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1) + rm -f symlist.p +CLEANFILES += symlist.c +BUILT_SOURCES += symlist.c + +if COND_HAVE_ASM_USCORE +ASM_PREFIX=_ +else +ASM_PREFIX= +endif + +noinst_DATA += kernel_syms.lst + +kernel_syms.lst: $(KERNEL_HEADER_FILES) $(top_builddir)/config.h + $(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) $(CFLAGS) -DGRUB_SYMBOL_GENERATOR=1 $^ >kernel_syms.input + cat kernel_syms.input | grep -v '^#' | sed -n \ + -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \ + | sort -u >$@ + rm -f kernel_syms.input +CLEANFILES += kernel_syms.lst + +if COND_emu +kern/emu/grub_emu-main.$(OBJEXT):grub_emu_init.h +grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h +kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h +grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h + +grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES) + rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ +CLEANFILES += grub_emu_init.h + +grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES) + rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ +CLEANFILES += grub_emu_init.c +endif + +# List files + +fs.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'FS_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += fs.lst +CLEANFILES += fs.lst + +command.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ + -e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ + -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += command.lst +CLEANFILES += command.lst + +partmap.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'PARTMAP_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += partmap.lst +CLEANFILES += partmap.lst + +terminal.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/INPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \ + -e "/OUTPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += terminal.lst +CLEANFILES += terminal.lst + +fdt.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \ + -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += fdt.lst +CLEANFILES += fdt.lst + +parttool.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/PARTTOOL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += parttool.lst +CLEANFILES += parttool.lst + +video.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'VIDEO_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += video.lst +CLEANFILES += video.lst + +# but, crypto.lst is simply copied +crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst + cp $^ $@ +platform_DATA += crypto.lst +CLEANFILES += crypto.lst + +syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES) + cat kernel_syms.lst > $@.new + for m in $(MODULE_FILES); do \ + sh $< $$m >> $@.new || exit 1; \ + done + mv $@.new $@ + +# generate global module dependencies list +moddep.lst: syminfo.lst genmoddep.awk video.lst + cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) +platform_DATA += moddep.lst +CLEANFILES += config.log syminfo.lst moddep.lst + +$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT) + TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ +platform_DATA += $(MOD_FILES) +platform_DATA += modinfo.sh +CLEANFILES += $(MOD_FILES) + +if COND_ENABLE_EFIEMU +efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) + -rm -f $@ + -rm -f $@.bin + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m32 -Wall -Werror -nostdlib -static -O2 -c -o $@.bin $< + if test "x$(TARGET_APPLE_LINKER)" = x1; then \ + $(TARGET_OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \ + rm -f $@.bin ; \ + elif test ! -z "$(TARGET_OBJ2ELF)"; then \ + $(TARGET_OBJ2ELF) $@.bin || (rm -f $@.bin; exit 1); \ + mv $@.bin $@ ; \ + else \ + mv $@.bin $@ ; \ + fi + +# Link format -arch,x86_64 means Apple linker +efiemu64_c.o: efiemu/runtime/efiemu.c + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -nostdlib -Wall -Werror -O2 -mcmodel=large -mno-red-zone -c -o $@ $< + +efiemu64_s.o: efiemu/runtime/efiemu.S + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -Wall -Werror -nostdlib -O2 -mcmodel=large -mno-red-zone -c -o $@ $< + +efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF) + -rm -f $@ + -rm -f $@.bin + $(TARGET_CC) -m64 $(EFIEMU64_LINK_FORMAT) -nostdlib -static -Wl,-r -o $@.bin $^ + if test "x$(EFIEMU64_LINK_FORMAT)" = x-arch,x86_64; then \ + $(TARGET_OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \ + rm -f $@.bin; \ + else \ + mv $@.bin $@ ; \ + fi + +platform_DATA += efiemu32.o efiemu64.o +CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o +endif + +windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform) + for x in $(platform_DATA); do \ + cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \ + done diff --git a/src/grub2/Makefile.core.def b/src/grub2/Makefile.core.def new file mode 100644 index 0000000..1ab201e --- /dev/null +++ b/src/grub2/Makefile.core.def @@ -0,0 +1,2586 @@ +AutoGen definitions Makefile.tpl; + +transform_data = { + installdir = noinst; + name = gensyminfo.sh; + common = gensyminfo.sh.in; +}; + +transform_data = { + installdir = noinst; + name = genmod.sh; + common = genmod.sh.in; +}; + +transform_data = { + installdir = noinst; + name = modinfo.sh; + common = modinfo.sh.in; +}; + +transform_data = { + installdir = platform; + name = gmodule.pl; + common = gmodule.pl.in; +}; + +transform_data = { + installdir = platform; + name = gdb_grub; + common = gdb_grub.in; +}; + +transform_data = { + installdir = platform; + name = grub.chrp; + common = boot/powerpc/grub.chrp.in; + enable = powerpc_ieee1275; +}; + +transform_data = { + installdir = platform; + name = bootinfo.txt; + common = boot/powerpc/bootinfo.txt.in; + enable = powerpc_ieee1275; +}; + +kernel = { + name = kernel; + + nostrip = emu; + + emu_ldflags = '-Wl,-r,-d'; + i386_efi_ldflags = '-Wl,-r,-d'; + i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + x86_64_efi_ldflags = '-Wl,-r,-d'; + x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput'; + ia64_efi_ldflags = '-Wl,-r,-d'; + ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + arm_efi_ldflags = '-Wl,-r,-d'; + arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + arm64_efi_ldflags = '-Wl,-r,-d'; + arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + riscv32_efi_ldflags = '-Wl,-r,-d'; + riscv32_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + riscv64_efi_ldflags = '-Wl,-r,-d'; + riscv64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_coreboot_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_coreboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_multiboot_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_multiboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_ieee1275_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_ieee1275_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x10000'; + i386_xen_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0'; + x86_64_xen_ldflags = '$(TARGET_IMG_LDFLAGS)'; + x86_64_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0'; + i386_xen_pvh_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; + + mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; + powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; + + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; + emu_cflags = '$(CFLAGS_GNULIB)'; + emu_cppflags = '$(CPPFLAGS_GNULIB)'; + arm_uboot_ldflags = '-Wl,-r,-d'; + arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + mips64_efi_ldflags = '-Wl,-r,-d'; + mips64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame -R .MIPS.abiflags'; + + arm_coreboot_ldflags = '-Wl,-r,-d'; + arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + i386_pc_startup = kern/i386/pc/startup.S; + i386_efi_startup = kern/i386/efi/startup.S; + x86_64_efi_startup = kern/x86_64/efi/startup.S; + i386_xen_startup = kern/i386/xen/startup.S; + x86_64_xen_startup = kern/x86_64/xen/startup.S; + i386_xen_pvh_startup = kern/i386/xen/startup_pvh.S; + i386_qemu_startup = kern/i386/qemu/startup.S; + i386_ieee1275_startup = kern/i386/ieee1275/startup.S; + i386_coreboot_startup = kern/i386/coreboot/startup.S; + i386_multiboot_startup = kern/i386/coreboot/startup.S; + mips_startup = kern/mips/startup.S; + mips64_efi_startup = kern/mips64/efi/startup.S; + sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; + powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + arm_uboot_startup = kern/arm/startup.S; + arm_coreboot_startup = kern/arm/startup.S; + arm_efi_startup = kern/arm/efi/startup.S; + arm64_efi_startup = kern/arm64/efi/startup.S; + riscv32_efi_startup = kern/riscv/efi/startup.S; + riscv64_efi_startup = kern/riscv/efi/startup.S; + + common = kern/command.c; + common = kern/corecmd.c; + common = kern/device.c; + common = kern/disk.c; + common = kern/dl.c; + common = kern/env.c; + common = kern/err.c; + common = kern/file.c; + common = kern/fs.c; + common = kern/list.c; + common = kern/main.c; + common = kern/misc.c; + common = kern/parser.c; + common = kern/partition.c; + common = kern/rescue_parser.c; + common = kern/rescue_reader.c; + common = kern/term.c; + + noemu = kern/compiler-rt.c; + noemu = kern/mm.c; + noemu = kern/time.c; + noemu = kern/generic/millisleep.c; + + noemu_nodist = symlist.c; + + mips = kern/generic/rtc_get_time_ms.c; + + ieee1275 = disk/ieee1275/ofdisk.c; + ieee1275 = kern/ieee1275/cmain.c; + ieee1275 = kern/ieee1275/ieee1275.c; + ieee1275 = kern/ieee1275/mmap.c; + ieee1275 = kern/ieee1275/openfw.c; + ieee1275 = term/ieee1275/console.c; + ieee1275 = kern/ieee1275/init.c; + + uboot = disk/uboot/ubootdisk.c; + uboot = kern/uboot/uboot.c; + uboot = kern/uboot/init.c; + uboot = kern/uboot/hw.c; + uboot = term/uboot/console.c; + arm_uboot = kern/arm/uboot/init.c; + arm_uboot = kern/arm/uboot/uboot.S; + + arm_coreboot = kern/arm/coreboot/init.c; + arm_coreboot = kern/arm/coreboot/timer.c; + arm_coreboot = kern/arm/coreboot/coreboot.S; + arm_coreboot = lib/fdt.c; + arm_coreboot = bus/fdt.c; + arm_coreboot = term/ps2.c; + arm_coreboot = term/arm/pl050.c; + arm_coreboot = term/arm/cros.c; + arm_coreboot = term/arm/cros_ec.c; + arm_coreboot = bus/spi/rk3288_spi.c; + arm_coreboot = commands/keylayouts.c; + arm_coreboot = kern/arm/coreboot/dma.c; + + terminfoinkernel = term/terminfo.c; + terminfoinkernel = term/tparm.c; + terminfoinkernel = commands/extcmd.c; + terminfoinkernel = lib/arg.c; + + softdiv = lib/division.c; + + i386 = kern/i386/dl.c; + i386_xen = kern/i386/dl.c; + i386_xen_pvh = kern/i386/dl.c; + + i386_coreboot = kern/i386/coreboot/init.c; + i386_multiboot = kern/i386/coreboot/init.c; + i386_qemu = kern/i386/qemu/init.c; + i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; + coreboot = video/coreboot/cbfb.c; + + efi = disk/efi/efidisk.c; + efi = kern/efi/efi.c; + efi = kern/efi/init.c; + efi = kern/efi/mm.c; + efi = term/efi/console.c; + efi = kern/acpi.c; + efi = kern/efi/acpi.c; + i386_coreboot = kern/i386/pc/acpi.c; + i386_multiboot = kern/i386/pc/acpi.c; + i386_coreboot = kern/acpi.c; + i386_multiboot = kern/acpi.c; + + x86 = kern/i386/tsc.c; + x86 = kern/i386/tsc_pit.c; + i386_efi = kern/i386/efi/tsc.c; + x86_64_efi = kern/i386/efi/tsc.c; + i386_efi = kern/i386/tsc_pmtimer.c; + i386_coreboot = kern/i386/tsc_pmtimer.c; + x86_64_efi = kern/i386/tsc_pmtimer.c; + + i386_efi = kern/i386/efi/init.c; + i386_efi = bus/pci.c; + + x86_64 = kern/x86_64/dl.c; + x86_64_xen = kern/x86_64/dl.c; + x86_64_efi = kern/x86_64/efi/callwrap.S; + x86_64_efi = kern/i386/efi/init.c; + x86_64_efi = bus/pci.c; + + xen = kern/i386/tsc.c; + xen = kern/i386/xen/tsc.c; + x86_64_xen = kern/x86_64/xen/hypercall.S; + i386_xen = kern/i386/xen/hypercall.S; + xen = kern/xen/init.c; + xen = term/xen/console.c; + xen = disk/xen/xendisk.c; + xen = commands/boot.c; + + i386_xen_pvh = commands/boot.c; + i386_xen_pvh = disk/xen/xendisk.c; + i386_xen_pvh = kern/i386/tsc.c; + i386_xen_pvh = kern/i386/xen/tsc.c; + i386_xen_pvh = kern/i386/xen/pvh.c; + i386_xen_pvh = kern/xen/init.c; + i386_xen_pvh = term/xen/console.c; + + ia64_efi = kern/ia64/efi/startup.S; + ia64_efi = kern/ia64/efi/init.c; + ia64_efi = kern/ia64/dl.c; + ia64_efi = kern/ia64/dl_helper.c; + ia64_efi = kern/ia64/cache.c; + + arm_efi = kern/arm/efi/init.c; + arm_efi = kern/efi/fdt.c; + + arm64_efi = kern/arm64/efi/init.c; + arm64_efi = kern/efi/fdt.c; + + riscv32_efi = kern/riscv/efi/init.c; + riscv32_efi = kern/efi/fdt.c; + + riscv64_efi = kern/riscv/efi/init.c; + riscv64_efi = kern/efi/fdt.c; + + i386_pc = kern/i386/pc/init.c; + i386_pc = kern/i386/pc/mmap.c; + i386_pc = term/i386/pc/console.c; + + i386_qemu = bus/pci.c; + i386_qemu = kern/vga_init.c; + i386_qemu = kern/i386/qemu/mmap.c; + + coreboot = kern/coreboot/mmap.c; + i386_coreboot = kern/i386/coreboot/cbtable.c; + coreboot = kern/coreboot/cbtable.c; + arm_coreboot = kern/arm/coreboot/cbtable.c; + + i386_multiboot = kern/i386/multiboot_mmap.c; + + mips = kern/mips/cache.S; + mips = kern/mips/dl.c; + mips = kern/mips/init.c; + + mips_qemu_mips = kern/mips/qemu_mips/init.c; + mips_qemu_mips = term/ns8250.c; + mips_qemu_mips = term/serial.c; + mips_qemu_mips = term/at_keyboard.c; + mips_qemu_mips = term/ps2.c; + mips_qemu_mips = commands/boot.c; + mips_qemu_mips = commands/keylayouts.c; + mips_qemu_mips = term/i386/pc/vga_text.c; + mips_qemu_mips = kern/vga_init.c; + + mips_arc = kern/mips/arc/init.c; + mips_arc = term/arc/console.c; + mips_arc = disk/arc/arcdisk.c; + + mips_loongson = term/ns8250.c; + mips_loongson = bus/bonito.c; + mips_loongson = bus/cs5536.c; + mips_loongson = bus/pci.c; + mips_loongson = kern/mips/loongson/init.c; + mips_loongson = term/at_keyboard.c; + mips_loongson = term/ps2.c; + mips_loongson = commands/boot.c; + mips_loongson = term/serial.c; + mips_loongson = video/sm712.c; + mips_loongson = video/sis315pro.c; + mips_loongson = video/radeon_fuloong2e.c; + mips_loongson = video/radeon_yeeloong3a.c; + extra_dist = video/sm712_init.c; + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; + + mips64 = kern/mips64/init.c; + mips64 = kern/mips64/dl.c; + mips64 = kern/mips64/cache.S; + mips64 = kern/generic/rtc_get_time_ms.c; + mips64_efi = kern/mips64/efi/init.c; + mips64_efi = kern/mips64/efi/loongson.c; + mips64_efi = lib/mips64/efi/loongson.c; + mips64_efi = lib/mips64/efi/loongson_asm.S; + + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; + + sparc64_ieee1275 = kern/sparc64/cache.S; + sparc64_ieee1275 = kern/sparc64/dl.c; + sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; + sparc64_ieee1275 = disk/ieee1275/obdisk.c; + + arm = kern/arm/dl.c; + arm = kern/arm/dl_helper.c; + arm = kern/arm/cache_armv6.S; + arm = kern/arm/cache_armv7.S; + extra_dist = kern/arm/cache.S; + arm = kern/arm/cache.c; + arm = kern/arm/compiler-rt.S; + + arm64 = kern/arm64/cache.c; + arm64 = kern/arm64/cache_flush.S; + arm64 = kern/arm64/dl.c; + arm64 = kern/arm64/dl_helper.c; + + riscv32 = kern/riscv/cache.c; + riscv32 = kern/riscv/cache_flush.S; + riscv32 = kern/riscv/dl.c; + + riscv64 = kern/riscv/cache.c; + riscv64 = kern/riscv/cache_flush.S; + riscv64 = kern/riscv/dl.c; + + emu = disk/host.c; + emu = kern/emu/cache_s.S; + emu = kern/emu/hostdisk.c; + emu = osdep/unix/hostdisk.c; + emu = osdep/exec.c; + extra_dist = osdep/unix/exec.c; + emu = osdep/devmapper/hostdisk.c; + emu = osdep/hostdisk.c; + emu = kern/emu/hostfs.c; + emu = kern/emu/main.c; + emu = kern/emu/argp_common.c; + emu = kern/emu/misc.c; + emu = kern/emu/mm.c; + emu = kern/emu/time.c; + emu = kern/emu/cache.c; + emu = osdep/emuconsole.c; + extra_dist = osdep/unix/emuconsole.c; + extra_dist = osdep/windows/emuconsole.c; + emu = osdep/dl.c; + extra_dist = osdep/unix/dl.c; + extra_dist = osdep/windows/dl.c; + emu = osdep/sleep.c; + emu = osdep/init.c; + emu = osdep/emunet.c; + extra_dist = osdep/linux/emunet.c; + extra_dist = osdep/basic/emunet.c; + emu = osdep/cputime.c; + extra_dist = osdep/unix/cputime.c; + extra_dist = osdep/windows/cputime.c; + + videoinkernel = term/gfxterm.c; + videoinkernel = font/font.c; + videoinkernel = font/font_cmd.c; + videoinkernel = io/bufio.c; + videoinkernel = video/fb/fbblit.c; + videoinkernel = video/fb/fbfill.c; + videoinkernel = video/fb/fbutil.c; + videoinkernel = video/fb/video_fb.c; + videoinkernel = video/video.c; + + extra_dist = kern/i386/int.S; + extra_dist = kern/i386/realmode.S; + extra_dist = boot/i386/pc/lzma_decode.S; + extra_dist = kern/mips/cache_flush.S; +}; + +program = { + name = grub-emu; + mansection = 1; + + emu = kern/emu/full.c; + emu_nodist = grub_emu_init.c; + + ldadd = 'kernel.exec$(EXEEXT)'; + ldadd = '$(MODULE_FILES)'; + ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + + enable = emu; +}; + +program = { + name = grub-emu-lite; + + emu = kern/emu/lite.c; + emu_nodist = symlist.c; + + ldadd = 'kernel.exec$(EXEEXT)'; + ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + + enable = emu; +}; + +image = { + name = boot; + i386_pc = boot/i386/pc/boot.S; + i386_qemu = boot/i386/qemu/boot.S; + sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_BOOT_MACHINE_LINK_ADDR)'; + i386_qemu_ccasflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; + + /* The entry point for a.out binaries on sparc64 starts + at 0x4000. Since we are writing the 32 bytes long a.out + header in the assembly code ourselves, we need to tell + the linker to adjust the start of the text segment to + 0x4000 - 0x20 = 0x3fe0. + */ + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0'; + sparc64_ieee1275_objcopyflags = '-O binary'; + + objcopyflags = '-O binary'; + enable = i386_pc; + enable = i386_qemu; + enable = sparc64_ieee1275; +}; + +image = { + name = boot_hybrid; + i386_pc = boot/i386/pc/boot.S; + + cppflags = '-DHYBRID_BOOT=1'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = cdboot; + + i386_pc = boot/i386/pc/cdboot.S; + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S; + + /* See comment for sparc64_ieee1275_ldflags above. */ + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0'; + sparc64_ieee1275_objcopyflags = '-O binary'; + sparc64_ieee1275_cppflags = '-DCDBOOT=1'; + + objcopyflags = '-O binary'; + + enable = sparc64_ieee1275; + enable = i386_pc; +}; + +image = { + name = pxeboot; + i386_pc = boot/i386/pc/pxeboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = diskboot; + i386_pc = boot/i386/pc/diskboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8000'; + + sparc64_ieee1275 = boot/sparc64/ieee1275/diskboot.S; + sparc64_ieee1275_ldflags = '-Wl,-Ttext=0x4200'; + + objcopyflags = '-O binary'; + + enable = i386_pc; + enable = sparc64_ieee1275; +}; + +image = { + name = lnxboot; + i386_pc = boot/i386/pc/lnxboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x6000'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = xz_decompress; + mips = boot/mips/startup_raw.S; + common = boot/decompressor/minilib.c; + common = boot/decompressor/xz.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; + common = kern/compiler-rt.c; + + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1'; + + objcopyflags = '-O binary'; + mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + cflags = '-Wno-unreachable-code'; + enable = mips; +}; + +image = { + name = none_decompress; + mips = boot/mips/startup_raw.S; + common = boot/decompressor/none.c; + + cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1'; + + objcopyflags = '-O binary'; + mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + enable = mips; +}; + +image = { + name = lzma_decompress; + i386_pc = boot/i386/pc/startup_raw.S; + i386_pc_nodist = rs_decoder.h; + + objcopyflags = '-O binary'; + ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200'; + enable = i386_pc; +}; + +image = { + name = fwstart; + mips_loongson = boot/mips/loongson/fwstart.S; + objcopyflags = '-O binary'; + ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + enable = mips_loongson; +}; + +image = { + name = fwstart_fuloong2f; + mips_loongson = boot/mips/loongson/fuloong2f.S; + objcopyflags = '-O binary'; + ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + enable = mips_loongson; +}; + +module = { + name = disk; + common = lib/disk.c; + extra_dist = kern/disk_common.c; +}; + +module = { + name = trig; + common_nodist = trigtables.c; + extra_dist = gentrigtables.c; +}; + +module = { + name = cs5536; + x86 = bus/cs5536.c; + enable = x86; +}; + +module = { + name = lsspd; + mips_loongson = commands/mips/loongson/lsspd.c; + enable = mips_loongson; +}; + +module = { + name = usb; + common = bus/usb/usb.c; + common = bus/usb/usbtrans.c; + common = bus/usb/usbhub.c; + enable = usb; +}; + +module = { + name = usbserial_common; + common = bus/usb/serial/common.c; + enable = usb; +}; + +module = { + name = usbserial_pl2303; + common = bus/usb/serial/pl2303.c; + enable = usb; +}; + +module = { + name = usbserial_ftdi; + common = bus/usb/serial/ftdi.c; + enable = usb; +}; + +module = { + name = usbserial_usbdebug; + common = bus/usb/serial/usbdebug_late.c; + enable = usb; +}; + +module = { + name = uhci; + common = bus/usb/uhci.c; + enable = pci; +}; + +module = { + name = ohci; + common = bus/usb/ohci.c; + enable = pci; +}; + +module = { + name = ehci; + common = bus/usb/ehci.c; + arm_coreboot = bus/usb/ehci-fdt.c; + pci = bus/usb/ehci-pci.c; + enable = pci; + enable = arm_coreboot; +}; + +module = { + name = pci; + common = bus/pci.c; + i386_ieee1275 = bus/i386/ieee1275/pci.c; + + enable = i386_pc; + enable = i386_ieee1275; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = nativedisk; + common = commands/nativedisk.c; + + enable = x86; + enable = mips_loongson; + enable = mips_qemu_mips; +}; + +module = { + name = emupci; + common = bus/emu/pci.c; + common = commands/lspci.c; + + enable = emu; + condition = COND_GRUB_EMU_PCI; +}; + +module = { + name = lsdev; + common = commands/arc/lsdev.c; + + enable = mips_arc; +}; + +module = { + name = lsxen; + common = commands/xen/lsxen.c; + + enable = xen; +}; + +module = { + name = cmostest; + common = commands/i386/cmostest.c; + enable = cmos; +}; + +module = { + name = cmosdump; + common = commands/i386/cmosdump.c; + enable = cmos; +}; + +module = { + name = iorw; + common = commands/iorw.c; + enable = x86; +}; + +module = { + name = cbtable; + common = kern/i386/coreboot/cbtable.c; + common = kern/coreboot/cbtable.c; + enable = i386_pc; + enable = i386_efi; + enable = i386_qemu; + enable = i386_multiboot; + enable = i386_ieee1275; + enable = x86_64_efi; +}; + +module = { + name = cbtime; + common = commands/i386/coreboot/cb_timestamps.c; + enable = x86; +}; + +module = { + name = cbls; + common = commands/i386/coreboot/cbls.c; + enable = x86; +}; + +module = { + name = cbmemc; + common = term/i386/coreboot/cbmemc.c; + enable = x86; +}; + +module = { + name = regexp; + common = commands/regexp.c; + common = commands/wildcard.c; + common = lib/gnulib/regex.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +}; + +module = { + name = acpi; + + common = commands/acpi.c; + i386_pc = kern/acpi.c; + i386_pc = kern/i386/pc/acpi.c; + + enable = efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = lsacpi; + + common = commands/lsacpi.c; + + enable = efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = lsefisystab; + + common = commands/efi/lsefisystab.c; + + enable = efi; +}; + +module = { + name = lssal; + + common = commands/efi/lssal.c; + + enable = efi; +}; + +module = { + name = lsefimmap; + + common = commands/efi/lsefimmap.c; + + enable = efi; +}; + +module = { + name = lsefi; + common = commands/efi/lsefi.c; + enable = efi; +}; + +module = { + name = efifwsetup; + efi = commands/efi/efifwsetup.c; + enable = efi; +}; + +module = { + name = blocklist; + common = commands/blocklist.c; +}; + +module = { + name = blscfg; + common = commands/blscfg.c; + common = commands/loadenv.h; + enable = powerpc_ieee1275; + enable = efi; + enable = i386_pc; + enable = emu; +}; + +module = { + name = boot; + common = commands/boot.c; + i386_pc = lib/i386/pc/biosnum.c; + enable = x86; + enable = emu; + enable = sparc64_ieee1275; + enable = powerpc_ieee1275; + enable = mips_arc; + enable = mips64_efi; + enable = ia64_efi; + enable = arm_efi; + enable = arm64_efi; + enable = arm_uboot; + enable = arm_coreboot; + enable = riscv32_efi; + enable = riscv64_efi; +}; + +module = { + name = cat; + common = commands/cat.c; +}; + +module = { + name = cmp; + common = commands/cmp.c; +}; + +module = { + name = configfile; + common = commands/configfile.c; +}; + +module = { + name = cpuid; + common = commands/i386/cpuid.c; + enable = x86; + enable = i386_xen_pvh; + enable = i386_xen; + enable = x86_64_xen; +}; + +module = { + name = date; + common = commands/date.c; +}; + +module = { + name = drivemap; + + i386_pc = commands/i386/pc/drivemap.c; + i386_pc = commands/i386/pc/drivemap_int13h.S; + enable = i386_pc; +}; + +module = { + name = echo; + common = commands/echo.c; +}; + +module = { + name = eval; + common = commands/eval.c; +}; + +module = { + name = extcmd; + common = commands/extcmd.c; + common = lib/arg.c; + enable = terminfomodule; +}; + +module = { + name = fixvideo; + common = commands/efi/fixvideo.c; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = fwload; + efi = commands/efi/fwload.c; + enable = efi; +}; + +module = { + name = gptsync; + common = commands/gptsync.c; +}; + +module = { + name = halt; + nopc = commands/halt.c; + i386_pc = commands/i386/pc/halt.c; + i386_pc = commands/acpihalt.c; + i386_coreboot = commands/acpihalt.c; + i386_multiboot = commands/acpihalt.c; + i386_efi = commands/acpihalt.c; + x86_64_efi = commands/acpihalt.c; + i386_multiboot = lib/i386/halt.c; + i386_coreboot = lib/i386/halt.c; + i386_qemu = lib/i386/halt.c; + xen = lib/xen/halt.c; + i386_xen_pvh = lib/xen/halt.c; + efi = lib/efi/halt.c; + ieee1275 = lib/ieee1275/halt.c; + emu = lib/emu/halt.c; + uboot = lib/dummy/halt.c; + arm_coreboot = lib/dummy/halt.c; +}; + +module = { + name = reboot; + i386 = lib/i386/reboot.c; + i386 = lib/i386/reboot_trampoline.S; + powerpc_ieee1275 = lib/ieee1275/reboot.c; + sparc64_ieee1275 = lib/ieee1275/reboot.c; + mips_arc = lib/mips/arc/reboot.c; + mips_loongson = lib/mips/loongson/reboot.c; + mips_qemu_mips = lib/mips/qemu_mips/reboot.c; + xen = lib/xen/reboot.c; + i386_xen_pvh = lib/xen/reboot.c; + uboot = lib/uboot/reboot.c; + arm_coreboot = lib/dummy/reboot.c; + common = commands/reboot.c; +}; + +module = { + name = hashsum; + common = commands/hashsum.c; +}; + +module = { + name = pgp; + common = commands/pgp.c; + cflags = '$(CFLAGS_POSIX)'; + cppflags = '-I$(srcdir)/lib/posix_wrap'; +}; + +module = { + name = verifiers; + common = commands/verifiers.c; +}; + +module = { + name = shim_lock; + common = commands/efi/shim_lock.c; + enable = x86_64_efi; +}; + +module = { + name = hdparm; + common = commands/hdparm.c; + enable = pci; + enable = mips_qemu_mips; +}; + +module = { + name = help; + common = commands/help.c; +}; + +module = { + name = hexdump; + common = commands/hexdump.c; + common = lib/hexdump.c; +}; + +module = { + name = keystatus; + common = commands/keystatus.c; +}; + +module = { + name = loadbios; + common = commands/efi/loadbios.c; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = loadenv; + common = commands/loadenv.c; + common = commands/loadenv.h; + common = lib/envblk.c; +}; + +module = { + name = ls; + common = commands/ls.c; +}; + +module = { + name = lsmmap; + common = commands/lsmmap.c; +}; + +module = { + name = lspci; + common = commands/lspci.c; + + enable = pci; +}; + +module = { + name = memrw; + common = commands/memrw.c; +}; + +module = { + name = minicmd; + common = commands/minicmd.c; +}; + +module = { + name = parttool; + common = commands/parttool.c; +}; + +module = { + name = password; + common = commands/password.c; +}; + +module = { + name = password_pbkdf2; + common = commands/password_pbkdf2.c; +}; + +module = { + name = play; + x86 = commands/i386/pc/play.c; + enable = x86; +}; + +module = { + name = spkmodem; + x86 = term/spkmodem.c; + enable = x86; +}; + +module = { + name = morse; + x86 = term/morse.c; + enable = x86; +}; + +module = { + name = probe; + common = commands/probe.c; +}; + +module = { + name = read; + common = commands/read.c; +}; + +module = { + name = search; + common = commands/search_wrap.c; + extra_dist = commands/search.c; +}; + +module = { + name = search_fs_file; + common = commands/search_file.c; +}; + +module = { + name = search_fs_uuid; + common = commands/search_uuid.c; +}; + +module = { + name = search_label; + common = commands/search_label.c; +}; + +module = { + name = setpci; + common = commands/setpci.c; + enable = pci; +}; + +module = { + name = pcidump; + common = commands/pcidump.c; + enable = pci; +}; + +module = { + name = sleep; + common = commands/sleep.c; +}; + +module = { + name = smbios; + + common = commands/smbios.c; + efi = commands/efi/smbios.c; + i386_pc = commands/i386/pc/smbios.c; + i386_coreboot = commands/i386/pc/smbios.c; + i386_multiboot = commands/i386/pc/smbios.c; + + enable = efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = suspend; + ieee1275 = commands/ieee1275/suspend.c; + enable = i386_ieee1275; + enable = powerpc_ieee1275; +}; + +module = { + name = escc; + ieee1275 = term/ieee1275/escc.c; + enable = powerpc_ieee1275; +}; + +module = { + name = terminal; + common = commands/terminal.c; +}; + +module = { + name = test; + common = commands/test.c; +}; + +module = { + name = true; + common = commands/true.c; +}; + +module = { + name = usbtest; + common = commands/usbtest.c; + enable = usb; +}; + +module = { + name = videoinfo; + common = commands/videoinfo.c; +}; + +module = { + name = videotest; + common = commands/videotest.c; +}; + +module = { + name = xnu_uuid; + common = commands/xnu_uuid.c; +}; + +module = { + name = dm_nv; + common = disk/dmraid_nvidia.c; +}; + +module = { + name = loopback; + common = disk/loopback.c; +}; + +module = { + name = cryptodisk; + common = disk/cryptodisk.c; +}; + +module = { + name = luks; + common = disk/luks.c; + common = disk/AFSplitter.c; +}; + +module = { + name = geli; + common = disk/geli.c; +}; + +module = { + name = lvm; + common = disk/lvm.c; +}; + +module = { + name = ldm; + common = disk/ldm.c; +}; + +module = { + name = mdraid09; + common = disk/mdraid_linux.c; +}; + +module = { + name = mdraid09_be; + common = disk/mdraid_linux_be.c; +}; + +module = { + name = mdraid1x; + common = disk/mdraid1x_linux.c; +}; + +module = { + name = diskfilter; + common = disk/diskfilter.c; +}; + +module = { + name = raid5rec; + common = disk/raid5_recover.c; +}; + +module = { + name = raid6rec; + common = disk/raid6_recover.c; +}; + +module = { + name = scsi; + common = disk/scsi.c; +}; + +module = { + name = memdisk; + common = disk/memdisk.c; +}; + +module = { + name = ata; + common = disk/ata.c; + enable = pci; + enable = mips_qemu_mips; +}; + +module = { + name = ahci; + common = disk/ahci.c; + enable = pci; +}; + +module = { + name = pata; + common = disk/pata.c; + enable = pci; + enable = mips_qemu_mips; +}; + +module = { + name = biosdisk; + i386_pc = disk/i386/pc/biosdisk.c; + enable = i386_pc; +}; + +module = { + name = usbms; + common = disk/usbms.c; + enable = usb; +}; + +module = { + name = nand; + ieee1275 = disk/ieee1275/nand.c; + enable = i386_ieee1275; +}; + +module = { + name = efiemu; + common = efiemu/main.c; + common = efiemu/i386/loadcore32.c; + common = efiemu/i386/loadcore64.c; + i386_pc = efiemu/i386/pc/cfgtables.c; + i386_coreboot = efiemu/i386/pc/cfgtables.c; + i386_multiboot = efiemu/i386/pc/cfgtables.c; + i386_ieee1275 = efiemu/i386/nocfgtables.c; + i386_qemu = efiemu/i386/nocfgtables.c; + common = efiemu/mm.c; + common = efiemu/loadcore_common.c; + common = efiemu/symbols.c; + common = efiemu/loadcore32.c; + common = efiemu/loadcore64.c; + common = efiemu/prepare32.c; + common = efiemu/prepare64.c; + common = efiemu/pnvram.c; + common = efiemu/i386/coredetect.c; + + extra_dist = efiemu/prepare.c; + extra_dist = efiemu/loadcore.c; + extra_dist = efiemu/runtime/efiemu.S; + extra_dist = efiemu/runtime/efiemu.c; + + enable = i386_pc; + enable = i386_coreboot; + enable = i386_ieee1275; + enable = i386_multiboot; + enable = i386_qemu; +}; + +module = { + name = font; + common = font/font.c; + common = font/font_cmd.c; + enable = videomodules; +}; + +module = { + name = procfs; + common = fs/proc.c; +}; + +module = { + name = affs; + common = fs/affs.c; +}; + +module = { + name = afs; + common = fs/afs.c; +}; + +module = { + name = bfs; + common = fs/bfs.c; +}; + +module = { + name = zstd; + common = lib/zstd/debug.c; + common = lib/zstd/entropy_common.c; + common = lib/zstd/error_private.c; + common = lib/zstd/fse_decompress.c; + common = lib/zstd/huf_decompress.c; + common = lib/zstd/module.c; + common = lib/zstd/xxhash.c; + common = lib/zstd/zstd_common.c; + common = lib/zstd/zstd_decompress.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd'; +}; + +module = { + name = btrfs; + common = fs/btrfs.c; + common = lib/crc.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H'; +}; + +module = { + name = archelp; + common = fs/archelp.c; +}; + +module = { + name = cbfs; + common = fs/cbfs.c; +}; + +module = { + name = cpio; + common = fs/cpio.c; +}; + +module = { + name = cpio_be; + common = fs/cpio_be.c; +}; + +module = { + name = newc; + common = fs/newc.c; +}; + +module = { + name = odc; + common = fs/odc.c; +}; + +module = { + name = ext2; + common = fs/ext2.c; +}; + +module = { + name = fat; + common = fs/fat.c; +}; + +module = { + name = exfat; + common = fs/exfat.c; +}; + +module = { + name = f2fs; + common = fs/f2fs.c; +}; + +module = { + name = fshelp; + common = fs/fshelp.c; +}; + +module = { + name = hfs; + common = fs/hfs.c; +}; + +module = { + name = hfsplus; + common = fs/hfsplus.c; +}; + +module = { + name = hfspluscomp; + common = fs/hfspluscomp.c; +}; + +module = { + name = iso9660; + common = fs/iso9660.c; +}; + +module = { + name = jfs; + common = fs/jfs.c; +}; + +module = { + name = minix; + common = fs/minix.c; +}; + +module = { + name = minix2; + common = fs/minix2.c; +}; + +module = { + name = minix3; + common = fs/minix3.c; +}; + +module = { + name = minix_be; + common = fs/minix_be.c; +}; + +module = { + name = minix2_be; + common = fs/minix2_be.c; +}; + +module = { + name = minix3_be; + common = fs/minix3_be.c; +}; + +module = { + name = nilfs2; + common = fs/nilfs2.c; +}; + +module = { + name = ntfs; + common = fs/ntfs.c; +}; + +module = { + name = ntfscomp; + common = fs/ntfscomp.c; +}; + +module = { + name = reiserfs; + common = fs/reiserfs.c; +}; + +module = { + name = romfs; + common = fs/romfs.c; +}; + +module = { + name = sfs; + common = fs/sfs.c; +}; + +module = { + name = squash4; + common = fs/squash4.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H'; +}; + +module = { + name = tar; + common = fs/tar.c; +}; + +module = { + name = udf; + common = fs/udf.c; +}; + +module = { + name = ufs1; + common = fs/ufs.c; +}; + +module = { + name = ufs1_be; + common = fs/ufs_be.c; +}; + +module = { + name = ufs2; + common = fs/ufs2.c; +}; + +module = { + name = xfs; + common = fs/xfs.c; +}; + +module = { + name = zfs; + common = fs/zfs/zfs.c; + common = fs/zfs/zfs_lzjb.c; + common = fs/zfs/zfs_lz4.c; + common = fs/zfs/zfs_sha256.c; + common = fs/zfs/zfs_fletcher.c; +}; + +module = { + name = zfscrypt; + common = fs/zfs/zfscrypt.c; +}; + +module = { + name = zfsinfo; + common = fs/zfs/zfsinfo.c; +}; + +module = { + name = macbless; + common = commands/macbless.c; +}; + +module = { + name = pxe; + i386_pc = net/drivers/i386/pc/pxe.c; + enable = i386_pc; +}; + +module = { + name = gettext; + common = gettext/gettext.c; +}; + +module = { + name = gfxmenu; + common = gfxmenu/gfxmenu.c; + common = gfxmenu/view.c; + common = gfxmenu/font.c; + common = gfxmenu/icon_manager.c; + common = gfxmenu/theme_loader.c; + common = gfxmenu/widget-box.c; + common = gfxmenu/gui_canvas.c; + common = gfxmenu/gui_circular_progress.c; + common = gfxmenu/gui_box.c; + common = gfxmenu/gui_label.c; + common = gfxmenu/gui_list.c; + common = gfxmenu/gui_image.c; + common = gfxmenu/gui_progress_bar.c; + common = gfxmenu/gui_util.c; + common = gfxmenu/gui_string_util.c; +}; + +/* Added by longpanda for Hiperiso Project */ +module = { + name = hiperiso; + common = hiperiso/hiperiso.c; + common = hiperiso/hiperiso_cmd.c; + common = hiperiso/hiperiso_linux.c; + common = hiperiso/hiperiso_unix.c; + common = hiperiso/hiperiso_windows.c; + common = hiperiso/hiperiso_vhd.c; + common = hiperiso/hiperiso_plugin.c; + common = hiperiso/hiperiso_json.c; + common = hiperiso/hiperiso_browser.c; + common = hiperiso/lzx.c; + common = hiperiso/xpress.c; + common = hiperiso/huffman.c; + common = hiperiso/miniz.c; +}; + +module = { + name = setkey; + common = term/setkey.c; +}; + +module = { + name = mouse; + efi = term/efi/mouse.c; + enable = efi; +}; + +module = { + name = hello; + common = hello/hello.c; +}; + +module = { + name = gzio; + common = io/gzio.c; +}; + +module = { + name = offsetio; + common = io/offset.c; +}; + +module = { + name = bufio; + common = io/bufio.c; + enable = videomodules; +}; + +module = { + name = elf; + common = kern/elf.c; + + extra_dist = kern/elfXX.c; +}; + +module = { + name = crypto; + common = lib/crypto.c; + + extra_dist = lib/libgcrypt-grub/cipher/crypto.lst; +}; + +module = { + name = pbkdf2; + common = lib/pbkdf2.c; +}; + +module = { + name = relocator; + common = lib/relocator.c; + x86 = lib/i386/relocator16.S; + x86 = lib/i386/relocator32.S; + x86 = lib/i386/relocator64.S; + i386_xen_pvh = lib/i386/relocator16.S; + i386_xen_pvh = lib/i386/relocator32.S; + i386_xen_pvh = lib/i386/relocator64.S; + i386 = lib/i386/relocator_asm.S; + i386_xen_pvh = lib/i386/relocator_asm.S; + x86_64 = lib/x86_64/relocator_asm.S; + i386_xen = lib/i386/relocator_asm.S; + x86_64_xen = lib/x86_64/relocator_asm.S; + x86 = lib/i386/relocator.c; + x86 = lib/i386/relocator_common_c.c; + i386_xen_pvh = lib/i386/relocator.c; + i386_xen_pvh = lib/i386/relocator_common_c.c; + ieee1275 = lib/ieee1275/relocator.c; + efi = lib/efi/relocator.c; + mips = lib/mips/relocator_asm.S; + mips = lib/mips/relocator.c; + mips64 = lib/mips64/relocator_asm.S; + mips64 = lib/mips64/relocator.c; + powerpc = lib/powerpc/relocator_asm.S; + powerpc = lib/powerpc/relocator.c; + xen = lib/xen/relocator.c; + i386_xen = lib/i386/xen/relocator.S; + x86_64_xen = lib/x86_64/xen/relocator.S; + xen = lib/i386/relocator_common_c.c; + x86_64_efi = lib/x86_64/efi/relocator.c; + + extra_dist = lib/i386/relocator_common.S; + extra_dist = kern/powerpc/cache_flush.S; + + enable = mips; + enable = mips64; + enable = powerpc; + enable = x86; + enable = i386_xen_pvh; + enable = xen; +}; + +module = { + name = datetime; + cmos = lib/cmos_datetime.c; + efi = lib/efi/datetime.c; + uboot = lib/dummy/datetime.c; + arm_coreboot = lib/dummy/datetime.c; + sparc64_ieee1275 = lib/ieee1275/datetime.c; + powerpc_ieee1275 = lib/ieee1275/datetime.c; + sparc64_ieee1275 = lib/ieee1275/cmos.c; + powerpc_ieee1275 = lib/ieee1275/cmos.c; + xen = lib/xen/datetime.c; + i386_xen_pvh = lib/xen/datetime.c; + + mips_arc = lib/arc/datetime.c; + enable = noemu; +}; + +module = { + name = setjmp; + common = lib/setjmp.S; + extra_dist = lib/i386/setjmp.S; + extra_dist = lib/mips/setjmp.S; + extra_dist = lib/x86_64/setjmp.S; + extra_dist = lib/sparc64/setjmp.S; + extra_dist = lib/powerpc/setjmp.S; + extra_dist = lib/ia64/setjmp.S; + extra_dist = lib/ia64/longjmp.S; + extra_dist = lib/arm/setjmp.S; + extra_dist = lib/arm64/setjmp.S; + extra_dist = lib/riscv/setjmp.S; +}; + +module = { + name = aout; + common = loader/aout.c; + enable = x86; +}; + +module = { + name = bsd; + x86 = loader/i386/bsd.c; + x86 = loader/i386/bsd32.c; + x86 = loader/i386/bsd64.c; + + extra_dist = loader/i386/bsdXX.c; + extra_dist = loader/i386/bsd_pagetable.c; + + enable = x86; +}; + +module = { + name = plan9; + i386_pc = loader/i386/pc/plan9.c; + enable = i386_pc; +}; + + +module = { + name = linux16; + common = loader/i386/pc/linux.c; + enable = x86; +}; + +module = { + name = ntldr; + i386_pc = loader/i386/pc/ntldr.c; + enable = i386_pc; +}; + + +module = { + name = truecrypt; + i386_pc = loader/i386/pc/truecrypt.c; + enable = i386_pc; +}; + + +module = { + name = freedos; + i386_pc = loader/i386/pc/freedos.c; + enable = i386_pc; +}; + +module = { + name = pxechain; + i386_pc = loader/i386/pc/pxechainloader.c; + enable = i386_pc; +}; + +module = { + name = multiboot2; + cppflags = "-DGRUB_USE_MULTIBOOT2"; + + common = loader/multiboot.c; + common = loader/multiboot_mbi2.c; + enable = x86; + enable = i386_xen_pvh; + enable = mips; +}; + +module = { + name = multiboot; + common = loader/multiboot.c; + x86 = loader/i386/multiboot_mbi.c; + i386_xen_pvh = loader/i386/multiboot_mbi.c; + extra_dist = loader/multiboot_elfxx.c; + enable = x86; + enable = i386_xen_pvh; +}; + +module = { + name = xen_boot; + arm64 = loader/arm64/xen_boot.c; + enable = arm64; +}; + +module = { + name = linux; + x86 = loader/i386/linux.c; + i386_xen_pvh = loader/i386/linux.c; + xen = loader/i386/xen.c; + i386_pc = lib/i386/pc/vesa_modes_table.c; + i386_xen_pvh = lib/i386/pc/vesa_modes_table.c; + mips = loader/mips/linux.c; + mips64 = loader/mips64/linux.c; + powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; + sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; + ia64_efi = loader/ia64/efi/linux.c; + arm_coreboot = loader/arm/linux.c; + arm_efi = loader/arm64/linux.c; + arm_uboot = loader/arm/linux.c; + arm64 = loader/arm64/linux.c; + riscv32 = loader/riscv/linux.c; + riscv64 = loader/riscv/linux.c; + common = loader/linux.c; + common = lib/cmdline.c; + enable = noemu; +}; + +module = { + name = fdt; + efi = loader/efi/fdt.c; + common = lib/fdt.c; + enable = fdt; +}; + +module = { + name = xnu; + x86 = loader/xnu_resume.c; + x86 = loader/i386/xnu.c; + x86 = loader/xnu.c; + + /* Code is pretty generic but relies on RNG which + is available only on few platforms. It's not a + big deal as xnu needs ACPI anyway and we have + RNG on all platforms with ACPI. + */ + enable = i386_multiboot; + enable = i386_coreboot; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = random; + x86 = lib/i386/random.c; + common = lib/random.c; + + i386_multiboot = kern/i386/tsc_pmtimer.c; + i386_coreboot = kern/i386/tsc_pmtimer.c; + i386_pc = kern/i386/tsc_pmtimer.c; + + enable = i386_multiboot; + enable = i386_coreboot; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = macho; + + common = loader/macho.c; + common = loader/macho32.c; + common = loader/macho64.c; + common = loader/lzss.c; + extra_dist = loader/machoXX.c; +}; + +module = { + name = appleldr; + common = loader/efi/appleloader.c; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = chain; + efi = loader/efi/chainloader.c; + i386_pc = loader/i386/pc/chainloader.c; + i386_coreboot = loader/i386/coreboot/chainloader.c; + i386_coreboot = lib/LzmaDec.c; + enable = i386_pc; + enable = i386_coreboot; + enable = efi; +}; + +module = { + name = mmap; + common = mmap/mmap.c; + x86 = mmap/i386/uppermem.c; + x86 = mmap/i386/mmap.c; + i386_xen_pvh = mmap/i386/uppermem.c; + i386_xen_pvh = mmap/i386/mmap.c; + + i386_pc = mmap/i386/pc/mmap.c; + i386_pc = mmap/i386/pc/mmap_helper.S; + + efi = mmap/efi/mmap.c; + + mips = mmap/mips/uppermem.c; + + enable = x86; + enable = i386_xen_pvh; + enable = ia64_efi; + enable = arm_efi; + enable = arm64_efi; + enable = riscv32_efi; + enable = riscv64_efi; + enable = mips; + enable = mips64_efi; +}; + +module = { + name = normal; + common = normal/main.c; + common = normal/cmdline.c; + common = normal/dyncmd.c; + common = normal/auth.c; + common = normal/autofs.c; + common = normal/color.c; + common = normal/completion.c; + common = normal/datetime.c; + common = normal/menu.c; + common = normal/menu_entry.c; + common = normal/menu_text.c; + common = normal/misc.c; + common = normal/crypto.c; + common = normal/term.c; + common = normal/context.c; + common = normal/charset.c; + common = lib/getline.c; + + common = script/main.c; + common = script/script.c; + common = script/execute.c; + common = script/function.c; + common = script/lexer.c; + common = script/argv.c; + + common = commands/menuentry.c; + + common = unidata.c; + common_nodist = grub_script.tab.c; + common_nodist = grub_script.yy.c; + common_nodist = grub_script.tab.h; + common_nodist = grub_script.yy.h; + + extra_dist = script/yylex.l; + extra_dist = script/parser.y; + + cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls'; + cppflags = '$(CPPFLAGS_POSIX)'; +}; + +module = { + name = part_acorn; + common = partmap/acorn.c; +}; + +module = { + name = part_amiga; + common = partmap/amiga.c; +}; + +module = { + name = part_apple; + common = partmap/apple.c; +}; + +module = { + name = part_gpt; + common = partmap/gpt.c; +}; + +module = { + name = part_msdos; + common = partmap/msdos.c; +}; + +module = { + name = part_sun; + common = partmap/sun.c; +}; + +module = { + name = part_plan; + common = partmap/plan.c; +}; + +module = { + name = part_dvh; + common = partmap/dvh.c; +}; + +module = { + name = part_bsd; + common = partmap/bsdlabel.c; +}; + +module = { + name = part_sunpc; + common = partmap/sunpc.c; +}; + +module = { + name = part_dfly; + common = partmap/dfly.c; +}; + +module = { + name = msdospart; + common = parttool/msdospart.c; +}; + +module = { + name = at_keyboard; + common = term/at_keyboard.c; + common = term/ps2.c; + enable = x86; +}; + +module = { + name = gfxterm; + common = term/gfxterm.c; + enable = videomodules; +}; + +module = { + name = gfxterm_background; + common = term/gfxterm_background.c; +}; + +module = { + name = serial; + common = term/serial.c; + x86 = term/ns8250.c; + ieee1275 = term/ieee1275/serial.c; + mips_arc = term/arc/serial.c; + efi = term/efi/serial.c; + + enable = terminfomodule; + enable = ieee1275; + enable = mips_arc; +}; + +module = { + name = sendkey; + i386_pc = commands/i386/pc/sendkey.c; + enable = i386_pc; +}; + +module = { + name = terminfo; + common = term/terminfo.c; + common = term/tparm.c; + enable = terminfomodule; +}; + +module = { + name = usb_keyboard; + common = term/usb_keyboard.c; + enable = usb; +}; + +module = { + name = vga; + common = video/i386/pc/vga.c; + enable = i386_pc; +}; + +module = { + name = vga_text; + common = term/i386/pc/vga_text.c; + enable = i386_pc; +}; + +module = { + name = mda_text; + common = term/i386/pc/mda_text.c; + enable = i386_pc; + enable = i386_coreboot_multiboot_qemu; +}; + +module = { + name = video_cirrus; + x86 = video/cirrus.c; + enable = x86; +}; + +module = { + name = video_bochs; + x86 = video/bochs.c; + enable = x86; +}; + +module = { + name = functional_test; + common = tests/lib/functional_test.c; + common = tests/lib/test.c; + common = tests/checksums.h; + common = tests/video_checksum.c; + common = tests/fake_input.c; + common = video/capture.c; +}; + +module = { + name = exfctest; + common = tests/example_functional_test.c; +}; + +module = { + name = strtoull_test; + common = tests/strtoull_test.c; +}; + +module = { + name = setjmp_test; + common = tests/setjmp_test.c; +}; + +module = { + name = signature_test; + common = tests/signature_test.c; + common = tests/signatures.h; +}; + +module = { + name = sleep_test; + common = tests/sleep_test.c; +}; + +module = { + name = xnu_uuid_test; + common = tests/xnu_uuid_test.c; +}; + +module = { + name = pbkdf2_test; + common = tests/pbkdf2_test.c; +}; + +module = { + name = legacy_password_test; + common = tests/legacy_password_test.c; + enable = i386_pc; + enable = i386_xen_pvh; + enable = i386_efi; + enable = x86_64_efi; + enable = emu; + enable = xen; +}; + +module = { + name = div; + common = lib/division.c; + enable = no_softdiv; +}; + +module = { + name = div_test; + common = tests/div_test.c; +}; + +module = { + name = mul_test; + common = tests/mul_test.c; +}; + +module = { + name = shift_test; + common = tests/shift_test.c; +}; + +module = { + name = cmp_test; + common = tests/cmp_test.c; +}; + +module = { + name = ctz_test; + common = tests/ctz_test.c; +}; + +module = { + name = bswap_test; + common = tests/bswap_test.c; +}; + +module = { + name = videotest_checksum; + common = tests/videotest_checksum.c; +}; + +module = { + name = gfxterm_menu; + common = tests/gfxterm_menu.c; +}; + +module = { + name = cmdline_cat_test; + common = tests/cmdline_cat_test.c; +}; + +module = { + name = bitmap; + common = video/bitmap.c; +}; + +module = { + name = bitmap_scale; + common = video/bitmap_scale.c; +}; + +module = { + name = efi_gop; + efi = video/efi_gop.c; + enable = efi; +}; + +module = { + name = efi_uga; + efi = video/efi_uga.c; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = jpeg; + common = video/readers/jpeg.c; +}; + +module = { + name = png; + common = video/readers/png.c; +}; + +module = { + name = tga; + common = video/readers/tga.c; +}; + +module = { + name = vbe; + common = video/i386/pc/vbe.c; + enable = i386_pc; +}; + +module = { + name = video_fb; + common = video/fb/video_fb.c; + common = video/fb/fbblit.c; + common = video/fb/fbfill.c; + common = video/fb/fbutil.c; + enable = videomodules; +}; + +module = { + name = video; + common = video/video.c; + enable = videomodules; +}; + +module = { + name = video_colors; + common = video/colors.c; +}; + +module = { + name = ieee1275_fb; + ieee1275 = video/ieee1275.c; + enable = powerpc_ieee1275; +}; + +module = { + name = sdl; + emu = video/emu/sdl.c; + enable = emu; + condition = COND_GRUB_EMU_SDL; +}; + +module = { + name = datehook; + common = hook/datehook.c; +}; + +module = { + name = net; + common = net/net.c; + common = net/dns.c; + common = net/bootp.c; + common = net/ip.c; + common = net/udp.c; + common = net/tcp.c; + common = net/icmp.c; + common = net/icmp6.c; + common = net/ethernet.c; + common = net/arp.c; + common = net/netbuff.c; +}; + +module = { + name = tftp; + common = net/tftp.c; +}; + +module = { + name = http; + common = net/http.c; +}; + +module = { + name = ofnet; + common = net/drivers/ieee1275/ofnet.c; + enable = ieee1275; +}; + +module = { + name = ubootnet; + common = net/drivers/uboot/ubootnet.c; + enable = uboot; +}; + +module = { + name = efinet; + common = net/drivers/efi/efinet.c; + enable = efi; +}; + +module = { + name = emunet; + emu = net/drivers/emu/emunet.c; + enable = emu; +}; + +module = { + name = legacycfg; + common = commands/legacycfg.c; + common = lib/legacy_parse.c; + emu = lib/i386/pc/vesa_modes_table.c; + i386_efi = lib/i386/pc/vesa_modes_table.c; + x86_64_efi = lib/i386/pc/vesa_modes_table.c; + xen = lib/i386/pc/vesa_modes_table.c; + + enable = i386_pc; + enable = i386_xen_pvh; + enable = i386_efi; + enable = x86_64_efi; + enable = emu; + enable = xen; +}; + +module = { + name = syslinuxcfg; + common = lib/syslinux_parse.c; + common = commands/syslinuxcfg.c; +}; + +module = { + name = test_blockarg; + common = tests/test_blockarg.c; +}; + +module = { + name = xzio; + common = io/xzio.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; + cflags='-Wno-unreachable-code'; +}; + +module = { + name = lzopio; + common = io/lzopio.c; + common = lib/minilzo/minilzo.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-redundant-decls -Wno-error'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; +}; + +module = { + name = testload; + common = commands/testload.c; +}; + +module = { + name = backtrace; + x86 = lib/i386/backtrace.c; + i386_xen_pvh = lib/i386/backtrace.c; + i386_xen = lib/i386/backtrace.c; + x86_64_xen = lib/i386/backtrace.c; + common = lib/backtrace.c; + enable = x86; + enable = i386_xen_pvh; + enable = i386_xen; + enable = x86_64_xen; +}; + +module = { + name = lsapm; + common = commands/i386/pc/lsapm.c; + enable = i386_pc; +}; + +module = { + name = keylayouts; + common = commands/keylayouts.c; + enable = x86; +}; + +module = { + name = priority_queue; + common = lib/priority_queue.c; +}; + +module = { + name = time; + common = commands/time.c; +}; + +module = { + name = cacheinfo; + common = commands/cacheinfo.c; + condition = COND_ENABLE_CACHE_STATS; +}; + +module = { + name = boottime; + common = commands/boottime.c; + condition = COND_ENABLE_BOOT_TIME_STATS; +}; + +module = { + name = adler32; + common = lib/adler32.c; +}; + +module = { + name = crc64; + common = lib/crc64.c; +}; + +module = { + name = mpi; + common = lib/libgcrypt-grub/mpi/mpiutil.c; + common = lib/libgcrypt-grub/mpi/mpi-bit.c; + common = lib/libgcrypt-grub/mpi/mpi-add.c; + common = lib/libgcrypt-grub/mpi/mpi-mul.c; + common = lib/libgcrypt-grub/mpi/mpi-mod.c; + common = lib/libgcrypt-grub/mpi/mpi-gcd.c; + common = lib/libgcrypt-grub/mpi/mpi-div.c; + common = lib/libgcrypt-grub/mpi/mpi-cmp.c; + common = lib/libgcrypt-grub/mpi/mpi-inv.c; + common = lib/libgcrypt-grub/mpi/mpi-pow.c; + common = lib/libgcrypt-grub/mpi/mpi-mpow.c; + common = lib/libgcrypt-grub/mpi/mpih-lshift.c; + common = lib/libgcrypt-grub/mpi/mpih-mul.c; + common = lib/libgcrypt-grub/mpi/mpih-mul1.c; + common = lib/libgcrypt-grub/mpi/mpih-mul2.c; + common = lib/libgcrypt-grub/mpi/mpih-mul3.c; + common = lib/libgcrypt-grub/mpi/mpih-add1.c; + common = lib/libgcrypt-grub/mpi/mpih-sub1.c; + common = lib/libgcrypt-grub/mpi/mpih-div.c; + common = lib/libgcrypt-grub/mpi/mpicoder.c; + common = lib/libgcrypt-grub/mpi/mpih-rshift.c; + common = lib/libgcrypt-grub/mpi/mpi-inline.c; + common = lib/libgcrypt_wrap/mem.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + +module = { + name = all_video; + common = lib/fake_module.c; +}; + +module = { + name = gdb; + common = gdb/cstub.c; + common = gdb/gdb.c; + i386 = gdb/i386/idt.c; + i386 = gdb/i386/machdep.S; + i386 = gdb/i386/signal.c; + enable = i386; +}; + +module = { + name = testspeed; + common = commands/testspeed.c; +}; + +module = { + name = tpm; + common = commands/tpm.c; + efi = commands/efi/tpm.c; + enable = x86_64_efi; +}; + +module = { + name = tr; + common = commands/tr.c; +}; + +module = { + name = progress; + common = lib/progress.c; +}; + +module = { + name = file; + common = commands/file.c; + common = commands/file32.c; + common = commands/file64.c; + extra_dist = commands/fileXX.c; + common = loader/i386/xen_file.c; + common = loader/i386/xen_file32.c; + common = loader/i386/xen_file64.c; + extra_dist = loader/i386/xen_fileXX.c; +}; +module = { + name = rdmsr; + common = commands/i386/rdmsr.c; + enable = x86; +}; +module = { + name = wrmsr; + common = commands/i386/wrmsr.c; + enable = x86; +}; diff --git a/src/grub2/buildgrub.sh b/src/grub2/buildgrub.sh new file mode 100644 index 0000000..996dd99 --- /dev/null +++ b/src/grub2/buildgrub.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +VT_GRUB_DIR=$PWD + +rm -rf INSTALL +rm -rf SRC +rm -rf NBP +rm -rf PXE + +mkdir SRC +mkdir NBP +mkdir PXE + +tar -xf grub-2.04.tar.xz -C ./SRC/ + +/bin/cp -a ./MOD_SRC/grub-2.04 ./SRC/ + +cd ./SRC/grub-2.04 + + +# build for x86_64-efi +echo '======== build grub2 for x86_64-efi ===============' +make distclean +./autogen.sh +./configure --with-platform=efi --prefix=$VT_GRUB_DIR/INSTALL/ +make -j 16 || exit 1 +sh install.sh uefi + + +#build for i386-efi +echo '======== build grub2 for i386-efi ===============' +make distclean +./autogen.sh +./configure --target=i386 --with-platform=efi --prefix=$VT_GRUB_DIR/INSTALL/ +make -j 16 || exit 1 +sh install.sh i386efi + + + +#build for arm64 EFI +echo '======== build grub2 for arm64-efi ===============' +PATH=$PATH:/opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin +make distclean +./autogen.sh +./configure --prefix=$VT_GRUB_DIR/INSTALL/ \ +--target=aarch64 --with-platform=efi \ +--host=x86_64-linux-gnu \ +HOST_CC=x86_64-linux-gnu-gcc \ +BUILD_CC=gcc \ +TARGET_CC=aarch64-linux-gnu-gcc \ +TARGET_OBJCOPY=aarch64-linux-gnu-objcopy \ +TARGET_STRIP=aarch64-linux-gnu-strip TARGET_NM=aarch64-linux-gnu-nm \ +TARGET_RANLIB=aarch64-linux-gnu-ranlib +make -j 16 || exit 1 +sh install.sh arm64 + + +#build for mips64el EFI +#http://ftp.loongnix.org/os/loongnix-server/1.7/os/Source/SPackages/grub2-2.02-0.40.lns7.14.loongnix.src.rpm +make distclean +./autogen.sh +./configure --prefix=/home/share/Hiperiso/GRUB2/INSTALL/ \ +--target=mips64el --with-platform=efi \ +--host=x86_64-linux-gnu \ +HOST_CC=x86_64-linux-gnu-gcc \ +BUILD_CC=gcc \ +TARGET_CC="mips-linux-gnu-gcc -mabi=64 -Wno-error=cast-align -Wno-error=misleading-indentation" \ +TARGET_OBJCOPY=mips-linux-gnu-objcopy \ +TARGET_STRIP=mips-linux-gnu-strip TARGET_NM=mips-linux-gnu-nm \ +TARGET_RANLIB=mips-linux-gnu-ranlib +make -j 16 || exit 1 +sh install.sh mips64el + + + +# build for i386-pc +echo '======== build grub2 for i386-pc ===============' +make distclean +./autogen.sh +./configure --target=i386 --with-platform=pc --prefix=$VT_GRUB_DIR/INSTALL/ +make -j 16 || exit 1 +sh install.sh + + + +cd ../../ + diff --git a/src/grub2/grub/arm64-efi/command.lst b/src/grub2/grub/arm64-efi/command.lst new file mode 100644 index 0000000000000000000000000000000000000000..aefec3f0aa3a65b958dbcb9fe4a4e96893532637 GIT binary patch literal 1136 zcmV-$1dsduH+ooF000E$*0e?f03iVu0001VFXf})3ho3jT>uprNM|#<9!Nj+Zg()P zOYTpqs)y26%O<-RnmV*q9FZv{Z`Y!METhsQp(&TTu(lfM1Ud@l$%d2(DaVj(JM-K? zdSI;JOzJS>ejmNJt+hL-U2YcQDf!h){(bOnLNUR>XF9pTD)(t43W3sb7Ch7$+U~?@FJR0?%=RBm-Td)&eu{8v`AirTS zwzTWm6T|CSD&*R6+dQ&OxN7s{ZrhH1b;BC0-i(6@shr10G&Dgrc-SQ&HutP0nRf-s zbu<9VNHXj{9QOm>B2%7|15+U^dx@BGRq4jk5<~J?9KvoNK&9pfoN&s~U=s$nq;a?y z$n-JX>ROg}U>0?)eQ2qaQj3(F&bv3`@-3HCXh3bBH~~$W=H_}K`8w% z-~^W8A&ps?`))!D3Lau<+~^!&h>?vDah9b7-n#ewg#RQnGjnJ@s;*ZzdyWC@%;KeT zZ`JK;v_v-r0aF83D6E%%lit34Jqty|vSrXQ>9tbkZ-~;W&Jttzp@hAX{quhhqdw!j z5$*7PLaBMYke`{i^@X%@MseSK1iIIJwTu``tWeM?aDg;{fSi_p|ZG$I8|I7KzQ75z=e4Zy2qx5 zyBr4FMMJS}n)fw%JFHJQg)sL{2GhMlMS7!;)G>r2PUrmV^LAfVE*6F~tJyskS%%g3MDE-mp=e-v;%htQ~-T$Aa=bY;h~w<8aQ-Npjd-@~}aH(5o3exAkzktuY|DmzinKULHpt01`Tv)| zbXVcna3R)78_e#*d@_)ke5k85fO6jR6M0~A4S>AA4@oLHXn>%jv3;7!HyfiAp{Hd$ z;sicH8LL3ux{4{Zi+zue?`PN3;f8q3peOT5S5FO|Qjp!0wvkLsW@P!cCHY{OMNml8 zD$AP@8&r-6G7p&e&oR9K0n7;R6#xJxasC0Z#Ao{g000001X)@( CJtKnv literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/crypto.lst b/src/grub2/grub/arm64-efi/crypto.lst new file mode 100644 index 0000000000000000000000000000000000000000..bd0a97c6fe74e6cd343242b32b1a8c5ee5d24729 GIT binary patch literal 424 zcmV;Z0ayP0H+ooF000E$*0e?f03iVu0001VFXf})1E&FJT>vQ(MQhLp$et@As?M9h zMhiJ)A7SZWg2V5uWvJl|@s`>N6!aP?W0VGWNB9`*%PH`)0sQ5c-0NlUiIHV{BG^`wSv8V}asZpZJ+_^%{-yrgPbb@mudMMj{ zFQwC@D&31<;P?rVn6L9FN?=l6ITn&&0URHDOWh~&qHVkLyTIush+c}BobhIbh@ zPz1)#CNdsU`#^rF@#d=_tqBNZ(LiV;AF1uzj;%#2JpcfkI~{&C8xZCI0fPgm2LJ#R S??I8V#Ao{g000001X)_UzQgnY literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/fdt.lst b/src/grub2/grub/arm64-efi/fdt.lst new file mode 100644 index 0000000000000000000000000000000000000000..ea28d9e05f69d458ccfaf4aa985d30d366bfbc25 GIT binary patch literal 32 kcmexsUKJ6=z`*kC+7>qkAdtE5qA0)Zb1fr?!x9+<0JCTbcmMzZ literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/fs.lst b/src/grub2/grub/arm64-efi/fs.lst new file mode 100644 index 0000000000000000000000000000000000000000..12c6c9d1b8e206e3c1c635931323b38df8f1b041 GIT binary patch literal 212 zcmV;_04x9fH+ooF000E$*0e?f03iVu0001VFXf})0NMbOT>vndtmX#zMDC?nb z`g%5@yAbxc%+@ab=t2MzhtdEnLkSs=RH*ZMB#2W$uMNC?oT2TiM@(Z@*`yif?UiHB zc#4GU8uEI&hcWTM?RISxo~DVQzn7KnjCpwe0002zWHk}347|($0j>et0RRA8*|aUO O#Ao{g000001X)@P*k5M= literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/moddep.lst b/src/grub2/grub/arm64-efi/moddep.lst new file mode 100644 index 0000000000000000000000000000000000000000..c3cca2021f353ee08d4d6f4303cca63f6b523f21 GIT binary patch literal 1648 zcmV-$29NpuH+ooF000E$*0e?f03iVu0001VFXf})5M~A~T>v{8NU&E;w$UC-OKqcU z+(>00*0s^6_Q>EIWlP5sf{cN=wwnjF2jm)n zN%C5S`vw*dL$(+J;1Arwu@YhvPRn;rvAjaRy=jQQ489PBTNO75(X`PrQMkNKI6)l+ z>|oD?57(4i<*;V9Mrj|6tTqtcCh`%Y^*fSBo!2~ML%bwM1_O3^xgBRJ(_#ka-}yH{ zu};7^v&s|X-ZT}#vMr?@!oGNMvBo(cQXnNwoqj2`Zg;1`g%2*d?3w*ExOg~0J9p`Z zG^uswh`9r&n?FKZ(gr2o69GE;fg+(DnT%ks#AA!9rcr%aXah^x_mgjy3*#yYrWReJ zQrE}C78ZC#LM1@STW%HK4@8LcG)J$gW_ZOUCxbu6?*I}d(^E8H$P>hBDRGS?L(EMp zO?(=GB{d2+lf~#)qlw>Eh+!Mkh~3Yk+xDzQP5D>2&F;WUl$_!$5t3?JuK22CO))o- zNfcPL;O_h^a6e9mW{D$;6e|Bofg_|=Q$bvDGG zO0gnN$x*p}o7=dahk0q;L0d}OZo-6XFBWr*D%p4zT`}(OwuS&DY+NdTrJ49>c_5t> z%VF^fyP>Yg`S1_}2=Vbh82}w4#k=C|4UBJow??!vUHKI=(0hTZq+Pe$FQT`$aV0NK zPdiWY?r(4W_H09IhqLWTs|Kl(_{K= z&(#s^N}39Xoz}kohBvsw6`fDctRw1S9@&C!_aYpr{;?oAIimxvLE`L<)NH924=O*@?=hV?UFS{!`=+u}Mt&ZZ zoUSHWZxs;|5aH6Nd!8^b(6T#CO4P#1J z1x%yBg)?5z=Qe?gmCJw;Vf?6Y&}r_NpCz*cp2$QAUP0v&_?%9r-GjY4F7`WValeaW zNt54Z_%bi*FH(eWho$VxedVkX#IeZ$6Sz4`qTGu1^r5FHg0{3Y zG+V4z2@UL?IR-65x4;EXc?1PfXs{ zti^eI--R$j+v0;Rvb?9WPY*J3+B%l%JYrs>$15FM&9(YRiWH&eoN)%Qmg7wR8}~IW zd3zEXcK!;2Dlw0SCCjL3GzghCHbS2+%_@QqLJVezSpJ#b+t|VJ)7l_RdHKye6HkL( z!7Yf}+8=Lw^c~oZE)#)%03>vae&MEEI_a~$9jv3nq@l5Ok;jb;hnZ@|rN2d+2z!LR zwGTqK0Q;W!3cHy=SRT9QXQQ;YwqQj{bZYBfp0XHhUtpYC)TG#yC=RDA@c24k-ZAtV ucsL6whcf~I0001;A};^Dq4LiF0m%&KAOHZtNvA`x#Ao{g000001X)^)tsraw literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/partmap.lst b/src/grub2/grub/arm64-efi/partmap.lst new file mode 100644 index 0000000000000000000000000000000000000000..720c55e3213349a71bd192e631c77f86bfb4c897 GIT binary patch literal 124 zcmV-?0E7SiH+ooF000E$*0e?f03iVu0001VFXf})0B!(1T>v;3N~|EGB#XD|B&a{= z*a6u1XU~$MS1iuZ`l;{Mud$4Oyk0H1Pi2T}RSq^21Q0O1_p)_{ill=83b~RQ}TR7>U31zw Zp6kX8jGBT*Tm^jc+dkJaf+ScXqX1_96!!oC literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/terminal.lst b/src/grub2/grub/arm64-efi/terminal.lst new file mode 100644 index 0000000000000000000000000000000000000000..0f853df051d21d0b1c7ab372166bf08e9ccf6492 GIT binary patch literal 104 zcmV-u0GI#$H+ooF000E$*0e?f03iVu0001VFXf})07C#PT>vzjN<+ez|E0Y^k&=@0H7w)1@f K000001X)@vAt%ZJ literal 0 HcmV?d00001 diff --git a/src/grub2/grub/arm64-efi/video.lst b/src/grub2/grub/arm64-efi/video.lst new file mode 100644 index 0000000000000000000000000000000000000000..ad1dbd09a4ea46d29febbb1cacd7613f954589d7 GIT binary patch literal 64 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

)Fql*d9z^&@npM9ft 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

**PtN-;BFb})*W z6fdf?R9(=KmAX*gZ32*X;LQqohI?LoyR+o>=dhs0M$Xq6k3WvwDOvb0Wc5-EZTEf#?H4##)DS0~Cq@g)kV+Lu{9;)T zWZmz0Y|~1J9I1XdkRM~;0}pNyy*E+|&-goXh`glSXQE1d%tW#iGNrMP=#th+5amJk zMf29Eg5wgIT_8sipUpF?*EFys%;1G}AKO{gaGf zuY%J5Cj;3UZtODi9-rJA_VIzAxo5YAJ6BeLp%aw`YL@t6mnaX35GvBGLhXIYwOE*867Vhk%P;jlKS6$f zVp+@Z5HmDu#obnEts;qp&8z_Jv4dccK40Q!bvB8WZ%>RoYkYaTH=jmP2KH3g`wp!Y z!r(%d-hi2{XM_DVGO(bI2 z)oEZRAGpyH&Ot}&jD;LVkJfsDfb3MRbwxtXU~-o+cE@Q1{Ld<8Cgim$#s#qdF&baW z^DKqxi{Ppur=Vd-(g%aGd?VZz0LZcYjds9@MN>(bu8PA)$3Va^*>7QolNKE}WA>W>RJ zTD6_W&?W!_C9k|aEY8k8&DMl5c~DYUsuG zr{V{qL+#<`T=PX0MBm7gHjH8G6pA&AcF+1Cl0k)DsoEY8)UHN*C@xgD^dZCfiNS{d zX2S~2yq=Zd#5LywcWz!v7w;-lxMQ}HEN*TGc+{xYLIW}b0}r$3yl8Y)Nf$IJCzDqX zlePZbqegp_ZYIE|SL#_Mix{N>jS^Pd0ZoN`RP#0el(mOgIdxl=SF!ObE>>Z^wqEI= z%cFEau&i1VYT|HYzJ+@@$uc>SfmB-+|8?~W9A?9+<8T&5%gXimq#E>UItL zRSARD;#=a?HIFW28~Ya=^H90c2vkt6oI4C-%T%q{2HB_9A=haUMo0Yl6l57>+Wn*SotEtudx%yt8h)OX-2%uVp>9FXxJMOj9Y3GH>%< zb@WRb;~QRfQ2J#nF8i097?T6G+*uVitraS*lmw_{$WPXn!_~;WI2hBgv&k*+gc|tCRnJq9I?CEwEA4xP&CSJcOvB=a|@eW zzIv(k97uwzXQq_B=9F9iVe7-ZjL&Mm&7s@U?Q<;Bx{!$gi}2`$-49&{!ZmTK*O^G` z8co~yZrCW`S#=NM_%;_YF4!}!agcH%NKI@2v4zba7busb4N+>;)C8}(WJ7>yW&PXJ zi_Ain`9jYrJxZD0cU&en51syq_3v|V;0v6|6Jh6p(hO?SwE+Z&5BJ43PbJcZuTMzR?i^f!#cNUZUH81 z^WQ8VfKFFmuWT&V;@Y$FnZibH05H-_bzo3{FGjfF79bWgSF$<3B+*|zJzr}Zj!<{R zTpr45jh4@GGDx?8ix8+gwAJvSCYY=-hIWtZ6tDuC1G*6nx;pb9uEG zdv|MIO|NJw0LlLcU9$I zc^C5p+g(L^piI_*SgGAge;-mxuS+>Sa7{mVkv~`&&9D<$PcZQleUWP}{Hj^#teIjY z(l(=m5|@PSO2Gb)D;N78O!J{^+1QfG1OR+Z)(vJLR;(T<18rfQ@Dk~dpjbKc6!88Y zMBTvcOB*<%?iU(gD0vDc7K+Q4NGu(S<`*HNAbvPsSFgeXdjpYV{)lSt*`c;^zV+T! zr?CxsHj(DVmL?EwAjipU0nQki?PesoZc8y#YSdLKavMhkC(oEWlLpPA9H z-pwv6-F+A3-8w{5eSh)79x5|uqXp7@qhZk-{PBK&OkPacKl}KD3}zmIxmGpeBiYD@ z;pk+*??y<(2g4}~)-3~$tEqb9|GWoAuf$3xe5v@Kt4Fg}JwY{oQd-dZ7UN}A(vk#4 z%LDm1LL-fcvjy=Yh>imJI;*fysGcoN)qTI%2CTxJm2hE;qrD+gjI4edUL!}iQY_87 z(Y@{+oU2jsD0h3TyV3P|(RIrPpBr(h{kXo)JQAPBiX2)867f5f09m%I_>gmAy3a!! z%)Jx%2#c{mqi6RA%KEy70vKuLr%$#Ew!v*pVlmG40w%dfZG5pdk8Pk@poj58k!9>B zA!Os8SV+CjWZmLZ{k@YjVw*H}J6mVZeK=w~@D+o*D;C7Hc}zK*mKZ#3H=iZDB9Z?WgZ(k!-1h9{xH3&G7=7 z5O^O07D)=60`G3q3>gh0dAGRwP44AgFJqTJ&F(9SPL}UpJ6c!6wD_$s|@}y%}Ktr^=l|9qy^ZYm7A<@c!)zV;fL}OX;8yniC zCCp>o0bf}NTx1Hi!(gOcLw|ahj-&;9pKD?uGBpoK+90wpOD?tFtzILWy8xCmOm^(S z!7}7r3hichk|oAM34SF3prT`j^%KrEWAp{g9%x``DWxr2IF1Ft!iO2`_qq5h%hIwc1L#W-^kDRzT7YryF<)z9dq-PShz$SX*0LYEyn#3M_~{#{trZjuw=j zZ*1$6iFvB?vb^htg(|}p7kD_0pI^`sl4S9bg zEsyH`nnQvD0s?Rn2gQ>$%sl(XDXzAu%wTA9Jl5H?O#^I zkcKR*fE+A;UJ0XKaK3@Tq!+J{#|u&6Be>LzJV8bn*Ma|>_C#K-%d&o+1c2nLbf;BOc4tgq0LKg?WN@cdmNFj}XeA#m2sr&L1FXnT~fZh!>f z)c)*UpGrjsxrUUc-pfJ6pM8Ath@ZS&<2CFEsRle75Z_Oh?om%~`OjoX6r2|!#%%Co z&erDY?oA$7PLxMmAEUh+Fm{tO~2UN17mN>+dm##IkZRmRbI_;roZDEFY?> zzqOc0YqHj@`GT6A2Idk-l@X{O8oNLpc(iJgr85$E5q3TNQQonQt-6=GC|hDa3wDg^#cqmW8hl0KVu_XVm9DD zNy#T!IL&iVy_VmAjAgW`jH-m!@t%@`BKivaFam3h-6{dv)xr-ad2i6V5#8hT@iXir zKMzjrjks3R1Q=081ggVtZhTIQHb&x*PUomSg3erW$gV=+s9pB8jlocgXpayugnK6Z z4%nH3Sv`}h^1Dz~jT@?Cz?mx3;g9QA8(eLg_WJdtzA!ug}f%jKpcb)q5&ld}y z(TnbRrPNV_l9|~@x;k5%&#W3i{~9oXMp|{Tbt#TfV>@YRahBdG>THSz`IiKJo{x~*2mj~CLnxUPKJ2U+;dwE*rBocwtTgPz+t3`%hR zf^cj;`UtTrl}kM|5ao}x3O6C&;iuzObmxW`&WEj5KQ=y3tU3ohZeGHSa2Mm_N;TPy=<@!3uKim^$0{?sujgu zLsPS@zYg%4cFE_14 zA*E!M<(w^y1V4s8K9GiHT0a5Pk{5N$p zBMAwA=?!P1LW|6PHa?OZjqe>8UXpglcKdvt^-)>#HJeTDs{BTOTWsUn;aN1Sr1@(_ z`7x+N;noS66KK@-SR}==KU>Mu0;IgX4`%(iK}}r%JsO@2HWG6KORqAy^G8n0!M#3c zV<|sxjv0eXPi2peJ=#d~u=)erAxck;x&SSXQ?GYOh2&5NprT&?bi{65U&^;JEkB3+e%aLRm&CUDV$W zpEF}42k*nfbWf2kp}lL#fTLGy3HdG`c&0>|52AT?EThGzEAQM9Jt2jzxr~m5t6Ap0 zeY~gBL%T@;yYajb{9A1@?A{1ArNzH^@Ze9LlVR6-^qpdbZO0Xj&KyiCWAl4CQ;sPH z3-xGPdb;_jWgfxj$mElm!FU|L0X?M>WNyJiXF%KbTKjImAdbs-DG$4|qYgJr;@iGt z<-B~i+;Qe<&1rli)r;G#foM9)^Rk4xB`qk>IBqO&mPtw+hNhO$Me_{~>xS7}H22B# zFd&#n9)+1QD9jVUhBeC#VLLCSc?sw^J57U&<3)9pHEc zi4K<_OeXyPFHEC_@@PJomZCYN?iP>Zt9&(qsq@k;e>2|(`JhHkF~iRkROBqF=d%e| zI$Y+I6Id#KCOh)Iip`Ys5X@UVw-1#pw+c;6!$=HaHLgAJy-8+(k(VnpG5!-h zr(3fMRa8TX91lW$}!hrJ!|UL$|d@& zf999lx(gan>F=5^K@zC*5`>?@S=rAF&ixl>+r|q(t?z!TP@S%MWvsITzrz=Qhj+CU z)=J6#lNLDE)+1sA@|g4$wsnoAFCGHHhB!A*tw2#S&BIi4uXS{(yTtxmJ#OD&@2XQ_ zzOn(^%4FB>6?t46i^>~RzRn$5TSlUf13}L(_=aCdJXpHqhUptTE{<^M722+2g>Ckl z0@L;~4kKig*Tg?tOm8`&#)Tde!d;*tbseF-{3~0HLcMw$V@u7Prgeie^X252(t+EGhz4_w zHF!^k{d2MrO=@0i;f5B;jMHgv0yW!`(@cb)9;_A7OS^G3zBbbnV&8f8s3jCzZLMv2 zApQytc0Y~$be1{4a+et6QfvTo0MylV@}5h;yU9237_v1Y#ja;d+rk-?}i;8qMC%8k=4$|$|CNliEkEj zF@#q=$v|R5ajhhF`}<+7LuOT-z1me!_urlcA%C%lXk+egYBP6`9hqZN_xFwTfySFJ ze0KSb<)v_uE>5{&PpsPPw*6GTfQ9z8xvnNG0py_7M(VKmKR#Y>-*V=EPi^xR?_sRi zi(#Vfqm4$J&bB-S4>G_Cv2U&OE8TJH3*#sOUV@-o^X5QuPg1cZINaZv3aObZh0lSr zL(qA~b-*jlPKa_BAs`?1x4Iqx*s;a#Z|uj!>lXO^x>^w=AOKd1={31fWDLCDYG>j+ z25CMr|IdY)DFE^Bb#-H02>{3mZjRf*Vh{`1H_Pm-5Jo-%@r8S(ojwe4v>6c3q5E5~lGS`Z*-kQh}1F(a!K+HuQDiLS5Df8-@Tp`ij$ctgT4-gu85 zl}=_R%=xmlElM_v$aia~iQbbD@B`d<0Z$JN&s6aUF0TG4F9E-;xt5T6w;iF2JLzs? z49fKKGWmHc9`9?J1bi_AF_e|*ilMxG5hq_*V7zP)yk$5T%%AHUjHsQ%sZl4?wzH>B zZR;AlM9l?*Q$%ftN|&gGg|o$-4MFf69WYR&zCk0Yby8+JtCMPc8Lk52dGs3x2DSzd{nfh)e#>9mpAkBd}{7=y=A|aJ>OoQW09X zM1n(+B;Ykl@luK5*);Hz;11w%xw7AHsbs;cib^5fM=m@S9F-y!SDZ+H5jVz$Wa@{G zSHen6HRs8GF}JhwB!t=p*>NR!y+rK{I9>j!qZYpTyAdPyuv7W*hO67xWjUkQfDB>c zyuD3>A%y|Ej?V1ql8nH$r#|^NmpV-~=6q5jN5Ltg8IqGOMyZQygC`y~%kuSzB>v<2 z8IraaunS6V+XBEBZ1)=zAZmjF-sBM(Be|4>*BkVFq9I=fgj3Z>2b8{CYhX}A{F2^3 z-xPWSN^FLMXYPkjNogJ$LhCtN6C4ya(SQ4!SWuhyDv18;OAzDU=-4JmwJZehBGfkWKt2--J@ zP#sYy7AS*tkNkuxk>vDUfw^ohr%2jf)=!98s18dt(PfuY6_)65{<5X8S04)LB7IJdV(; zmkh-Ux6r=!kKmv#6mFfgPJFZj=j-4NPM>wlGq^vpno%|6zJlejrvPfXta2;~!UN5w`waPjifP>wh#?kHRzELe7lzO&3A{7z8ST@7@m$-! zO&D)4CTqT)s;FHkmeh0$l$~N-gUW$n{_j9Mvr7*}8`l_1K(GjgWLFzFeh-)6Ye@D+8jt>GtoZuUPGUWi z!>fhbv3bU)MnBPGs{9E+MQ#*0!SFBbSdWL_;0)oZLOZ;ok|E&vCw7Z)Ja~u8e1s_m zoedN=8bj4cRx-tt|DL(qvqs>UYT!E4FJ|%$c_S39QU~1Ip7efL>6lw%k9o#y_bA_g zlR*3akTJDZW-e3OSV$j1WTI;SnVT1+hVFqy3)Ck}Jy2P4p#A+A0F+Op(pZ0%ACQ7X zY%CGO*v;?9_?h}tD-lW*-yN;gVyC=@a;pY?Z)I9yZAPeN76hI9`t@sbCs+7Iyq6|> z=dN$solvoTSaY+C-pzYc={wM+%CAvqg^5vALI2xmLW8|2E?@&`V)1xoF?NiYPW6lf z{)--3%wEEh@Hhu#6CnjL3<7t^krCR1C~bZH?JSkPk(`r7O~OS+3da{1{KPNN@geC!%l+H2g@Iwa%p)gy_FSq6Zj1vm z7^_-Hwy<{q^g1i}f+}k5Adyzh`qNUe!xqKcQ z-vj9PLIwQ?j!*fi#5?$=)){JWAY|xv04dD?jViw-wW!&SM_`Fe3g0>kJ3!;c(?85Y zZvbzg9HTNVrygH9`gd;iideYtaUZWuhe}%zdln-ivi3%F%RAobJE(Ge#;Rjwm2Ig; zR_aAe6;tvV%g8G%I7HLjOh?M48nuy|OhxCI*%C^--*f?l3iyD$(s$4S^wSc=M4U03 z8+nx5-){`G+`E=7XXjHh&hLeXVf$jaO~g1A>m?@9bpsQNoT(Kn(s3i!m>f)wQ^ZHz z5b+8jvaQ^xG_^+g*$NW!Q+Ya)VEQ2 z6Hr+s%d66d)G2S1r5AEyG1DeD1C&u3Y|E}9XpbZ( zX91BwihSt(+#(B>PsoMG@ELp+EJn&pLU>E$ivZ|;0C)8*<)?{6lUf!uK zN=B4M$>Pr@NXwHavA+_bYh8q9)vHgjH?3&JAf#@_Fi~&iP66nwv)sv=ni)kuLLWUJ zz(lb_-xk$9jh)_~AE1Fq?m$TgilokftU+efNrb;0F}<}C)gEet>4$=I0QmYY3-kDa zO9MID#sUqgWuiKO{pJ?PZbA^qHb|VYF|-p)akS#_7JjB#h)=TPQhqi~Ub@Gq**3*Z zr6l7YlEI*stWQjDCPcGIy3k4my^w$KXR404^fB3Qace|?ui3JGs7`q9w-0I+lQ~0@ zd)wY$b5Yd)tO@VQmMSerH>Se}jZ7!6s~4JfE3oY_SW#-yGtfPs=|&c;84NlHOW@=4 zZ`(Zb?wss=T4vi<9r-qi!^KTZvk-h*458J{E$UWPR|W4Z=VrKqXjb8#{t4PiJzbk> zZH8r@ZV})4>AhhlF|ZufAVOQKGGpwv9QlLqUp!+V%Ez>frY%_69n?G>R5aJ`|CD}^ z{N)phyfg3J*5h8E#5e9qcwF}PPMGa}LLc@I7mS{>8zDQqJ<9xqEMtnFBPD; z&(p1c8%T>F>W@AXF&j=$(4iJ#07v(6RzkFiO^0FA#arwDQaHchT&?kUXP--@+ zDfeOoMQ5(){K`YyV-xqIJI2uH7fM+iXrvnkG#hM2sX?&PH`rM&f|vv}Wv^^gw{V&% zD#Cr}-slETVyt ze6VG?QkQP)!v)BLpDY8<7>{lgS9y`-0`qBc8wS)Vc~FJcfe1cBq-ErT46Z<_VoNeL zn|*x1%qsEBlA;lG;CuDa3)2j(1h8P=#~z*)JeOPkEnDCV(wyq&!kN4Dl|d1e#pU`2 z1Tgs>jV+o*#yguuL<7kunfz&)_60kI5GPXypz6xt&mjr_L9%#Ls*}R|-+>|XS8^U; zgFOEU!rO3%q5(20izyBy(x4iji~KnZdEMD(9z?Q5e@wh(%+sa{zCw-HFq=HrC>RR~0kp>D!WfhK(#ni)FcIMA zOO{eG))9#uQuj(@FHO23IriUDG$m0t6`>=C-kQ9YVN4A*JBSKBw5o7{Ci3 z*f^;&5z$4)S<#oE&-2Z1bG$wgHhKD|b03MlD(0N7B-_O>5EHneP~}h*E#b=+aR_g( zOQ`5m57xDfe3AI`qdF=1C|bjAFbbS8^X#rPs#x)q_eVe}^mWKI55R_KagWsZ{NI1$ z1+~0}6A|6fge(X`A+$qcRd^p3%POLXOI!D2yFDXWyo9Z99Y_7R5?h|G*bb00c4K!2 zMP=6uq|$#XlYal9qs*|PY%%%oy}$K+lcj|hl$iKQW4^kAr#ZU~JQ+K&DgdHiw67C; z?Y$MI+BH6AN>v`GY$0_f-HJF}D1Gv*(f{Pmx>f@%(V{j_;@LZHmK#4=gemDxq+;xw z`7{~_Jf2{4YUOvFZQ{wc%Bn2eW+=pPQ>aX;=6TN+Y%xvdgfj`T0rt466T(s+RJL2Z zcqmqdcxubcdC9bgLm`fN*L~Q9xb)9Q7Q?IFq<(VCC4qJ>hm+L_NB<8T4T^H+svCsJ zw0p=DU?4DuchGbiKa=`gHeZYakiWs1W7a11q|gu2yTx`%GMAK?eitzJ{UY}tfuZed zEeer^tku$KfG0AvE`1HN|7aPy&T)z@5?B^+cKxV1&_#FlKh<}qog5OfY&%4 z1e!O&uXR(Aea;85_z|ILZUEERM%ZT%JzaDiuMGxW2W}$U5aGZ`!LCypi?j%U5N&l* z3=Oh-^r|mNnYlKf74pR{ZM8@9k>LF-0zDa>ppR3-rIAxg()IjMj;2OPej zR}z25`<0iYeWVaxt%7* z20I_0*K2M2zhMC9kfsxY1K?sfpe&#D^cVld2pEDH|vEV1` z;MwSqaDahbIegoqs?}WTPaB5> zZ29DlR=zsmKrBUoJ~m@mk}-lZ-p9IQ7w@{XY(W>;ojNW(zCX7!wnsC}!#|l{a#?5C z4q33nB*kkTemd4^$~lRiUiNIvSh6a2P`-%x&~DCMOx8i|!+#LVBU13hvDdX1Snk2qpNbwoe~mUHdC_0#xw&^8G64Nl-ThN9 zHI!-dhXqugZE+{-kw6~O-fgUi$2D`8U0!pl4FQck=y6`YKULM2wFj9gb3h&Q9|JkR za9Stcc`aE5B|Z8&^j$@M?=E!-nhzgKNKMvTfv%pd)hy&yA!kW z=Y{bVY%MtMtl{xs)Xb71P@2Q6J^MDiGIOyD*HuPSKaP3|ee`HRC33tmP&SWtbWXOV zix1J7(PhDNh_NBG*V=w-#z ztH!41#~p>0aiqo7Sc{gP!WsgJx?2n^^Q3Dj@9Gnq?ZCV=wI!U!3jcP>`*-*K~ z8jxEn*!>k`Kp(ko#EI#LoL?I-73vs{&YgyQfHJRkiq53v9sf@)FF_H_W)Rc$p zj|;Q<=5-{?;d@G$jGA|T0gPrF(u1<|+qJxKI=njZjMh#RK>d|1tgKYBqFqtQD2=xj zP#(o;df(AaH&rg=9fFL$t0DxMG~dS<`=e;O7c<+AQH=oXrRU$`#VbGwj;j}d5%{|o zFkMuZ;uC%SH?S8%lFco(PUd%DKT~p1Ez|r+8xS~#fd7~BDV2WL&z(=e z#C)c`3HM(6e^eOJ&F0nn3kqiJY|ucf2?cS-p^ZAsHm3au%0dRDh|8O`Nt&uJz5elv zE6R4p8XGb0Ll2b@l_o(d@{!UAeiy8CjLH|tEm|A+w#7$FmuQJJ&L6*b6Upk($lH=Y zL79k|IG~2`bS^S@i0siW8=}ef@uvb1j|JKJI{i;U&R-{q7!o%4?pFgNwF@-KqawcSXW92L@f4vyl`B{4_lKE zlw+N-XIu-GNNn267wJyP|GSXsXEpA>QSG059s0CRNRcd-32c-WDQfq0JjOC@TdYvA zaIl@kTwIvxQBSeQ*X%F#h=Lu|M;p_LYasGzdHs5yYLw2foY7yRXRmE?PM47fFu8t? zU=3?^TlryZjinR@!f?;{-NLz1-&L&Gb+-hb&ClLq@5i%T@<^=p-;8(!38Q32HKp(fEF-`GW*> zdT?B8M7u{0u{zcSV+Y-d8|+wDFa53&=3b&+O5!263k*VZi(Dqk1pS_(=v| zQTk^zJ6&11Aq)il>lTvHI%XTkHD@iSQp{J7OFipM!=8%eYR^dbN_tkmWrs8lo^=5u zn@Pm60_+Wk@z89fENLWe)>*eE@>Kf^RLbk_Ij~mymqG$i*EKu?j2#+$ZBMyOwq7y; zKe+yRRnKM~p-8^8n9ocg>B->}&}BN1Dx&iv_V}cQc~dVTKK3362G5t!Rv47oCxmm# zBtc#;e+pG?Sm1~OE5}`pYI|SUHq8@ll$0PEh~E_nrD>SosD5py5jdvM+Q}wodB0x1 zdxGT%drN4v#c>iCE#*=E+I^llgs{)EE;>_Mp%`%i`X>Id1utwT2m7{3B_{((kLR=> z=_`a$USTv+ncS;+{t@?J>qi+2XNR9=d13TCtcOSAh&l)NaHU(Nh4R*?V9?#^UAY4S zN6=yEC=|`gv6#(`LhxF0vgAE`aVSJOyl|?O(!7KIlE>_$oBa{QuocYdVZWO%ExrBA z_C;xyip1@TwU{OK&#Wq(XK=JPje*~&6xIcncbSZCFnAj1qi)bI=mf2A!6UJ6c=rkD z=Eh{=<_=04xW>M_>KP-KET&YRJgUjk)^aIVFoEEJ@BRSr&nr3RLF<`0a^Xo9{z48- z4uaC`B|&HATLPXr9&v*~NF>0VsqYO_;}#kf{keHja}M2%1(>MDe{$(HFLBQ_OSTmG zsw&2`$&U>h`Llzfh8&M8*R6Z?gt?4zP^RNcMA7s|fdbC>YYcZ)K452B`bV|y6#+{M9VkMg<{p?gyw&vtFxft@PrRRz=SZM96kkOJ(=J_Hv+j`#rZi!K%RP%CZB9&36|ItX34kuBG!?eoq)ou!wkLXX7 zDP6E(MK)PItSIj_RIo}10gJNGO+~y&rB%N){zF5L&A}Zy&rtu|nW8#bE8)UqdS6P&nFFTEjy~8qhZjS+?mI%YBtI|Q zA|6TOw?Ig1LQ zaN)`z&3|I2>o?3lK1lcx;;q|6s(sCxuh|F&w7a_jD<->A)5QIo_4I+n(f&hu#vtnn zy%M0;Hj**NVNV<5cLaj8#rt*D@Ev2=nZ>9~U*4|I@yN#fWFB$8zajf>?2qLzdx%P8 zkpyrFxO59(sY0*>Bnz22`Ati1o&u;sraur}Wng=uSt!Lap@!3mTiKs;4)L$)2DO;z zCwZasoB13*&P@=QZN>kgmEv?@HuM_*wg*=Vl^4;Vf56>+Zz9A-HAOqn-=br|A~oX* zeaIW!dEA~lqOTs_JoedC^p z{q8+wzSub_Zmu@$+)B(?AC^&;hKvCXNJ^NDU<|r9QL7Lq-XN{}DQVLG;&)5#I06hn zMPrHQ=R;916X4T~ap4ugJpV-Vx$HZSJIiYSu)L z#0A|6?jl>QXrc*+>Z^pP*Hu}Och5EimroSTL*deWbUP(MSenVGG^0uz6@4C`q&QrK zYkae?1|7y`Xct9?Xc=tE9)I%!_IG8guz9q^G_i)%U_VM=myo0L0WoPogD1-eQ1PgR zI;h^W(A?p3(Mh5x9AO3rM=1BJ@A~-l!;8S{8s^1-;tC4luU0xKtX|^R0`$pPSrkSH zD4dxMV?+g9d4dZ?903*dbO35VFzk-WUTGSErChi>lYkj%nt-Rdwn2YxscxCv9d&CH z7c3zxoy~(P4<8{70E$CA@l)D;hE6<6e)kta1i|1NB>jP0q<7q4{NX;t&Qac><&DOTvrtvsL#2efMFh1w7Gd)!(}I zRf2A;QzUrPQ)1T-to;}IKRItt-$}g}@2ZzXU(@O#BOu$^z<8;tgD@Wo;PrTJYlXe! zDbE8xm0>!tz#K&-l`m{ekO~Ogwtr6Eg<72694-_3kJ3d6P!*YWp=wl?K2P_&sJ+S< zdRTYW4f3Xm>O&t!Z=;_sHQELhG&XDisx?}Si)z-NKi@7eZ{F9tEx5UGsDAJdC{H8o zmqFUNoI8YE2pG4yy3}}T3S|O2VF3-|{?W#v_1WzgJ<;Ev7&_Q7m+^yap_+?cyBLC` ziMJrD+kFAm@L&7{5wWlj!(^i~2w9AGcBaO%?|xXpd%x5wik0f`YQcLLte+7sJ=N))d$ zwhyj@pCp3!BB{rW`xK61&JrZ#)z@{R-xF@{8t+!KVTupI>h+MsGw5d5t!741yoWx(+UkZl=pPs(f2EdK$yj$5rjk z+(^=gD)sAy{Uql4he8OHLw_8p^P(N1U z{)QF4oHYd+DJfI5KShF5vtA`#iT~;vR;U?5!o+MbN=zIrak_Nsr7^5z;^usSNlC_L zD?B{2Wj?2%GxVqp1G4L7u=lTM0g{0oEoY+Oj7K`SvGK;O%;fDcT9xY-RUG5?uSJL5 zKgwNP$pt$b;*TZP%wJ#o)RTEi>RrL3V;1O9#H`#y{ z4cF5!Pk2Zp{OdDn5$up(j+5_3weoP73SNFk#YnLv))*9*+wBkO$=4MN8&E8m3Av-L z9X$5KgkQ(VvkVNBi3&B~%$CV9&pmh3N}A2F%O=ag$;i4x z0xa)CbamoPY!#wY6{$K_A+P-rGMkzRP_)$=a*F_4hj{)PU%oiF=>Jc*p2? z?uKkL#|l0F%>QBLRCuzeL1WXF0hnx$Jg1mI`@IEm_R)?$R3u=Nmu0wyCFu&RAqX+a zuHSP;N2df)Cu_`@E}c=X`C@cvz^;7jPhQ9r^vO5!3O47Fs+JW^j>{F%R5kNToZ`wE zx9Vd`kRX=z7_^JE{$;O?b!B^J-$p8;CQMdj7ytcYJ@|F?)gmSju8P@}=CNtZhDW=N zR}5^!8PKWWD`O)-2nXZM*h6QXIsRst2Xpsio)#H6X4mo(;fdtqqf5wVV0{TYPmsDW z13e#RQnGHCRbMB4--+TkmX9so&B?j4UFno(?wrT}2dJV|7ZUID6A9jk7v_ZlkU^3=`f6-%f98L*n} z=FzyHCfkOZLJm)R^f#LW}%HTa}!rrY*hgWr` zJVIkRPqwmhSl7n|H6IG`_xr{E0m*!&Ot?o!HXs$R8c5QK<|y*fQ6XNTF4r!;*x0F8 z&Y5Z+@o{7_>NF<#S0tO`{=sDnh1Ska{AX;Eet||MoZqMpPwk#KG9b1vU!{$5NZYv{ z>Ns#j5L^Rl6zNCs7X@D48-oW`QDnb+Cc2so(ziMI2Ocf#7m?zF@IQZ*gXpxP6T7dR6Xy9rI~oia@xk&#Uis@l(}|3rjCgbWXZ`9p4UiqN&eV6wbIYVX+@GNa4@?1Ng~mXzk{B=KToo64pK9D0 zdO+PkVoGR{!{3kjY;p+cq7&$E3M?BPBs>e%% z``|@6hH0(iW}s*1BRtv8@orlK-P*bfQMTCONW?F~)8@rW)x1723c;S3L&O(fcz{Q= z)dcJJjBiY-d^@l#Jexw~2<=HPd+e5R@)VzN6b6X#5r}&G_|?AX-@<|NLFP#6g8k)h zrdRGLlUIm~1Pi-jkOBb;{1=K$u~#hbj}h(6!F-kPK|kO4}I+3ca zO;(a!acOas5lV<4Xrkpr~ZN=aQN?(U8qe-3m-`cS#u z2xJa=xTTjRJm3oWF8*i3O_wpX1UKorb~#a8s9LpyDrThjlQ&!^kFB02Y;4qi&Bc%V zB8w=EuYO>%b!0j~v6iG7VE!PONHl=QpR5fo4=>l7E$)s}$+~q<@Ui0^uF#fZ4T?G$ zN^%Yw$EB$`^QH5GbGKLdiJpJU>`N+e2e4UmU^Qfj?9gl+MHI2JBJ}G3M66qQx2+PS z6bUs3#C`7D>@LW&s&m1fj z#fZEG)9>>{iH-%b@RLXje=-(@;_pMGKocuzidu2;s2Ko_0mc?wbnk0W)``tv+DG7# zm@R|Ak-Nktv;n0J|6!%-{bv{g|DOn#x+&4j1|Mr-o@!ZH%mx-)QF?enxV(G~BKyfexg6{o!P-DluD3)*R-MvQAP%*t2$~(KD!6+_q z>aqkT-9 zV0Z+gx%h*uguHSRmAw0w6sW8t#p^(dF&f>LH`(N?PN#vNGKI7XO{XtRY1! zM^sP;*_*FJo8U6CD+g`|Sr_{l6^ONcoq@9HY-G|4W&s4@lGJxxcbJ6ZZDIE<%(fK7 z9H-EtGlE*HjS%!t1;$gO7&L<}Cs1oewk1)?#j9+;QH_gce?F4MDk(VWMnS@zRct_I`U1@*?FY}6I zjshMY7A@hWK6m)--Gwi2=8q5}#^wU*!^D2vE=&0V;=9OA2L@9Y%+m|Tug?M zlQHurOC-$)ii*V%yKdl2^;rY8@X?mA!T5U!Bem@ZMgd^KQhb-&yvAu`Dm(44!MLpY z%o)&g)ULu#MKCRB*1>UbfJf|tGzbESA}d1Pf9_`XiBvSeuS*--anZi4Z3Wvmh`7DJ zmq9PbnnyRnBkEF>17$6$5%i@%{nbD63}NMewx7V?kz<{Y8x6s|LL45;?IZ7!=MZw$ z1p*|4A>5_560^Pv13nZVztm(xknZS~Pt8t}(UUyf0Ion3X+8$gL#@XwNcES|1cOt7 z)L8=894j;>tm1%9<|1>DS3YpJfEMQj%m zF`B8xk6Te&A#ai#1-U!}#&RaU_`4tM$hjch84EHzD|H*YAC|Px9|1ajyNogsR?L3Q z`4(6{FV`3yIyg^aT_FqJSaShMtC_a!lD*pmgKYx=XQGD}+Jo*dvFrjE?kKu&9?elt zCz#GQoRvUIrPN1)%oNPuveG*!?ri@ELMwJGbK=oA!uWposwM5%CJ!?mzyoPAKfN5T7=oRg-0e zYuo`sE;Hxu(XD}OI^eC$hd{@M)#gFgYdgz1si;;`oTHX>N7Z3~rLDFKSN~?KsQ0BX z)DN^yzfxv@S2O+jMzQrPUV0)VfmGeP|E`(HelJ>I>XCiwdi%1dc!La71My98pN{ zxka!(hruqY=eReNj}m6P(!tR}S-~Y#BBG&{2YNgU4Ij5>(J33ec*5D?m#J|$28&er zu5uNAGtW-)hncY**}}>E;Xqzf$)`S^uwb|El@OWm=gnSWM32PMk@_7HtsY`z=|%Sz zAE31a#9IY~cBwJa>h16_hm|a~KV$BVi*WOgicT#>#d{94SqAsc)v zpgAcX#K%28Ii1sgolSkE#f`+=Kqw+u+bu^NOC)VTqf3#(0#0wY*>gMQbzr>ao@EDn zjRiwfc)WKk0O5PLE^x<7%4m$GBk`v(*oHA1cku$Z=c2DX^t!Ut2l~X8kt&w{+Zw9{c5fl=0BexvIlZAxO$HI7)?0+ok%l87MD4D)VDySgyBCOe z&{)=K6k~&BXcV0J)<0oM^4}D3a5vv&h{7@=6NSZMZa@6R&||*&w=q(oY4`RE_sW#n*{Lfj(eS& zk%<*zQZ17HYM|{b{GC;P7QQn6iJz~xH62%%*5C>aco<7=9L4s^y$ObnAp(`9O){(n zt|e+|*108-`!tF2L%c^@{2*hs}T&WwL_AaAqeWQ3K-rN0+K_p)Q z+1Z*Bi(Xi*&6v=Nz?#nOM#l8P$Yub4M&L$3bXyL*2zODHF8x=*<-?QKB{U zbe1aYJHyI$+G?iD*8w3R3(DmBU70_a#=anNhs7GWThH%ZXOLIk*E7y&zs$$ky>G{e8)QS`}l6TnAlv^^! z48+p8qN4AL+!;oceh8X;gs;oV`z{w8(cu9yytdiF`95vnzA5jy@>$7&oLDsf+!5Jj zzyY9Ro&(u({h%KXg{!E)HBu6jDFVW%aOx0kK|7PzYIIU=2zh+Y-LpyNXfH2e((}YI zIZ`d9Ip3@)CA!FB61>+&B?IbbOS?{Eb~EPd&r>xS6sA$_M66R27E2GI^)JxUrdIya zuwKqrvcnrgh%!c)j~i%x#GOX5`FrUUI+J+2LXz6Yt%iVx*csZ)%{Frcjv$IcBGTAJ z4%1n@He(NwZQ$q*O8^vB+hR{6_xlrHY0(o4F>3~`?-jcw&o&yF6qHH99PWMYd^ke- z{U1v`TBkWXCXm{%8|i?~CbQ271sI99Q1>hLEK99)Y)Y!Yj+jhlJvP(gL}*h2ebU)IAHUXOO@`FlZE!1iD5!5p|Kh0V^NXM-{QWc+wDf?ISGnY!^fHOeVy#zo+M6{ zTjp;MRx-X^F3b~k%u?l4n9aL=YM;m<1v(fZCePAAHalFgKexfz+)e}+F@FvviRP3k z1RfLV?2;1v)v*YO)$33w(Lz&lQX`u3U^mHRw5c5=wVk{@ed%hQ{Bi!K^)Ib`_D-|H zmx6*BeIh`ytK6Q zfIPc#D%OTnNi0*lo=Ke2Y$9kV0~`ugv1SB&+W62bsS-<=F@xy4=#CYz=V%9Q?_P4a zNms4Bl|2#V>0zH=r4XZrJ6rlH~5sWR;q79wt0-x)MlkK zhwBz`Xuzzg-0KPLUVxY`86Ecy!#L_D{oSI`N*9(oYb;Tz9?ZbSS9Bz{Y$1xJ!C!of zRS=mYYBGX=+u=L;!gnd5b~5v&i}n-(?0ED!bU1`%el!=;+KZLlU8c~yzKrQc2OLg{ zb=EQqXKOWWeD-SOPh@o_$>9{~vxAC7*G&5dJAzIN8^4m4H;W*cFixXaMsxWugvpYI zlYjqQ{Tp}No!W|mdXQE4Jat|`Y$MtlF;rbms3EE=R^_1@Wf92(8kX^M#(4c2WvGHJ zF4qSZvaCj01j)^rixC7Cqbab8GyP+s2`$jbk)cS|k2d!DM+WSLHv@d&V1N6ygbU0( z?)m=SU@V}hU@lBQ39o%kE`V7PuvF#TZ^omo6v~9xws<^_#CwK}o^}h~pa5(vDFAWr z&Z=CIX!(f$=WXpUJ${*@ZXK&5jDfnA+JS9G9?3pKo33Y?scV^MOwJ96i}Xt~xh$RJVlc7lENoSt&{s?}g>Svd{@u#t>1S#?Q zxF$b#5i|+Jx7iiEzg=T{d$$PZFSE%(PzNg;mnu090;o7sdi}R1$AYzuc{T8({>}#_ z@bs{<#Rt_y8{RH@;}!1iX>V#C<4&!FB4}}s(G~(9jqXcT;bB7#?p%VoxsA+l1OzHE(f}}!tOw2zPY$CXALkw1D5^00S5|=(uVtuqZ(MZR1U*ja=L(5S%)WnSkgubX6>p{N6&+Wr1M8VedHuw z^`-yWFKya;5e+j5hL!x?!VWAhMM|I(P5VwIQ==agz=Bw2*tM#dQ2pYGqJZ2*c^IoV zEsy1!>Ow#_un1PATHh3kp2%5_(E#crU3=O{IpbsOE|*t;{5edISkT3w9EtW!C_ z<(9q-*g|{==q~9+Nh-A&nBCd}#<3Iq-xsgHyDS1Rz1q*F;&lrZ2dtq@({N#4d?MP~ ze-Ru`!32gasxVuSyh+eBl0>Ek>io`T<%4{@Fi{Xb#JDj%s}@IwJ)@gnz; zw08&$!8by~1Cy{niqxh@bTW0;4gAUn{ygM9Uw)M%d;KdCisr8Vvb1ud0X-aHwuWBw zjq-F*h$xgK<5{06MwaU5lJpN7ArVBLYcZ|@vTHkpnF29oLbH7KexeSA(bs(jkzbQO z`H?%;4QJsD>QXOT{Y9{R&!Ld>=T>$S+Z$VszH-p=o6>um81ZEI+2ksb%?iPy`(U^( zbr9Z7ASs|*wT)lV?~@-;pAv7TNRf|#m(A&DcREraVlkpXekGsPcvYr|T4{&HTFJHM z={1!=47#zz{Gr-NZ4+dXW4dL!+!-_{Boik`Awu4^2j-guCCcGJkXwSjhmQn z8&6{!bPM4iBn-K}y;iw3f}~R^ka2r*Ta?3Wx1T3t@jlj=Xk~YAhsDW%8t@9JO4F@1 zlzVT*6Zbj$xr7S7qqJYN<%lBhwk&OWRSdkXeGfLzyni^B<9uW|4_IV*#IE1LKW=v5 z-2pjx6noF7*gT3NDSmDh4 zsT*(<25c)U+?E+a0xi#+@lJ`8(&+qHR zws1NNRRaYwzK7(>nh)%x#x1g7F{*#lW(I{bm6N>mPVaOTZp#Ob5WIok&vdIzu*xlR zPXF$am+cH@=$V3-)*nuk6pE^c;+fhhRmUG9yjK~|H7?AEoEKLq?qmxvE@bpSrx7ON-CTNOkPI!%pU1kw7`r*Y%%|b z#r<{X11inkKV%c*k`3u``jw@DMSe)}Ju&Z*S*~&5024~; zvz)v|N!a`>G-bwR?7SU_Bd~FmhmnR6xU9PgQC94mgefHCtbJ-nPD{`BN#i}HD%(N~ z=)xf9-iuhGiJQS=k-UE0oim;>o7M1;#la`@mPu|H4;+=ZxF^#i$UxnLtv7do0frvS z@SK1S8^dS1i?TUNP_2hhiHMgV1UCJx&C;1cIOxJw49ijtwMN_we8>s`GA$xRn3ktZ zYis8Q+?faZiuOtk?ied{X?5|Lj$6V^@Dua z{AhL&=TiNNwXh}!m4DkU^dnr?8=>8%UD~nX-z3mj!n$XcUPJaTF~H{lWe;sj&mgYa zuobsg8tBM`i*~KH`f5J;eYYezK^s>D87~#u1yF}Hy{xVG8~D;}FXX@80fP&hd=p^$ zmQcWpAW$GIm?99i;ql=q7$)P18vxocnq(_Yf5=;=+6W^h>gQk9lSpl46Td-EX{(Ix zbJ`zt?=9aq`lP-k7mltUME3{w>L5E4sYq?Ube2IZnTW} z>csNx}M0~S0uq1 z8-LBc`_*8|t5Q_jokbZJTNZ~aA%SEdX2^zT;)}@dE+&5gqCW#$YNT`76K!zMO`TE% zSCe{H3xiM`s)TN>Iw(cu#|$d1fdX?HOohF&F|Yet7dB1G+BJ1E0t|u4|0$6Dk>)>Qx?{^9H2VD}rIMw*yrjq{l4ENB zomOWwUOZ=%sdhF?K@0jorU>;3S$wwU;7t0Ib9sj{Ej~fOFtk>GzN2qnJ?WTDObT`- z`JZ}^&@F9%A>(~>G-e^&HQ^f&XW#6}@tv25B2BBJTO|cy4mm-w+GM>VsY^}&Zp-Q% ze2UlN=ej zl*%)Ohy$DnU5efZi1X!rD}YdJ&GRdzBtQ1U5EwFQ)|yNULS8Oxhup(Nm9zypq-fng zEYpC~hwv$TUase&Sk?_Wr6)ff#o07Q<5w}2o$k{`#$9)vNQOh2e|+`F4@RBS(;bQ^Wot_*%sU{p{dv3jl+GJ8wd?}QpzxC(NN)l^}&jfO7AQT`&HJT5xjSN5Q)@=^nnwydgw% zUYCS*$-OXZGgplN&>Y?{8h`$wVeHpv_i{^f#~@}>?j=M8oT?0`TVg3>-i`wfL+9t^ z*e^oT5U~%o_$grM7H55^eI#!$d0^%Y_alXenrDK-!ISkNvUl@s65+QVu04W@&n0vN z=Ry4(`23PGYHs7#R>)9bnSYwW>QEZ+sM&o2Cf0`cm7Z)2%(`zck(H(NDa<3nx@SIm z5s##rWlSE~j0%$?>u|M7^bx60h=zLzW@MVJ2{Ozv7rh$`wsAj?_gX~ArPsank?%}l zM{bMu)?hJc#NS_R)cDpiq)ITLtuN3erdx{B@L5wRsQJHr^B6p?3(j-wT9Q#7*%`hl z{dL5S3ZE?DKOHcJyQdj8M|KA?n_C3BnH&d(dB?>HlZ~{aV|`QntMK&_nU~6r(hB>%fpTN1&2) z`6(uQ=#XQV*yz4Kt0SaN-+jWl|JAer=_#A)?9=IAdw*2piG!RA9~Ft|RfiXJR`z}! zHPt-i2?R4?sSh2gghM}s^=kn zV5r2~plC_S&rA8A(njBp5EQ<+(PgklCC(Le zeZh$eBBeLp4lXyUp1PY<#%&VJX&hZ-wP#Qg@~`JQ_GY2{%^I zUF`EabrU^$`sq8Sz`C7j=onCbJ{2p5TPbaTH%N(Y4POW^*f*H0;Ms_$1O8E{(HOfUC!V_pyd!j0m#yzohM z@MMo5RFjf+oD3K&p3QH(!gWhj8QVLQB#FvJa1myiThS8s6=QOHvXO<-cAe5r0>4+` zTF6;dKwno>z;4VRR}oOcfMQM-a86A_I0DWWx~SOPDxa_E)YgJ@W1Fd|QIH2gdD^a? zJhe4x-IWpftmw_TsXv#oR%vdG?Rb@yR5MEKg6_+F}B$Rngg*k9p4Zfb27f5Wtvu?K5u%-MNiBtm$Zs5611iQyH z$x)m1v{_?HZY;*As%YXM!bhFtr$nPuCR4f*E1elOQ3S**k%FQ@MZaIu{0T_=yCLqJOY$#|CIT__1`9y$LVMaa`dQS=4rvw=puteGj zgwSlQQgw`Y4=&GdI-CK6g4AI=_8gq!kljU+RDR@}4VQ-pwM3>%3-FCHI`8GVe*wH0 z9U(D2my^A*MDLIe9r+~eYfK@T1nKw;MTa(HWWojxjz9AVf|7(3gGPCEzLpM#Dq1Zt zh^hITINKmN6JeqXeVbykbh!wAn-kx}T8|kbb2Fehx#@Wu!d0uuqVd+$h!3^4`@AS$ zfb+smwM4B-+%#$^EMjy=voV6)GDA9zzw`vO;JE>Ztuh zd2Xtn+v{Hg2k`FMLfH6o+80>4-U4=^S@7=U`?$0UPqGcuzBz?!H#p!Cr8VgTcY=Oh z7%;TniiG$ER^=q^2j1TgP!w(niuZBe46(a+#ZYYwWYb$t0ss%J-GLyo_=8NCvp+J# zSW@Hfk6wU^f3|plc5QR(Eurd0zbv`5fyM3Z^VEcKc-^Wc5G8J}sRF&YjJV~dEEA(~ z2|cH~ix=Z1wq!|ST1e?xrW@B1xfU6-E&;BMa9RMVh4vWw&!pt(pSh9MV?XMQckmy% zuQFo3Py=u?Pw?`jW15y-7da=bL0;Qx)Ucno3vEw-v=LwUwz!$_dpeK`_p*oaK)PWe z!esQ+liUj}Q&qps}kRA@|NSD z0H~jA;zmNMkeF#m1@7oyY}yYyLQnd{&+$V*g5C<_#}Nj$!B{1T z1Em7Q)q@)u^Y%8H-14aWfJslsszsDZKA41JRXra7K|sF0hK$UvR=-ZwEh?c+QS@p>I2HvncC(~i*;bK|4|`T9G?fz=IgGgbBc0`vXYlvT_F0)8+x zL}`G&^#ksAVI#rwwUBI6(*}5MGAh{YwtuP13*DN&EQ#SEQ(}P7F3MxTw*0P+I@Kyq zY5|KS38lCh9Bm@Y0>cO$n)E{bl`z&|FJVR|y{}}k2iO^$y0MTws&5038_6}xonDnz zF!(l*7Q=F!V8i|LfPZg6Hl;t8tHtn;XH!F6iH1OiNYU36Kg*_#$$A=WHqJ7V(@oLo z9|Sl5Hq%C4%(Y{X1p^)?VW_GM9#9|9mip4 zG+yjI5XsTI8X4mX%q|M^(g%9r}!#`F|MP!J0>I`YdYtmA+{;|0t zjg|#EVjc>3b??}G2Fxm0-de?S} zskI6E$irrT!xxAZ{>pH^3H)o$MK5LU7Ev^0Z_aui!pr zY|YA)Y~&vr7oPiZ$EP-9mYzM~5LWqC2ZQ1`UCy`?0Cn^?`;JydPosqlWZOLgJpk3s z0^o9qA5`^5uLBl+y^BNytq-ne4MyTEnpB2oAZ#;p;J(3SlFAkQKi)h3B!|oX;xp&| zjO;hnD!KN3V7CK|Q}{f4iWUstb-5pyAW5_sx{`GmzVs5DTxVL*tW1Zk2QBr7QEjgzn-C^-=i8v7l@Wi(ZnKo@fFR?g@Xq)2l>O)bl-obbb^j&w4Ht4G0a>gQe88 zRyI<{N@ZqKoh^DuDPHd@dkYaFECzt zY5njQsAm}DL1WuIji22R;Ob8}<*Fwq3l@%<87rsVm;_`hl+8uAh^Ga+_}qe=!VLDN zmo8{xt6Oz?Cl#aGHd?!%JoY4US9gHvLR4rGHcnjddHV+E+OXIa78oT>WgRFFmGAj_ zagXYYaPZ1zDIeuM*Yg*(RF2iRBh4~otc6TsWAn~`W)^fYSOEFQ0!S=TYYUJ8Q;KP; z9w+%Cp+2(tJPSxVvTt4xuy2XMN`2Nr&j86+fV?37ef~x@(?s9cy_K z`8X6)wan0rQpCEc;?}cgnLFu^)AuOOjVK=lA6d6Lchfn(WR5S2vmwA z0m{Z=x9%nNX_IKMu6xpo6=Np5sr;F;zO&kr#_Hti~aWH>AYd3TKaCnPjpO`s}RhT4}m!b2K?W z$eLb&?Ze|oFsSX?C|&dt09!+2!yZ;Wli!J23EmC63Z3p(U3a*ayeIXOq`g-U&56z)y7k+iE|eiph?jlQPx zON7;p_C8*GmrQ-0(5wK^6cz8=l~pGiY8RmfusS7+6EfyGK3}%x;Iva9ZvCf$d4Up`znVj_{#g12Zbr1u~ZOIZ|4>qzrU^ zz>f5;6imVM40JhC1~@*fTVpuRrPPtaF6q&s4vowKI;&!nI;haya>j$69a@)opUF^D z|2EG}_tLa=M=@?6JJhQGq%1I@E!KZpYJA-oNAmh17W$k%g(AXbS~_=eqU@iSE4Tw3 z|1`x}bU1? z3$JnMnu#Fq46`dmBYW9pHb^2?l!La#ePJY1b8210O+R9-|Se9@%;G8c;j|w>$Z~9$@N*(F56&Q@flyp?}CA(Sf*Je_S zvUv0{It&KDA-)ygCm8AA@;-k9#p*Nx747?1lwk>C8FZqviZP!!VEBex;U2q)sCE8w z_Vt-%U3ceMmBT;NNb^P&b7z-*5ca-0u1ezX=7ZV4!1os3E)T>s00LO+hOnwwJos7A zSw=M*7EQwI_{pR|h%z*u1%?hx+0AX#G-3Hy+@82gKG>u)US0ifSeRx!kV@)47sGjN)_kJw-M% zP>=GpLLu)B;}nyTrm9zgybDvpR#WzyShFFBrs(vGS%SMR@ot&=B%Sp$>>i}v%z89I zpf*p-M@s+Hwf^_Kr=wwPc|FB^ecRk6KwLS-1T%CXkQQ4Z$MUkdB*0y;SbI6o2<*_(l0M;x6l1<)a}g(K zz*y5Np%o~_%)#17C4c#5Vq?$C&?X*m#>Q1^MV+z9+@KsipW za!NBjuG(=#Go|7!%?1B?p?D7wmr{e6LBO=dYQl=-3n}wAo@oDwYQ9L*AC45tNJd~Q zl8#kQjfgD6Sphi|;>_Uy-l#(+F|FkSMR&N?ZiF5VZIF8R35X5vx}d&{DR_=@mn2Cy zIHQk?stW^SKS0Fg_Rz{55;P>=$;)TUb^ZR*HL}a3F`nuC3VptU)UTShy$` zj%nuS(!)C57j+5-D%x7LSTuk`iE=0O&NU425cX=g2mUUu?>F;jAL_Tb)nE)&i>Z=4 zjL@<)HzO)8SYB@*hi>9Bs@#&@AVecElX--%BdXvEzR#Y&Rvm{99Y%^JHI*Mx_{;}R z>L5X!!U)%qHB++l7VjT61jUx%GH3M~B+@F3^>Uz_Iwz^)9+$6R$(umukQbc3C>o|E zxYS%oC#0LzcpkDk;G-E6_(xS971chF+922huaU1Mfo(6Y1_?fMS=RvU9oytpg~YOa z?YGm>Qa7F>z*ZN741EWOH~RpjEmM9!2SX0*V#lWb>-!AUh$bm)gP)e*&Yw-kXH2so zoC(0YBxsQV4+rU26ac!XW|>T2`qHX{77c*`6*|z@7d7JBF0dCdKu1@uEj1W2&yB1P zlMh%wWB3mVu`;?an>Sfta;4cU!}XLJDzLgn2fbt3F1;|Rs*v*(6a%> zX8JVJ`NRG=?SSy~-T9Z{@d_`zn&TARW$yY|V-Z8okn2+E{9AxGPL1tsI(HiqHq$5V z8`^a<1AG=cAOHU>>02&<18y{hU!Dh~wQF+U$0}2-0@#YK6WK)<#1Rw82nkT6R(2G7 zilWrz=FVyy7I_BT0P*1?AZ36M{8(0CVzx zNwntxUjVsft8sUDijYO7&N}<)nSl1WLS<@7n&dM+uYVQGSVgd_t&PZ@g=hybALXn* zM<|G>9gojrLZp}FX>Z_6dqb_v0iD-qYi`;!T+L}%L78)r`d zj=ZkeV*~KpeXSiJGHu(pn=B=z4BWC|4g#7Hnt=pP$Mk_mjYKQA1peM10Ka#SY%gb` zT!WO)6N@T2zQ}Y{99y<-S?gRiYnE?^pqs;fzNTwo*rwTuE8 z3ck&Aeo>=%URcE0ehzb1cPL z*Zq=o__Qut!z^Rb zVQ01vhk;vndnvn^YJH>6`gmshTBo{z{14(ykja7KsGa#T$NY>F(7nL$;#oBP)3?c6 zN}f@8^ZiR)gryP?OI*${s%W9j?vjK=`Kry`je)*g$v<^yhW~XmhR4-yle7Y@p*2>g zU3-~&q-U5Pc3uI4t@8ZDIX2_K(V=sgCMoT&IYusBr~_3{e8@?LRyc6umpDz(e8(eX zBzkB6HSCz#=wHvc0CzT;PPVwK*8X%IBi?-S7bzugT&;Q5U5~R~76HE3acUmGG-XXiZnJ(oWLwPIf z{}OA#WtOutSGxS`D%XV_3Oeb=-G;=FGwJUYQWrrUOSLFlb=&bmo-&jj!R7beum2h1 z{0rkA!qeh}>+H5f_|MIKC9Oho*?8SU%hT)W1dklAcfj}vN%x_Ls>!S>rXLekXjY6Q zYQZ96Ku>nsd^zaR%vAq{-rk}`mN<+UMhm7nrcS&(CY?%%JBl@{xUJfs;tM+z)TLD4A?r%*3hX@>mT%V z9BdP>eLBKhXA1wbA$i>m2pKK}10tEBQV=IL_w~WW1@SXVht$!tP1%o^dM2+yecJm& zMJ*=DYrx+Ng8_9Jw5sx3{7qVIHtOiHuf%_gstl<%7bK-@<>>1+$?&U*^nRfH(`hzG z3DZFjnkPD^fdEW5xPFM28(<8y7hv!=e4e?+jSJ;p8z*|m5Jo7vAaojG@Bi1?@7ra- z0?!x2h*m#o(azOM2I$oG73#4uI}ZsqOfQL zt*u=(#+Zns^IeS^?EWhX)sj(U^WtZ+y9J}7&q4St(~}w!Z|)Ac?)826#F-8*!g|%-T%`Cn0c!?@^p_PX}7iE z`fJv{=E^511c3-Z7sKYA2v7K$zRW@GmkXI^x<^At>}J>nbDWM)*mMbW#7r+zr?gJ? zP09am49^XZKuDl?YQp+~>e$yjE|U$hEftNR5dKi&4fb2HqzlOginlM~k4y{sf^M}( zF%-jqm4-$n1n#Zy{GjTSjoh_`nJKy45|f;gn|mGj+{jTXlX#7e-(7j4kRpF8rw$#D zV+6--SbrL)$&UB@%xLF=`Bj)l88-o8xq;iVCmjmyCek=sn`N7^Q@=%I8}Y{Y8C*1r zBzrpctJ5Z9AVpi-ck({2IjatKwx8CffV4KH$3l-R#aYQ|BQ}ZQKLdQG{411!K(&qO z$eMvLpz}iB#*!c=MRgHaBDUcvgP)s*sj!Lx(B%nx>EpoSqz1Ou*)8DuG7W0IoAfWJ zl2cF%VTNJ_MWqnmQbB-|1S*Ph0LqU`0oU^YwW8N?qFk{_g^w97mhOE=C#yNg4ClN| zjWBiaVinypLJMKf#lK*gklOg-oh)LdC^`CT|CeOd{X?iHc&~LOxYL{3r)2@`-S4V; z^;5GAFQdz5>V`MEKP~#@1Utp;E(9mhpyFx%e&6EO1Dww>-_qhg%TlAGk?;^)R<;3s zCTI~o9+mNQ_eJPTZX||iB8yvi;P39ro7VnHVHGYRrv+(yayCpYovHMRbWvX_10-YA zqD)e4d|Z_2t~ZF)M(5`WoHzLxcGJy}OK9l6HGY^Ngz!+N@|2qF)N{&bLXI=;Q<#%& zL^~{|{iM!&3M#O8{1ERoI|Z`LWYtw4GyAFj|@A#~q z{VQ|dJN>t8098gBF*MDi@AKQSE?0W>+b=3%M{Oc0laYc%O3Y<8f635k^o2WgSR5AN z^xae70G5)rA2LMYWalpZPbXhfa@UA2>chBtxQx36GH(QSq%!`4-3jg_j>B7)zdC)i zjXydVIwkH>*v}hIoyixJtPCA;CC}U z?27Twa1rMD(-S3*7gL9-)K0)8>I+eA8|Znf0F6quHi$0kPT~UQq1kj#Q)h$S61b0ENZ>(_ zrm|cdQ_UioH)S|Z+$-*^$qTskdL~UIyn@N<61zQzS2MIgyG5ucWVvT61 z&8xV?Q^s+dsps5KCS>Ss^#KZgSjiL~Iy39=6ZNi<2FY^s@wJR@tb50avUeFNPBx>Y zDI$+IVK_s%gZaLNeU>ZQfY8`f=-?;JYxpk_Vz zZ_X{zqc#7(0VZ`a`s!3XIE6i=a*j0cK{T2($FH89B&P)3IBIn-1&@ z$ku23qxrlBb#4YgieHl`p{|Q{IGC&+=G$BOUb#SuED7TCAqa(ae6c+Qo|@SWj8^4KjU*Be^<-q(P?Z5mlPw=mj z<`48e?B@eunVUMps_qF12`$shiR~XFkSVE2Sr^(9oE9ASQ^R;(dXWd3X zUGfUOwA5(b!WuB4<(R6p3gpR7t#5y{8?Bo*3gm&+f8dwQPhle9`9EazSrno_{TJVZ zw1jZTNtGr}(dxiuN_%`tY@UPQ5q4sxD9|cn@AM(o> zGFg!x?9ZgfND}j$wGx*KFDem5g^s^Nf#xNF<-)4!N>pV^T+YmAj&I6&SJ2rWi9>)I z7bIA;PBxfDNoWQvCAG^KaB1{RPmLbTY*+XI0~=xB{dxSHJv}x@{2-g$tiTxt4UJ{M z%rC#su(g5Y?^}UT-YZJdB8F(jVC)v|s*??n?ueHcRJTq%t^OJn?|l@JLWKN^>nBR} zbDK4%6X@g5cz3J!zi{vgOL74j%uuY1Pv2=V4wpSLe4?~Z2GaIuNnS~8dHiHKWMWfw zutPYZJ(uMqJzIi|XSvLI%!=`vQG?>RiC7H(Qu zS_6Z<0oG=emg**jOHVpB5Xzxf;+;?vqMEa)MsUk-nEd5+hvM)}qZh@f{F0ZfI0_Y9 z!(74tJNHng(q!v|LyN8Tu%KBxZ_2Z2(C^dXdao7jj+iSZvL{tVka-CUO+iG zI=K_~IVbF){=X6H!v!flQTjGm->FW) z^d|Cp8tfvM&&KBMmEv2F_*HoSJa2Te*`$dUKxKUiesf-M{;?rZ5e!sFLicA2T<{k} z6=Xb5YG5X1*uWh5J@UTH;x(2~)sy*pQLq_0@7SHvv#(Iz_zB@QIHCD9VWxeDm)M*0 zi{mxLZ;{^0&7jzticDPV_>E0+!;39E=OnBG3H^2FRoBQ{u_=+bm|UC_xitQ!7h6DCaY1`+Ch~1!1sLNPK>%` zAeQZzZoBmN=*1HVbZ?;QWEJKMB0=luvq|N2!h4;A3hi#)n$ybo%M)uVUJeK(#M*Qx z5H8jQ!4>-bLx4pd+m?33tAl5J;H9^Nll~D%dVJs8j4~U-dpe6l^$VjnVcm0Ma9K;P zS#CCkSp?e#tO0CNUO+1hei?*AMW`$guIx=shDAo*6J_h35K32`@m^Q*#j+!0@c6Xh zJSUIB5?&82st3Vn`IpkYS$pN2h@*}5&lR8`TKmpTO}K$mi5v43lk6;4yz0fU1(adp zF$*J&i4jBZP+)4bRdNw-!UDhy zVjG0Al)BAm5;I;qxhQ3Bvo!PHwM$fu&4dyvO>`o2LocqBw=L z2ww7mz=M2z8_hT<)cS(BJ{=Ehn{Ik+1VSrGUcs^3JHE5wbNQsSY%)Qr8qzBr1r<^L z(}y0hu26(=%U3wvo!*hghTyl5<*s1e7}pr$5}Lp1NT&QTC~nr&-((uq5_E}uHx-QZ zPRY;bbL3#lY+ZYHt;b7T_N+=eFj79^q-~F^G(xCwv)07m2}`Q^50!A>B_PU3CkvfyO)U6vtA^su0CzIR00)fhpCqOJy zAvodiPgd&ZdzWz4EIREb$`njB^7kWa+jowc9Xu3|SS~8VcNk73(HaDuiqr8Bym)8Q zxNZV$a};AEBvv+cqm0^~j{BJ8#&tXfL~ALtt*P;YVY!;mxr>Wu!Mj)>gMlg3Aj?x%pAjGdW+q>pf5j0UUq?eMA= zgVrTdN=~YeSqy849MI@Cx_H>+Qa$^P^cC*-O0>NVspfAGDAL=>&Tspy@2e(bNB5jg% zPZG5a8}Kb`p>tV3Y1MVTsxbg(5{j7*{>d~!5vrM{z=hV!;1`4+C?yL%hU%_d9<0ul z^%2PRJ+^Y+sKa5A$%t-=3Fe2%Sd63<>R0v`=idfa+CkqHICD_%1Si@;9VcDja2e&aC`^+jI!?g4p;_vg>AFI*FRWe(M{8{jVno(;4GV4wmZN`m1{_T;6e z%ni{hJ55tUf!P9~OaPY@JkqsiLH>A8Fi89zM4duW#n`u(g%z*$m*|ha2IZtrqz4A( zMe%XC$y*_5ou{96QD4J&gVr2?VNDg2b|z#oebIhqxbuR3(!VGcuum6fj5&eBaxg~w zuIWWlIOX(`t}+ot6cQVxwjOax|Mrz3yRg@98b5xUBqu@(kqMp#JK$$c5R?aq?bCz~ zH)|FnRTByEWfvoy&Tzr-Sn>`~q#AVEaWfJxKO{ttO#ff)QWb zKF_@##8j+vSBYyi%;TgLjqn0&r~(RNJ%*7N@K^jQMBiOjm;kpCb$i5e6&2~Vq|#CnU zmeH6br}7i>8Zml2x)wXPdSk;M_Uef`(8m}2a9w<|ODTv(jmy0OHI0XjlMf3WWyqKR zS&|q{!TNFO29wd$-eWS4>vuhP!dH0e>h6d=E|WuDocqnocpYK&0#tOS$4wx+UOF9I zEobZCy>0Je48XrVzbdmUMArCHBF~@ZawU0&w&@4T6JZT3b3eomUjBy!n@5*2(vJ$m z{Nd_WRHXk?@cm6&d8k@P3%6vLr;)UAyx4nBBkgG^(Q*v9rxB7su3xGyy0j6!!plJI z>9)*)3`a7VBIVUV0xEC6C@c+fdhYGeL^ioL|l^4 z;fm8v4^$`?IrZd;)B1pRbiWBFBtDGl!D%GaY}q`zYg4XUf!d&M(eB z6S)vsza3tzF~UIPb|zV0EjVq-=r(i&sE)4GUy50<5p5N$&2ps*&S0*z!!MD{(b8x= zIoX2xo4CoPN-$wDaA|BXn;?;ueH%F;=Tw=4_l+?YD}2W=q@wKY3rsbXa+2G*ScQYB z7k7s_C-R6*rZQqqx_WB{fy$$(cgfYK$!?l|+Sn87kYgjN`%hdHIt2W_7*G;770;>Q z@jBF2y1moC_>AW)TK>>q9*l^KJmifEPTl> zZjrd@$Kg~VF3YV8Pk7+9a9#}n*KU-Hv{Co`jI^FK5(Yv2wnqx>BwIFcqNSX9<=}^f z0aE^^UUvuzppNCP2QK+Ok}jnu!!gKW4LVHmv!b5JaEBT#u#(4hQ4yqgl?&BMXnnlO zo$9`a1>HT2RN=dja#$B`==Q(y>xmJ0;bb_vPuO-C9^ z9l3b650nmZ0VS2%zrJXcI9JF@#M*v~%YDq~i!86tp^OMj0GExtkVz9}+(;b>(9%Y= zpP*ZjR<5?g#l_H{7a$)aC1SzOI03upQdM~J+#kf9aY66! zc+T~NNvGbD&3jzmCjOhc2b7rR8=>;-*@2FTlF1Ga$(^ic&lzZ96v~e-$1mtv483ji z)7M&Ag{jI3Aen&DQBn7;gD6yWUaq3{DVg-99EKRhN>^i;=i<+^Zxp4uqN ze*?_49>06xilS#~QkMGBXu7amw0SVM%xm&!ETwd1KObw3$0z&O-mkr`;O5#{O8;ef zv3&`9;j@`IS1(?W1Aqr?it53yJJ6fZnnWlaE9+@WImqj*reew0Toxs#tngQ3p0oA$Lx|0s$-hQeXtcM<+y=~R3d#c@2j?fFH3uyv! zWj5@Zp-wok&n+d3wjJtT4N6c8WdSR6+w8=4V|3c`Y1htI4f2~D_5TtbZdYQSWVx$_ z7~1ep)b%z&4O1~=DPV(hyG&%$M6F9!Y-&1mer+{?H@ZC#c~5AWb5}{E!5RBe{fybt zDXW)vvxJw1v5YfRT`mkkc0na-XU=6Zw0 z?&u&%RnlcuIME!H-r$x1se zA}aYaK%FLZH^k{=Nb2wHUF_CMDoMgDE>jj7YmWC zJ=mIK5(i`e>ZPeT`9wwBYAki^op$Rqb`~l69S&8pkJ9SC16fuWLfd5Do@=tJT z9|G&nA#tm0F9G}dV&Yv!(TIQ8Ycyyf<`Fgt@J)9b2f!v#wv>HM=g#rge&O}Z=AgKF zS|RdOseqnyJ(#;Pv+Ix%Fm+Kc!=&a|sA-S8f!}Tpt&sRaiC>B{(X+qvf8BX#{;Q!S z3PagAT{O?Jav|U2)PPL^X3t{pK{j4l{rQB+WylhC1cskhwA*xrg+Lpw{7gW08tcIX`!eEQLob(rKYT#G?c?wsH4lvoe~qra9%j1 z&4&18z*VnpyY+s*vSMU63kXYq^0GIuZ1`fHJt2h!%j%}GK9(X6{Pzm_a9o?+FeXHs z790|v@EsgEGVX;S;Ueeo@}8Y6HCJPh$40d1@uM(n4p$iiZ#0c1^mKREsnC?p*L5e* z%7h+~xVpBm@qrpDLHbi3ygvc6+1#=;1yE@UySXQvB`Ig1e6fUUHN+;2vvpOZs>jpJ ze)L#9iQCE3+u1BCe989nfdrkgYUMD)H|BBBcRQM5cW2d+@>tN<#d!%~#rZZ8O+71Z z0o3vPUV31{TD|w;NacRm!uzu&Y9&1J!D+V4+Vi|@-s}Cojle+U*0Dku9RtxeSf;ZA=)C%^T|VuAgGp9 z075j1H-s95gQ{er+Fth?n>Kv`ja}R71t9l|jIXEeahfYCM`-#T#wE}EG;JPryHs=cLpHY z&-9ZJzGPeOM}Iuk0NI7h@5$Sd>5S#LnAkw-Yviny)hf3Ciam>{G4avs1a)IrDjs>C zGRyn zlH9T?90=}{x|49z9+fg%#ZAl*lh$-_E*LY4EdKc=GcDdQf5V_kXjQEDUM=4N^1v^y zE>KUGp-mmr^kF9Ih#xJV5(;r$-q+jDq+TJT#;X*ikizfuIE+)i-g^k0!ZFAwp_XyQbU0n1e-M+xGF3DEdQwo_9=T4j?>&0ei@fdR9_|wl8@m)D zWYK}gLvw^MOlT{?bA$uj?IycWRZTjP4;)NFqktu8&=8!eYWE=w;35xJzng}v;nyRF zZpx{_Azid}MU=)qM)7AKad02v#rmu!xm`kjRv#pRM41@c>Z}EZFE1q}A8X%TEbbHA zvaz3u81I6YTm>RcXfaULI3Ydyy;?2ktc+JZKtsL3;T^?#$*MvUnRrc z)^UWm#Npx5an>6gSqWG2gW8}j4FQZBH}?6gq{grV)Z>~L<|4`4Xn5m#ZZ=VB zOLuc8-nz^+g7vUZi2}m6-xQz;)N+QXyZ2B4;;X*CZO#+N>#oB6OWV*s%?C+MfO;jT zQX^&6+qu%PR@Li@qF0(5UM^-x*HO@hXm9cnNliX<2oLn#;4%X5EP z8Vzbo$I1?(sId4&<{d}c?~K@lgmv0&b#1)N(d%$76VuTlvSCwdcmFhRa~!}(V#Wa7 z(C+fs`8qJ&>-T2u$yE+gtKHhF%QVImK7e=uJzw3is^^o7&u81}Ts^A!WvVX*p|U_c zReSbd*Egpg97DpOnLV>l$S3>y$d1#jSWxN4)Hm$LP-^zWTL1nFQP*!uCK&9$dI`B* zYOf~-xTp9i9PLT(l1?h!lVdukN%dK7GUpuH2cdOvc>IDpfIuspZ`ZA02j{d4^y%)% z*iq^Lz^UcNU89FZ9isCn7?egq2Ji)*CjfAv-)mu+wKg5=m`JxCJPFTvxu2}VMjuY5 zv3ECHFvS)_h0i#33>rG#2u!8BA{!VzuI&@lz+$HHTFEiQpru?RNQnYbpE-O7=B$jy zTJ5-~!s+(I+Y@*gvK*CWx^wM~W{QSG5SWi+FEah|3qmNz+K5H3){6)DSSTYTk`j6IWA1x7= zk_;O(*t=X$^e5Mcx5`kInfoqBj>Yl%WsxAX>Db)FC`Nz}XK+2@m=N07s)*VWp?gB+ z$E$=2CUA{yI8qOsJ@j)m>F~r@4=1oe%S~2sHJaZ>_3j0@ccu z`Yj6?=z|5T`g|{Ny1C=g{hJc-k6L zZpg{k+CyR&eSAR1qbcFnPKv1Ic9z2*L0*0dQ`tWwxO6A|aK3OW(2)0jY}X!kL~t22 zmsnCyMbIl?YMOg1q4fj??X6XOmF57xs;VFdZQ=taL+kDx4*Siy1XHXdC46Tf+lr+; zpef2GZYH{`KA2kVv~79Y-D=xaDT@HNihGd&7fwxE?8`bgFzSjmLTz=g$iEVtsWu*MO=Gf zIfki2MX;*3<6-P^+rzap;_Lx4TVaI^fZA6rN^Rokd)rLQ6=U6_ux;~KB`*md=uv08LN#h$S`R@$r zIW;&^%dM5)#V4wr_RX%2juDfJszInSLYe*zyA} z=|Iz8z{lmdppdij92h_NGO5ZYn9=2!1>8vF<=u408@C%|XR53*o9oa1oowPrIRZf}Y5kwEu(-V5<1h zH2sczF>cWULbv`OIcDtv>+xjgcCd3Q9$R9LTtY~!q^J^I* zAhy3=X)}!m??n#7j)0$%TflWtGwLuP)*5FHn~GZ@`|iUX)g@GJj;L1^L@ntp^;K!tpVHx$4|A_L>FVFXzLVB~IB z@{?^vYKk)}S=3kurh3Pb(RB#as%~qUU=_oHD9Y>rQ_LC}Bj|rV@+Ktno_AOyK5s4p zQUvc8U6>?QuJzH>c3M4=7q_~NFK@~*`z35U23SehZvZTAW>oA9UKjU<*PABlO7g!Y zvqH2KG8Tn%(jmzZE9Z`){S4M;V1th1?+M_(1L4H^#L3e{uE)vA=}` z27TPu@DkYm1zICJNRb7-o!>zkq^0lZD(`Z@SD94o+K>{+mrW^B#AKIp5%p?x{S&eh zFl|7DxFX4S?WPAYo8_9LBb_vip2V;43L?Z669ZWOx7Yethr9iQ8IQ>tHPv@~#N?`2 zyuhCJ2fvOVDlv@ZgH2eL&#R*}CKk%)-z6u-$K)RcHMd=uOtgZ|ML_i(!m>vAgFOP~ z>t#rbmnHjn`K+@rj{XdLT(kCPY)eN$GG?JJOAE*86@s<#IBKh#$6 zl3&yC@NXT?XQ)s1OVFzHW0H_pl_-i~Nk#y&U+ii<*g}$QD}P|u5pg7Wl80d&#^%Dt zD57;0Ro_%-kvhp3UVJ^Z=1uS8-O}dBI^3dZvd4|&--Lx`G%%|@jxVSoC&aow8On=`KX{D)UjqqDnu%Kv!e42W7xhB3K$)?G7t z=Kw!Iz`s9_19|~8zKWcDTb{AJQ?vkRDZI(Lcq1LkL|*j zx>g>Ph&reudoCi8cOE8%pxSuI`3)Qd-Pqg5sVR9FuxqZb+wA<6WWw!D6A2;tsv77~ossf*me+45!S!j|aGc~cNJ#~1rD@*p z-mPuw;V}8mX{D-o^N$h!Z%$}~Gvqmn!D~?Fk2xtl@Iz05pSRK$ZecfK;@Zy^af?@2 z&A?!vpw3DEkaqG{54t;tbb_U^Rv3USVi10ADxD_Jkz0pCu(&9#AB*EYZE{N)crjJn zdo@&!p-3*p$A)`_^5%MX^=%5wg_#H1bC6-U7rA!HZDJeUp2hrm{#8%FgBs_vwl9?9{bR^}Z0ER0GU|9F)o` zs=>4{{Mkn(^U(WJ>7wLHP||;^-~=37x#s(pZS9ZA>|fdYs3+#~SpCmh{gdV^%S>Mw zSLI-xFWzIaLaJK=O#EId#UBbx;jqfRchUy}K~Zkh8{-!;jz~d=jzGY6vsXM{Nnfl0 z_IHj;3-^>#?6X%z6j7~1gX>8jS2Jd6JB<&)kkHJV(EQqk0XT}kszMF`>S(2e=gSC{ zPrWjXs}ZK<0Npq>zNyI_Jl(e=Ra}U$Q~21fw)|$&ZgG&(mjoZjnS}M9x1^=ul0{Pa zElpJUs%@;|y^a6~mXL1b)`5~F+y0*Ra0~q)15J+do83OK#R}b0H+EH8*nLn^@Yy7X z*zeUZ&2;T`3L1T?3k_B=OZV*k^rur;@8SKO?W;fVjkDthP4AJ`I(@z5k zw~K4s;tJUIV8#w2&q;Y-!f(k8BIk8%k-`Z zE}K|PcAMI*Z7{B>H8~2$G##;B*M004b5I=B_Xyr)btuo#jm&W{>w$8jQ-Z*jZF-a2 z4lhjBOJ*lIfe)r_+vMBj`L(?)|5Mleh44vF>4=mjU!^T<;+iOT#!iF*JN z1<~1tu%zH$QW?`FZ*y3G-f9%k6VWi(1JH$t6TGRLTzLU_Jwq~N51Vr~KDN8#Y4YXJ zBJlqcfg4kXt=vR2IC+M>76u*S>~cZT8=)38>%aFrqJ=>AciJEklMVI;=hEqS|?M1{y99eG;znv)bZ@iN}`XY^wb(w7ky&o>`=7gz} zip@SdwJQ0+4~|sD-+t%Pti0rRIZ~1n4(ABuz(@kO29tGMMeusFsWydT32TAQr?Kz1 z?GA%topEJFG5Ioqy^Vqt<;roeaMs7nL*h2biu}2r2Tk&HxOPePiJezT#&A+;;~Rtk zPK$H|Ef2Y+p_6_R@~Goz;acSg9ZY~{T7uXC&*Wwzk8rQk+DqtHTp?%=D>45~x_pN8xPlC@MH|qEPU{S#~>9wYfBE;jn2ldJ+8%Nm>Rh4(pprJ%6QSqpDnP`9R2 zqBnC~n_k#1er?{UI`zb_Tt$n1z&OUvyO_0$ShlA$CEwZPBd?`74|BTXfNjrZ>Qnd` zEl@oO{G8R3l~L_VC=>J&UgQ?9#%=A)U#^M1zW!Uu#$26jR)qQ8d+R}$Xt~#Jz zcA-h)-$)uHTp4+(18rR^{saFncZGMS6a8yrxB0-buuWX=^!Gs4PrKU2HyBinxA2=B zH&>;7*D=cmUm5hDCT|3iE^x zS7|QsLy{I1n>)_i)U-0QOaLY@q>Kn2jYBM%Zl-9dpDq@&s0fZeSL2 zYPPF!=O2Kv>ubQF8lIeYtTIxKc5zg^B4a7Hbj4zQH)*XeE|bJ_ZW}A-HMaN5t`KJ1 ziwr}(HQ8T$GV4+Xr-bIo#-y!u@stbq%MBbAL0Gu{ArT}-wKGpBl*vun<|<6}?}lvW zB)8<#GLrE{{Un)35ih2VSg2?eHsW_?fOdB8NJZ}{n+?+lD^ABTf+!2Kcx~il=@FWj zq&;6WL_6GRjNL4@A-v@ezofCl5v%ZEaReS8c10aWKYvtwPD*l8J!l8tT)@;@vE?YV zRBLzVp<$ATx5H8UdxH4qQ&eMVKEAx9E-NAwas^kQb$dvv!iv{!N>&gLE-E-F&R+3{L8mAKp!RS!qb zsc-eMAC2bn_yGvt#gR6?1Sz?Jo#xx?~CdP@GmE6ijo zuhH|BEn$8j?Ub|M1DD#lu>@Y9UFXFG2GPf~(Xx4#6dW6~t5JbmsokXEdp690yi|W` z%7J##x_c7-?pq#$VF1c^v2= zfr+ZiZv#o8;cg0L4P7jS8sq}Awz8Qb^OOfrlC&n1QqYigpI0Dh$<^|=!_VqhBe%#5 z3YljO1K1*883vtc0_(=3H|fvN=cQR=Udt_$)8lG#LbUt^Ip_35ZUW6hf2Cs|eM8Gf z$3=Q3W_cOe*PtP@pZ@Dp1a(528B!($-q6Y?6w7jF(aM-iWEG2U^j^IVplGi z4nLG-*zCg7g1GdrDDtBT_<+N)>~2;>9QRwUGen2qeQK*SxH4%DVs;t1RlMg%WpLM+ z{k@-Xg@Zh7YCK;Y?rE}zh>Xx|1Ki@)OwPMnO=2sE*&X}_hKwY8${zZ$OodGh7v~;$ z*yHD4xE$-&-u;!%)A=)q$2y;id@bsdX#pN^^ZGn>ti~3DD^94$ERXQB9|B)`<5l*u zNW4wXeL%U$X+hP2*BftcqY5gWcCI_z0wbqJkNc7WBm`9wg5k7EJ%GQF@8M&fK}z?uJJ=GFij&4p9dZgjix_=KrQD_wOMa zkxS7cK%R<=yNWD1;r`q*rdC1{bhoMp(@>y6$=qI|6M8l#J+5JDv&JAy$$IDrL8W*k0-RVcgh!3MAitmIG2Yt zHg^J0WT+hOoVPp=M#QYm8DV_ z-o&7QHe=##ZLNn@Js=Z-Xo1W;S9ap*92};)MW$DtePh1%eCOTCP0cwe&FxnWT~p#m zut&a$|R_O{}Y{3)rK$LoGn;}^?UE0WT$QVZ7P35nE zFCXvX65=U~TS(!)d^g4*Cvft^rU$06yq*}2o#`Xu2$g)3o-3(8P#dT*d`X5lJ$08H zJw9k5##1NNKh|A-MdzHvrh0_BSBBg*zJt^}0g{vuD3#jt_agI%63Gd0i|IgXw5lLf z<+IPG+fEJeKNgR)diyqoo_<}qYTl(h=J8J4VY8RieR-TKt@?u;c`KS3?PtcMh!myH zYeXwio`=T!D1*Oc*NSHuFb42;f^P#GRLvB&eRjP8IxN3Cq&=AtY+%WC3@OaZ$%lqS zK1~=kNll1A+!b!Xm}ZtVl3Hp9rK-M5O!+?(H4%LTeBe8DUm@p7U0e9I2&>(cLv3_c zuJv*()P_l012Xg0GDXms(;KB#zK4&IZTUI>hWpNFh%p;DJ+JcpNXKZW=Ne&G>S-tHI;2=S5B{FHyvN7;?C;uV0WE?gO?reYM{JJv>AJT-qV#|mIJ?@`K< zNxTTokyz*mboliJ* zPJwb)&A+-2NZmy+wBp@zH!rGA55awlqq04$jo_B3oI%2w45*#8=T}I9>I9GsA00Ey z5bdM}UJAZAH)IwO6?ZM#S+Zg8Ti?bg)=Upe8=T@5wBK~vTURB73lPSx(vClSuyC~_ z-89V;rc|BBEqCKcH=xIqmUPEG_XQILjTU(ui9L;}meEan!9Z-S zgsl=TM@Koi((}vO#7awXOydNx3VAL68^OC+<3&LEkhNLdNj&y4Ha$$?j=6}*F?4gK zij-(^RPY~tG2V$%-EyEm9oKE%ZK!3Wwx#s6CvJ0IJ+6;08?=7M&+DC<&^eAgaqnd| z09GJdC^w{2Mh+<i7ngyJ z4N7qlrQRhMoP^o^8$fKSYH>ua-nf*%<@$@J6WmzMNpL&@drAoOyv`T$%bNMns{5;k zjB9#~i-y}Mdv?E1N=beek#T5-75k(*-d^9|vs3lm&7aZAhae80BX@U_H_v@&o&bPH ze~eL^c1nd(NMq@llol(vf?z9F*I8*!v+6Of5-=}*j<&Oa6%)hib~NlYSjywzKX3)F zJ@gvg0>s9t2u)<#0$UphpN_JI`_}a_e-yO_xH@i%Yd}HRFUSZ&M-k?cea%4PRMwOY z>TkioEmQv^=Dpa5!-3}nzamQ7oXhR0=4;&?%|^=fT0ax2Qb0_YSRqBQ2smqn7khsZ z6GWl0NJ6lNazX8AaR=m>dt@7Bn{He>9A2#C@K2T!4RaTiXwl1@za|F2FUUIVC{&s1DmS8y;GRSi^A~jaLRndGxtjIT zg<=YuNy^e^0j)5=H^yZx!^i`23W9N-+pdi|OvTkxDSXY98Va1(K-V}QZX6T)eLx~v!WZ(6*Wj~sN52jG84TH|T z`|i0vW7UJ>gFYm$(aw>*Z#8agro{`nnK)a`Z^-HGJ4G|!Z4`m5pF%=MMgOJeM0b`# zCYI#B7nbb=1H6gc^0wdo!pS0lfRln6*Om=5h>;0}C=;qI<(Ii4ES->I#g!w~Z;{%H zsW*#cg?URlV@R!cMxedlZ5YL5e|I!RrIBbG>%<=EH9z)h?N|u4WqTHeP6Vhu7B}S; zkph4oq?%#ba|CpifuvkgBL~xq-^`;9C<(2&_BFHmtBjX9EOUhmZn_KRTU7HsRLiOw zC(g0wEY8MG&5O~4J#=OyE8iJJS5Y>4&y)Z^&;F4X`q+AH4A~ z_qTNNuG8Y`~Byfbv%|Nw2 zkck3#aty^%?8uOJT`<;?55EA83A-;cJJ$8ML)vIj(#r9b_t@?$zE@M_EeSYs#uew{ zL8?T0YBa43>yQyDK`Gc@~)h}VXW!wsbCFu zq9m9FWExrwW_6{;rHp`i&{)KZvg&_&IJcbg{xW@+del)4#d4%ks#X$th`K?Z^Y>Ck z+A?u)R4kEjdWH}i-y7N3Ot&yNI!ePI!Rb+pwZutRbnO1@JpHDtS*9ru`*!2W&?WSd zZyKa}xC2w29PqNqzV6MO;%V(kd+Zlza{18>Y7!{YP09*^SNBHN8NkQM3c*fyn2}+< zF!d+3y&n6!FD5giO^v8m+9zNylPdlxOD@FnYHQgH1$7x})wSQnv=X;w*47GYz}Lg&84HqYBdwfVkpgBvpe=GqmjXGo5TzZ*P6d@Nkf1r*!~*@Z~56N zLpNWEAS-?OJ3hkeZ{zR=&!vR#&J*7tPib z$`7o*5*XwWB(qTcugqn5yxE|Gz)yVW%F7d>czHyU1r@MRDw zTvS0xH!i@KA8$y*(uLPi!UNFyX<egcH{RZ{{$&sm>i zJf`Q3I;wv~OxVOwzS_tvX$dfroPsd9OKU8YkZ&;Pl>5NUyLJV)8;Cv&SFh(qrEM+< z!^)FV62d)-rt7;1bisc+aag+w$hyh9hd>fVG5@2qYVRT%Asn$ZOKRu_2UU`>v32@6 zb~B6ZRTEdo4K(j@YEZ_)69UJPb=ggO*?B~} z`Kn0SGsa_kPbA+eVg5_3l0LwoFTHfF0EP%Fo6e$r)$_A2Qy!E6vXNaQ&2mkyd&8@9 z&IvKvHK~4@hG`gD^zlrrM>K%F_2b)<;Y`13kAx0SsUOc0ARjLx;;5KOcD$rigBm~ zr6Y2xq3eS=3X%D_Ujtw6gWv;O#c5lHKP>(N>JFN*;@J8JFOp+uYWg9Q-&fb12oXhAa)*R;>w67=Jb{BTs^E_alidn|L|%RMu;nNg{b9l z`Oxt!&sZ$ax5w$#g|6kK~1G4mbtD0MbAeHWAJD%GEq6e#teV5MbE#Aw>!Lj6?;$WTffb6j0&F zq@LGPicGrBJvd3qcuU^^YwOUeJ!PsK!V#?mcf_S>0NDoy&dJAWeYS*_l-t(K4bP0O~#!5+v4uSjxT|r@axhDuMO?<(`fz)`T)EdEj&D&WVowRf4yiiNa>O zM1WIy(vsYp^?m++bm8N#USqwJy1iF-Au$=4!FygW@*;2yvpl0-h$JGvuIwQOxVyZK zC+bDwD5>L-#$lT#QpiL5KF+&xtsAZTS4GOt?s9zEzKmKJ+pP50hoa0Jq}Qu8UU@Sf zkVLixYE&*xf1@#w@^V>&%^q`(@{3L9HXZ(8)#6sI`bA|_nEPh?@lDZzkuvDg*z870 zI7iP^u^cUD1-y>mcS>4N03QAi`-<8$i5$L|47PGTL^|ve&dLmwV+${=M#cu@*7tO z*t-N0RHs?|H)rtm^(@FM&ox&LWf+e+UO1I&&)h!(Eb8Se_r4s?VmC^OShHN$EpU^$RHt~R%LES*0|BFhB_XAW=n_mjUf>|yzWVx?!VDP6 zp$RTXg8f+ye>wq}(5W&?T{z8t%Fl&R68FOZcAdeJb62~IcZQ9lU*>Yq);4}! z&1cZ2W&c%{0cx-kXzCv?S}q}l2agb-WE_ z!03KyMK@cDJL6P8CyS+9^x#i_Y^QFQ)UX;=LgCwiX}J(@PB@-D>s#htw94O? zk~m0wb1brTrACZ%wk)j29M`WVgOSn;e`n(CG$mF=pV2+}={BN;4_ckyd|0ac!=%Ol zQhv8sOc#L3rRh9`S~dE2AXi>)LBYQwwgCG?QoL!(Fbm|bS@N6wy-$2i$VEL;x~Kz-sh2tV}4@6>_km-AKzDY zv0Ez*Q)fK*lQyZOjZ4={@TjB>r&V6?0gPsJ+M5jx5!?5-Y|D>v{KE5JAqv1i@X2wcF;jgJJ}=2DY~Kw3jTkUbpx; zQKklo%a8Dkl5G+}^Dd$@Q2Mp%6xB&%Gv_|MjW1Xms!rNFBj)_T01dfT=mzdg{26`3 zTTdJGRd5OSngL=V7~X5o?&&nRVwveHPa5C7xZF2Y_%cQ=JNI{yC=Ds*5}@vr&J(;o|86-WJ# z6g==GMMUdo>@G-rY8`c?zM*!HM1^L0#P#R%oX6Ppno*jV(H^qRM2irEX6TQdp_?Wi zIx0O=O{!KmyS(i&g+&fY6g#dG`Eocf4bq|&9k1f#YpfA%YocO6NvsFl>wATetl4iY zYwpdy8R|cJNuDYsL?o-u@^%VOWlv)c34Y*oCF0`_pR^~%meO{o2VFnpId`v%moCr> z$dcO)=vFhb104r6M+##}QXatubjM5jnIPKa^5`N)H}UmcG_9b0 z2A&LvpAK`FQ(<`~wn@^HOu;@^=yYL3>N!K$xQ+p}Ysx|-FlR~RQx@)TEjuvTnTi!% zqbaEV4y6l$+U(X++(2*!6JA2=wKXI@cyMBsoW7>4h6*3i_}d!aOPRs#QkTB5{Yt zc_C1}PU(Z$?O?lBY4K7?nHNB`Dn37|7z(0%q*6t*&8e~F_|1gs^MPKfS?`J#5;aIg zo0CZ*YWAyp+@*WS%V7=X;UChpE^RKHXMC|w;OMrNRDrM&8A=)dpNlr#K;p1@7GPZ8 z`E!7j05{rQMSOWv@-0Rz&Jug;E+WFqy^ndV7!hTuj7pa&80r(%s)+d<4Fv#dH893L z+j1j-W4`iO`hdS1&H>N1%M1C{zW7kCCw%v{$ekK!>Jh;G{OG_o5g^r%itJ>dA9NTP z)Vj_%Ot6WdgQ=z!#h`>8lY#)w(EDL#{!v+-9W>qdM@;p$I6iR2{l@xMqC^>@Em?z z)%F=Q45)>=aoF8JZ_|KPPh0z}}t$sR)OcPpE!eSp^%JE9HQUre^T_)w~lx0Ei zOma#hNXJx7cGM)NhWH zfTRyzuj!Vn9O6nG_837#b_# z-M<@@Fy|SLfC&xJer~%ub<5~+Qbzd;`ivP0LA1UOp$((>W1nJ->i&#Ha)E5_oOTS{ zq(u>D=%4Hdwn&|Xt(k>$oWG&ObOBpadLZ-(_;sRGe+{)sESx@MavI5$o~U;vX&^SY z&6cZpxNRknW;mM9rJYXB%I|oL-%doD=OTyd6~q#9X^NlRAG5O~HInk?$c+rI^W_2Q zfYQ=W2)1nWs<%F!9ejCOL~bg!@Ql%d1Mfz9dJqfB#IXS7-W#QJFNdu++?gj!urM-{ zaF_h1H2(NEYLeHl6OGHm?;K5U_9iEpbuO#dFXq8oddoy;?A?ekO%h?I_Q=JkglLHl zcvvlB1#{eLINsa5scx_pLfvh7BB?EJq}0~Li+AJ41FOMsh@D5Zp{fmGs!ovkyJ3ej zf33L#efgv)c1xHEtv@QGNReX&`ACFb+NxCZLN@bI%+f#bb^`jt0EZw2Vc|&$(R!bn zBe7Y`A);Osq6h*hkvbkzCbwNt%pJV;7~;Ssnxl!TRsS92f?$;ItH;}a?#@P=$7Ag0 zG`LzQJY~YwHg0u%-4Oh2t<(4;A)_6CUfk{{tPa|#3vFgt9%+OvghvtDeYyMm{m{&j zVNi>v;&jF?j6mOin?xc0BfoX=yyCHgCevZxwFK}NF**<{6R^tmdM^^d(ggiyFBV*ds`ZC8hqs zTO?8Cde$8lUA>iuqGNhS9t{7tJ9b!i9=>~~yJj+lq#MlA@X7~h2!n*kEAncV%_=>wc+ITehfR7@CCabE}ZAWtO2^qzq2xf zl`J??ikG=(?KV)^(q zM8arj|1_lioOkHLSAoEu@u~;fe1TGT0A9cZV`HbeGVlIF`V(&}BU}@U$9^^3K7)qq zl7y$}_VyAXy6crnfcxs6f##@#$WW-lQ{9B&sLGJR7Efbn1&@f&y?d*miVbD1UFRTd zeB$IK50zQHpPINLo#|jNQANXkrR16`s)e%g46{I6o2gRKsZMeI|EmjJ3VtHUH$l5u z^FEwWFG-L#vu{toFB$}HHNHN<-ZZIy2GjE;QN*rs$xD?pWExz^MeN!K%nR<9mal>s z^ErB|1X5q0vd}i?6xXa+MKNjJLs6!8Eoq0#P;3a(m7jv1$Mo<2-h9~#_{iz(7#z)2 zye-TQXO{65D_Z}@6VTr{zM-vaL8$2r%xhCx_Q=elu+)Crf-q8d%7~EEz}Ht$NQ0p# zMOL&q{T7mgvLk=jpv2TjUm~swTlM}Ol_-;hA=Y#ZprE<{Hd%017ZJRx>*2J=LN?8E zXk0B3)+RT0Y_w0f&NpFzcs*tBIQtj4v8MkS9-?Bq&06S0dLrBaRuvaE^Uvif+c_Zy zWGKWW@ThS-`EX8~qX&<``?2%*CyyoX#6GYiPqF*-;Yg)8>)0Tx&%1WCX1c22Csy&o zCt`HR3~CQX88|n2>QhfXR8(&7*pQaK@xgvNuM8>XQBPt67LdTWJex&no(Z6N58j!y zn=3)iaC6GeT-PFt^vldD)OkG&%c#Qc73b7?3(UU|qrnu=;x_YiCC@;f! zJ-Ja^@hVi4?fZO5qjAP6tSz`YTjD!WZk}{=JX3{ZB2D<$Z?$C6_ln|yud3p_0oVj; z6wBqYKyUU&zu6NEuLYdtzia|!oRvF*mF_;E9hZ?-fnuOW&wvRzY;Llbwa{^ zIpeR|o7`cQCv+*m>C(1*3eW)1cSfRfhN~DXxtefw zz5N2#3EaFD;7e3=D&JUA@05GRFq7EVVOWqmQOa23s(X=Qn)4*4rX&bQ) z)sMXf)82=YZynJB9g#elj2Z<(fzq4t;^hI#m{6KtZS&^5XWrnbBT58smy8(0Ovg2sb&lX4#~gyvG6U%Q(in^ z639u6(8U_5m+4D>2`gCwhB|c&GV_Ofb$s)C>^bMKc901`f!YAaZGC7ysg0^rW`T|2 zlSlQoy`)b;B&}uW1`<><&9o51FJ|8Sw?Kx-z&V1b?1xb3RJ+wKymuCIoP?WjqxI+> zPW&FTFr21e3T=DrB0dsHwU>0q$`9+agZ~oc&#kFDLsAKha*M$5Tfobxp!YQ7M7bM1YI#FKrV{i4T*fZ(O7G$04>| z;mYFxR|;4$C;Y;ydem&Y7csA_hUJ2qtRC$9-YPWX$E%S>~pBh&-Z3^$;~ z3nP0aUf;mLR0~7Gs*OvAV&+)o?#H9fw+@IVpH{fs#&brvUp$>ye^(8ABwQqf1maJX zb&ay`gUQCh#x*W(P^ghpvmrz!@fuhq4Gaj(7LgA5H_{JMa-ktIb+jl?pLt4f^+1@> zq^YQZ)FGq}J%c{wQYL9{VxS8U3|C(`Vk>b^6zS{iHLz}#@bpdmgiCq9~d z<^U()22^-a?7E9q#@H{upSqcBb=Sv^b8}W$`hfh7SpiK*e`(D>l=(u%3{oFMIfd}L zd&KG?-J@LG##sQ^FHHh$#wsg+ijzuNahlT01N0JfMkKIE$NZ&w!v*+cdgGOeT(G)7SmeiMiN@5CHC zX^=m!Og%fJ(f^~^T+$P-wW*6v+v^_qiE~mI5)?^g`EkVJ%CGM>*vMxd66ga~*s>{H z<4W*nz&$T^*Xt=#<0vN604wq{zS7=;fS z&gvDjUn0hydK{p~fc;Faz&4}cJ`Ao3ZT!TCKW8CO0L5b`A**&>;-KK0c^icttwxT7+gC4?uh{NksS;2 zIM*ly#mta3c(j^WnUat*rHwrb4CWSwyo#!&Q7R!nQi?Ul53B}>PRgYl40FGm4U??| z_TnL;A{0#Gq{dR9syDn24JY*4^j-gU)y-6K{02+EhuD>@8cHxzImnph7VjwvUIoI9 zGlbR64|gtlN_tZH?q1O|bp0(w7emnbwyETST_6jSET<6uT7^8%JtLdK9h8Eg=_Sj1 zNKfv6$*Bp2)eB|o+Zw_j3gz{F55|I0O|PsegB{%?i2&Dr7qM zgM~`8>gknHmy~L^YeyX%CcYS12H0X?|{7=q1#K#E(D!&87=s#1fpSjsul zybEa=&QN-4(jlN5=lrx&iOP7s$XIr#n-s>`)ZFVUY>K9Nn0fnk@2u|%ZwK2xWZ8cV zm#HiqPaW!-m;1Tbx6TEC+%$e*4WM@xiW8O|ZA#KUGK7~f_UmxdspIh`veD4E%Ze4J z3pNvEu9S#GreI`3N!TR(FFJlpG^$_iuqRu3>aRUYPntPV7TzVuR&yJc%W%Z~bZ*}z zlAH<17uPZX5y$`*zu@^PW}`4S@*BulCufhTYpLKc9+~IB4Ql~FyQ&5eJIQZibQiU9 zs*#GmHjdiOnbQCV`7}k0xi8(DEiUf>wvI8^SxiCd^ZV@BWNdaN3XuH*^cZy9JB0%T zE#701zQp#(Ktc3TJCN{xlnpkG#y!-K3)cvqS7dYpsBL#8wa2GogWh7?mc%6sff4^k z0#x6%yh1;ZD-KZiX3}8k;H)`amMVu9*j(4X4q34_pvC_eM{i6Yr_jqzUN{-6#R5@%k@e zOf(7s7N$UFkS8V7GUEwce~;y3ZxrO*<56zY!={~tM?R>y+oe7`!Sg;#V+&z@Dgbp* z)}b&=k?+Dx`}Ws3jx8+X9Sgzpvhf@RtTe2AlY*2ri#>X2dXhVyIKzF*? zuP}*RY2Cg!USUS9Uk=`dbjCLTGU>f2cjipFo}Y%ZtDC6?YnNie)u(bn7-cz-x(6tx zAUx54D)wGmc;<(BL=TyGUjeGY1;}iDD?;OGe-4*MJxK|lI+E&~V;nC(FIgShtMxpT zu1ExQF#PO4!KS)34jQYm%>>3rfiVP(pXy&I1dYl|u^FURQek&Fy8lZO{yG}sY6m@> z7|txs0jv4=$i54!-F9H;ZOyD5eMD(peJG#H(ec(SQ4DqhemKS*(=B%1vy51X|r>W z-VY8XeUf{2-BXUE?=cCa&C_XY)yu^izVfr1oGp7HhhQp=;GimyfRN=?vky5YBGE?- zKR9EnVKUE0Fzg)@x74zS$Y+Xq#BO(MRdErzxi^nxAvjKwb;wSz0l^Ee;MJ+mtL0oX zWOhhODas9IyRn8K7qt@9>K3)rXu&0Pt{@O zH6h=;XriqlKB{RN{tV$a0jiCC2l5I}qYAk^v)g)5B)yeVeYv*w!c*chg1^_{c$Fa^ z`U!gJy4S7R-iE+1(R}2S4_emuYPpKsQ?`6RPdbSJ)S}QtDiDi;?T&C=YYwVda3- z$FwwU<~k7x93nm(3gWM{*EPS> z)a3yZJcC)fSN^R1ou3c|%kolTAYj@L)I@7&uM@!^?E7nGr&6qe=pdT0NeMaM6>0<6 zvbwEzny9{fkQ>nY3!Eki?8CtN380|OM_izzH?vV+xyB(v zF)UNomAhAy1?lqB7V42G&W%s55yIF;omb|=AbXd3KDq>FHTuZ{2Us=0VTj|pCCgQo zu65|{?6;(Sm2d{w`|Vcloumi3HaJ-*&>8bm%+#_F1Jrh%Q2#Te&8^YZhPGooFLp%Z<_OYRYht@{sVH{B89W>Kw zW|`INTjY*MqA78@DcU#v#tr{W_Crefw#&^WpMLD%pjO-<{lfYkVdon)XerS0>_4<; z=Tie#$EY@MU@HLO>Hf0_AR_Qo`Bj`Qk3NT-`C!bZ|9>vH4Lm#>U50MBeR5Gv@qgo4 zztSr%Oa5Bh_%d1y6!|qbooMW^WBs$$?Tmk)$Ny#L%Cff=7YM1E+$c!+ z9QoTt90ObhX%w9n;2Ge1k5Tfc`l}^904)4?R*<(1we>>rpnUQiW+g4OhwU>6kaAtU~kmObohl7FQ zkugi2${T;}hJa{wVTfwYRm(InDQ|C@=j_&xjgxl`RBV+!B5gE;p{PR($6vNK++Fsw zCrtpl@;Y1PI`9TDbec#Z4u$2X_91XExmr(w*k&)j zr$~whcX%NLnA1dmYBV#;JE!+tq~HoTGtdq^FQABP!FS+X{a+Lr>MOA|Rvagclz!;^ z?VIc5YB-?_FjrfWKcc_~USOL`dz^(@2el!ueu@E_s-co#U4R%TnQq{W6O?A}aB%B< zJ(=4eejnf%i&qYJmi6L}fFL*RPn%!lgM2rPd7h4&MC;7m7KBUT@ou0*(!1iJci^u1 z^N+YZ`sHRnep-?V%*Li{$$`v-j)DVo<*Y>w0_>swYusm- zB_eekd|2>D@kU^IvgLJ@$>60x8;p**9mQR1%p;Q7gs)g>y&+h29u>HV*I^9q!#PM*nyTR)ciR``k1?c5UwUZ87tn;Z*Qq zF4nAIlnPRUfhY}OUa5G)5&LgTUW3yLt zvuOjv-waXi(%|*RbLv;^IAgAj{}Z1$Bz0(W1&oth@$(&ArTzYnlQGG^DfWVcAC%0K zPB(C;Zt8ed1Jhw4O!5fehRHdswCLWOssEQaKSgpFVRfsaL-fYrS|P}GXrb57AA6{C z9_gNC(Tpys*b*xNf-KEU;*iW zc#~zVp$zuQc~BLwF$2+Zz!lDAFsR`MCoJ=Fb1KQzPnk|)`)FSDIkc$(XM$73Ev*=U zu9^tna4~(r2?+MKSaR&01Ecyc6nK;P7JC{5v}3*~0;?O|{_!s$%>>u^vEXEc8wK8( zIBPjFCE38;=&54_gu|G*vl+-2JVDEW_E00hytCZ!tYc$Ian)c_4Wi zFdTBsWJY_myABsvAp-;(Jh|1dm;g^eu)jAUrzMF;Ar>2;qVJt(fr9G$zz+D?J)~WU zhxDDtj&qW%K*zr}q4bMZJWM~eQxFqk@$mvx=Hf6$9W3l8B=w)qjA0F+BWRA=k?_Lx z=`WJJT@jW(efcu$e|F)u%Yd(K?`+EGEl^ksg_ph))t#G>iKbSClQI5g32D=fZBhPq%fbPnB)CN2^!Fxd>M(JA$F9QMkw^$+;Cv5o8$_!*;fPtT zVH|5-7LH%@rA^nMApf@b@C{Xe`$n=Qn1w>d;23iof`Zk)B@Ow_6g%L)EiT0C5rqI{ zc{TYWTxT;+(gvH@n%1#0|DUiG%O)vDEp>qPj_3u)F$U^Mz+qgo+aW^roX?n$Y421I zOs=;oGI;s&v@cz`=3Nw;;2XQ|46=S&+Z$57FWub18##ZLy;w9unkdFeRT>^+Guu9d zTFf;X1t_4inCAAhFdP%AQ9O#WOcca%}kmn_9i za{6YO$`>GrLt240EKYxKES3AWV!H>UkSGtieb?b_I1TJVAl!0qkIC<+l?KUgd2Cje zlGXRsRKPMvx?H#qaOGKmKJXInD~fKW8IFc+5&7!e2c=^9?H@h}(-Ce3r5`>2iwtKK zn+rx=#S17je-hk)h@OUIv4wJj%S)TyUc{MeYETu{T9tWsBZ5bhFv%VG;3hM+1J7dG z6vd+ZZFRk1Hci0u|Gta5n0`kl1@r(6W@WU4z=xp<)zD2fwW@5ZeJ_s-px1i=q!z1^ zJ=-}9$M|6v2h6Er)4>5)bhD8O^0kZ2_76No@{=zzdE&_qVi0;ioVpkPM4XM1jO(w~ zgdm2l4SIVq+B#iUFb6Gykns^r5Q3Q3PqJeo>iJPX>J=qhYKJ?K84M!(R^EoE_s@$< z*Cw%Sy7^8Z-+-Q+XhNtKDxXlj940tw+nXIxr-+t}J%n0=%VC|~n*PorxzX}+Xgm#Q z28d2z4~pp$Nf_%OA>fO70HrLhPFp+cdZu=kEOm#qV0Jerj#!EB9#-^E3#{^XiFR#c zmYKsP&gZyr0+*tNA|cKn!;psv@#1G1L+*V;xtv-B9f7=a~=Xui}ygvQ;r7;|_O#X|(p z3dXC=KJ)cTF^pwDDmHA#l0)~r6HYTB6hwQPjg0&f^NG4x@W{r=yr53}h_xLmdzH#R>Lej5dXJ}*24af);gj%RU?>^> z-{#7G?YbO+&dg`WgB`u_DcHM_&NOr6WO0Hlx8Gk22o}k>c>eHSdmEUS#g6unM#zIr zP(FIOexZ}lF*lc0Q05j4XG*_PQZy_>`S)4u;WpY%OO%JHMF9gUS_14%>2wb+ZkBvc z*$Ovo(V_0n_~`{1ZH?PN^hLB+-)1F3z*vl|ZcZ;1&tN zTvyQB1sOYfDW)J>D2$Gh zKZzvBy+yqX(1c5Ux1NFEqBWX-}XxX@gu!|acndTsC zl_CGy4|#ya(UWhGkj#nUG-R{dn$#!FZ`8OXpM*#_Wl8-&v8NTge8Mt=X6nb!-2U;H zEJ{bur_^dx3D4#b%P^<_H~0fi3nhE8>cr^2y_r@fzpM0EvffC-rNh0Yg#T;ewbqFg zh5E(s@`v}Q5A}?r^N&jzPWv3oh1h&hH&Du{5$cBi=u%n0Qh==curs7 zXVLivKbM)rg&jZS)F=R4=d<_G7_FR9)F-67x)GMv0bQ?7Q-@O;;t#zSbRmFMiGT1M z`G>%Ny-W})tXeag7%@|G`H9ZCVX`sO@2{X8*c3hym3#+glcz}4Wm_qqsmn~U!r zk3ErDZOA^hGZji%WbOSwPfG`ac4*KF&2A^YuNwRfd*67>c_!K@tUHG;3 z7+U?cl_OZ@G{Ee3Cv_x(N(Th?x)qQ*z2IL~%s_T-b+$3B4bPVw%}kpl=V>*$fK#JM zxXF%NpF(4LW0lIcMr8F!V^lUQ4dQ<5Ck?%V&Z1{Mp~5pn<&Y0{ay&J#%4?J^*h(ot zbS)_yu7|`FTJ0e>)W}v#$#}-X(qW@Pu98kO;uf!)R*o_Ad~CI4qU2Pf>U&K1+19`c zejGOW^Dn3SLFWJyjaomzDeR=mU*_x>HGUuq0$1?34I~T<8tPCVs)?$&`S7Nx-C$Ki zvNA_Yvja$L9Ngv&$JaXnHJV2M2v(|QG{s`6h4?_}&hDG@BDz{-b9gC>G^l(oK#5d4 zvK8?Qifq&);U>i`4cW_e;#;I6MQ{0ve^N$l)IOpSQyU}ca`y+pqeS}%gZLb`ll(R} z0i5Ja#m)f!v4^9VR9flL%dPJY!Wb-rc06>5XS7(w@Ge7jl^`l{7vr^RhVjGL4G@-TXr7{O3`AwAX!6LaI524SyJqiI1GVAg{53u@lC_z;XxB zNK?x*u`mwhfVxvLN`Hw3OS*S+^LJA&SFSn8f$A5slcr8oiFZHumBUN3L z)~fGzlIA8+dBJ;@#vSdCvbH*3wx;$P2M>dwzBpW1nYlA54}3Gj(P&z26wYNgYN`{D zbzfHf72dOCJT*|XPsV8{XM0GX1!O}Dk~p+r;Mm{(Umioq`ewBVwW#}*No}5+wXt>( zZStt{rvA>kl|i-EuGC&tyfzD!kkScP3=F@#z)Srxqz zO|pHY$z|K2B-)FVt%{5d1VVdqYUEH2c-xB*WB+MkKK|;Y!V;raH~x;$5X{I?2nz3= zExkNjI!xF?>_O{FCUG^&vuQc-qKGUp_^hZw*}~)`U50?w)PlMGW~hp&+#pak^eL() zAnT3#9`l3^^h&@tG@^iRa6=OYQiy#Pzdf1xQNx?-K)38%)@iC=7k+I3*8}JibWh{J zTwpcq*)>0;;wqz(h*yY69jk#dS zwe8wEARYGQ;!v~5+(xQQia6?02=&gvT=4%IXY~)Ff5-Yym7g1d8S~2ca*jy{IO3&v z_P}7D?7)0blvf1mT|HF{n<7R{vZoWrV-`Ugov*}An zV0Eo?b%=jhJTvSj;TJ6~xaU@iM4k6@YV)KKW=tKgySV(klh<&0y@sMO1i~EC(GVC> zwcbmd&pHk0OAawr4IJdd(t*~eBTx>un5p+_*E$f?@>3_@WG=O^oK8UNVW#XfK3$G4!e`w--&3V~wE`-NRU- zUHI%}*Ik6plNMpyqHIY;AgVWjfMPGWi+=BL$CKIt344Ge&xB3UQps}9^>y_%1Sw&Gif-?^BQYdg*FbRr@B z?#~%{)B;pMN=r&A`F2#Tn-tO&jZ4Nh8aBZReWzz0Q*zwBnTLCZ6h;{+3#-7G3fh5{ zY;-~`(EE!@00rd_{rmb)4`EdIP@s>1)X4_bvQC2clsrHjZc0@5&*89|?TH;2Rn#-= zJww67ZvmHuBtSB4M~0mR_71V4^}Tq)nO`;#NBn){6+8I&A74AA@L-7SOZt7>&+HO7 z_~WHofi79yR4Q}fkcI#v)l%tN+o|E>zzWvIxJ?ei2W7@b_B%(_mqZm5^D11d+ z8ZsQZ`1AvLX8+LFB(YzSWOdBe>-fKUCDade`)|_lgFnhUgjSMX#bZT)f?RE}LGC?1 zs(9ou%wN+A|C42y#3p5j;r{)A;Yb_ZVbr)6=dP^A6zwZPa{mPl!AivNY&TLSEqklW zC8GT3f%OHZa~$uLtEWTEL$=ax1t7z|`4$x(?HAz{7ecZauLK+cUJZAj-G~Tv?Px8f zd?%3_cF4!i7GO7Rq{1vvhB_~=m90;cewkea62R5gm$%%lYapyuI6<04Ofgxtgb)X- zUa+*)UM8t1a|xD*7jA`JXrKSM1w$&C*w+w?rfD`|IS4zUr4=l8dcd+C5F`dmGd|WF znJd5n$`WGL>}iHy2=Oq-;R;WkinRNR66Xwj>1ctT(kw8ivO0ZFdAZimOpFekv`U~R zb(0j=XR;!GeDs(Cfp-vD+WiwL-uoE9jWeM$YLRxa2rLb!P|2qpxZ8JZZ^Hh2BuUp) z**W~&fpj>`3d~Hj)x}(c}V~Pb1i5uqjYXP+xa`DhbaItr!tFQaG*1)FI1B`Y)SFQ=dDW zj;MvKFxH`4st0vUblnrLsB^w{FCJY8z4mp%Hdx)%2M;|b8Yox{P6W$GvKff~TN~-& z&qIQ9wZ5{+RdO7w?&YnPjcQ?u^j>_yzlONTU-$>WeBsN@@vy6$jKol&p}h z5}POD01)Q8-H`QJ+2VW5kR8-&rZC|~&U+5my9WVsGH%A-NZHtUB6#y_N~a;we@;u% zscIDU?E+2~SQasS}n9a=$BzMTh28*jffbD^hIk1uX+*mztH?D0<7&JfHd)WmtAqp9Hg3;){}fvIS2;{fptF1c1LoOJ z4Kok&|A)%^k^Di*O+2wXV6i*i3Uu5Ng45Y2Ihd#KJwWd*cwF~SO`Y1{VcZhKtMl>| z0&g0EfqM144_6a9U;AkSdX_#;we6X@s|!fR(c=c$4Anu{MH9$zxQFl=4k0;)>79L^ zEcs8WLNUOD6-$B3U^N$gm(f^uA)_6$$@{V zsbJHF)_-Eh&RAi=C#cgEnbzBln_0n*#-?b5`Ijo9Ju+O#Jm*a_5U8uN7)Dr}fqx)2 z$6Y9nZrS3OK)&m=s1Z+AG4-2ZC5n&({NgMeHW5f3rLf|+J>XGkNP0U<C?YaO=u1&|t%tQZbJHEzHS6MxN6-vHe4PVg}(J~ zgMcfnO_Dr=LNoTGe_|7|Dj8~ilK8eQL`nW5NIc-QQYicjHebAjCAU9B0-+^hZabuy zN>GvkV=Dop#uEC|lv+Ia0=#an!uD_7;L9C>o6rwv%nXtVyT9s2oQ$UK=TT;<5i+>g z>m9JM_{iy2j!ue0Qw$mwCBsR!|9%bm^EAK{c#{cRpq3LoPAn57L#~|0f9hIl{m?STHeDpKTuZT{X#MaW1KMiSdpSffZJX9Le+Y!rlbzLypy4{NS{~N z^4o4ca8B6FWu$Udnho^_A1l5Z3Mi_WJJyXflS!gOWMO7UuC8{odgX_?M+6L@p8=ZnNqi+&Vd6y z)1FtvxwHXVitVzRkW4%9!-CoPro27Ams;jGf)lM+pux#3a5<&cHA4UdK4S)gF&6db zBy8~IJGT>h@eue6a#1}h(TsLdG34kIO0M^0PnXqg8<+G)yD#L`9cVX5mg?l4^oNK~ z5scItP$6!EXj!PpO7OcTrg1tN51Z>&BG;9bZ>`Qj-rhn7yundvy0xKz2n}jA2AD#D zw9C<6L?MFT4*~B9z}{mW{ybcSXPR&zTWZ3^nZQ8u!6&`-6{F;2A4*4(_nk-?_BqwX zYrDtkuv1dc8eD9VASl?*`?1>4M6(D}06Bh}2dwFy*8x`vJSWFPxFTpTj@5=8&xf@e zo^?JHisAa5c}jC7r2gr5Kw%PvB3b30!ugEr$Di4Wy|>AA@?$)i7oiczOxY)^PRqc$!>fV>P6BVG_l_2Vk8?*^YIh?J3fH{s!HQ$EQ zY=0Q{mCNs!6j6Gaedq4ZAvJ10=@o|c!Co!RKofO7M99X_XY zRc0QJq^xC-NOw^gk^Bqn)Qhu3tizC_{LdX2UVE|w68fpYKaQ(biQVp+HyzQY=323L z#YQ%onKmuCw{o3FsJ2W&ZM-v^Mtgmv9hXTIbw9YPa2Cr}XENZoSugJY+G}k;(p;f3 z>CH44tgaOh=0XOt(lyA9bVjcGZB|>eq0YU&_`&Hv_t*?=X)8>ayq5S7vLz;>fkx}8 zLf4d-G*`=xC9hEyZ()%NtCSDHZnnnnBH6xN}+;KmSOoFcJ_6}V*o~- z0#qN206|cNP&a{h<6>Y9Q(7V^M6tnC6LP@3XqaV=<;aoOW-Y`iKYu?=T&j{`8&p@Q zv-N_b?fw(%NgBt=_#>1Ja&E^KP_uBFmf1-;wO75H2mH~hecV0#pa@MrJ1Ob)q)s0X zEbkMPB}5h95WwzG?43#Q*qk<cngF*9D#svp=rZ_EcM zSV+pxH%J@ji@-x_fc=||bK&5->#3KP&wVl-{07wL2Mpr8+u6AVDl~2}X(|e-K0W~7 zXfRV8CiDw5OV$fB+yP<4ymOvWv(4mr!ZHkb8wPEe$UcjfzYBgu#szBJo-i=MjbRlO zipA?Hrjl^Z z!Pa}R=X4(RdMg8t z?z7At)yv_HuY410<@l2mS%w6i_owyl4|h{Np%^?Z9&kC0uHN+~h?~N$=O19eoz-Z? z15Z44f*r0ZEL*4dUr|_yaEd&r);F@7XF|!vITR=6aXn5k?wHlsm-l6hyy_5VXQ{Y< zGi=t?*{g9PWyR?1ebF)7a>0!To= z1t|qZqzKHWvPS6-8CR}Af#r&>MHebrx6r4k$}v>LntK0memrH-s#7;o7QTRolUs#t zMvy**Q*cz`&3u4ho=`u|iS0YC-pf3+SKsrM*t*dfbN4w7X7zN=hM?4FXg*Ei9B%D+ z!6~yC6-Q=0dlv#&E_n})X&V*3_VFPQfVRf1f3z#PKib*~F85D9Y~Xn6QCEOd9?37NR@PHyt~_L03w(TxVzig#+TipICbz7i{TUD{j{59md`&D-RoAqERGKBN&oX6zho01{gl(SOXm*6Vb>V!ey!u z_C+$^*dkL{>grdhtUKk+W*@>m_?vFV8+|yf9aTj!vqM`x7C`iz0I;E(LCI*$VOea+}tS- zY_RLqOskEH!DAw~EAfpo#vIiUH;sFJSPr-!nJG8-q@C6xeC(A2Cu1uWYtP;4enis7 zyiiz&Vt)T5L|ta{W-fj4>kGePfXB{^EpiSohFN*K0{poj5~fNLp9K?HSayR7Sm=$z zUrvt)kyP27TOdb>d8K9iF@Zb;-u1rYA`XUEA4C`Xb-YUx@5-wrrz+&m<5|o-%d6?` zJU9$_%1IC-d`Nf;$Mp-o)8mC7|A}f3&8dGR4Tm)+sbhviO}f!+5bfCfQhrM$jm&H> zXDCkU-4c3n8YS_y0FT-Wi%vmOoLw0|j2PD>#pT9z3^3`V|Bjzf-EqZAy!aL_)3gFt z6VDRdzvmdL+k@!(`u)8`$SZ_fV(}U7=sBa-1(GrYL z8vmOc8K?z9P|Nb`KDk)>RGDune=|BS>Mi-*%0FOIh2&*>Cl}x?9oUZ1yigvouL?gC zdEH>uN)dJaNWHzg@5b2}h=PFChXjRKc7#7O&IZSJF~J7#nSZsRk*~K%ZAMO>aMIPV z0mybT6kxLi0}_Ly9_nI)$<9cXpH) z#>B@gX7`mHAC4Z%g;+&c;c0Y=LPaDM`8H#(+*KbX08yNy>49nsY&ayB#h9VznzRl^ zHMO{>P*zjc1l){vXvXb)#K1au7wNA*fY-Rd!_Jcn5l#70#aa{{Q;6BqnCxNS!wk4P z8Ln$T`sbGA@)i8>8FWe1_b)yH5Y`o@zSxUHI;jaWyAU-h#_g<`xJK%E^NeMqwa@W7us*k| zbca#Ohb9ZN+3-6>N%x4BYN4H%L9K@uIA;u}AUa7>JuNz!Vu?G&IN?KbMRZ9tCcu0mt*th~wwe0i-=Esn4nEnfY`hFl<6UQVhWZ zj$|E7ys9o!pQkW5mivSE$3P~jH(R2Lbx;O8x>y$(3i20{GC{O=6u!HImA|T`nrRT( zAOH`vmCw-3W$_=*>OQtmld~C*^NxCeNz+!GIoFqj$bnXJnSg)cD3+sXuHVY64*PuQ zfg2I^7-@Gac%r67eC1S6vd*K9t~c!Dq6laa|Hc&^tGKrCntiGo-s>R9$EJ0w;NW7k zQV)uKqwcvn?e4Nl4}+D>E}PhsXA+PV`Mivo8yH5Di7`IRq@5dkSf>L9ODs#yY(2;8 z@ag$!5Z55+yyzfaNqQeB5ZqV}l7tZ=3GSj$iw+d#q&<2Z^CZCxr$A!JR$nSd{W5eN ze>o9cwZV*_a}hzcU;0}S6~&5S5uZl5-40tz$=pe}MJg|))M9i204UQo)}37&KfB;Z zh3p~3mZ9X1aN)`|n=Y&`gWpqIaf+U?LA@woQ%0wl(pk|cX)KXRE$So-9uwb6+*N5r zg_GYg2xUt+NvlANJf}C@L9bd`1hT6XYX)0|vWb^1Ev~dSJ=+j{6Ni+H%xGX;?C6P@ zDonST5(#?wW#k9aRjTG7F>gSoR=NQMaka8>C}$!0Ab}8AOzUtNmmFKX@X~}t;49;i z)Nc>RhDkrGDF0ZiBG0ku&AmKR|-hCsHfcYOGA)}k{LlitPGsbmshJW)wu#~DX z-J^+L4TTt~Xg$Ph>Y@RB5WY+l8~2?2N!U`J0u_JBf#k3{DFS$}ji=n`4m@-|o(_e0 z=7o>}o8JE)5S{l~gnn|N4${3Cgn)hqqsWRtPT+r+v_|e)n`9|N$C&pg;q^Fp46RsD zV*VO6PfG^}H?qTc=P;9k4=lehnFumA32x01NT295rh97kB>Z;A7zXfeuxQsUYF#JL zwjQ*MIU~-l*a3R)bSN8M z4D!;ejkw zqy+v?t@xXZO^qe=f_~9y*UeExAz;txk-?XWS`xE$^2jPKI6vFY_9yZ2lcIv)UPF7m zHFQj98zj)+2$tHwa{O(=+@wq`eZ0;%*A&*$tm+ZPDpB8elEXPLC0l7ZvuJCw=0W^W zKj%Vr`58&^@-~mjG5jCkJpIX7tWVd@LP1v@^aPh_j0@ky3p`ngjwNIS_~vvdQZx8N z!Xj7bR}=={yaTFZCt+PT@^#N)Ya5Q0JEK2I4?8Za%LP!tS4hQ1P6zwM$V~n0v{EUU z>YIH6adK(;rMaJ7qUq=>nmvh_*3)s`6)yauiq@rtkxwgQ4m7Sqh1p4Yv?mpW%bjr7>5py2)>u=;t`!y z|3g?8nCH(E*OYq@39qbzrZTFL(sw2A!TgQ}oRxEt<8`#uqh$-U;|*OcH-QRKpGAZE zFxEm=#O%}9;MWvJs;PNz6N=&iwIqADPCv8Taq(a-iCLkYDi`AI8~3YOCDslXYP#QV zwa>wf*cNhoVv!sULlHY_bMvJ&TR!Kr&5QH&d`dGn-FjGv?lV$2(}|VGb|4qLAt}}Ex2=ps4h~_;2Pfbdm}e@1!}qlDtib37mO~Rut>LF044E|_)LMEg z(8Nb0S}zE~pF0i88O~VkKzu9@R5|8k^F7#j-8pp#n+tmH2qMCJ9}~U_(&J9Y!7k)a zf0;f_yH^2b-=4a;U`s#7!6rre!bfM9Q_dV~-)I;wOJeNh;;1zCW8ezJx-T8>Z#@Lf`4NjsL%`n%hjJMg+q;V44;`ADy<-d;6$h} zJUe~wkwnVrm`VpEW zs_K&GPQUu!pO6M{UksLm_Y|YYM6z@6j49?4Q7v-fl6#N?c#67OKcdZHZI)(*IV51H z1FGm-SzeMfGVSP!qtwnV*z^G>Z^Gt!!u5I8A05Z`;;*Sskv#dZoSOp^xqSQ(wKaG} zpu~AFO~~l93@eNYSQFT6WL>Neyh^SJaP>0mC(Fnf$@pDteELmqPCej)XHtb3o&+yMICO+|IfJO3{dit1 zNycGkERLL3oYQXrh=?asQ?4U=Qj!Xwx2H?*uLl<^C03c zrUw`s5}R%i4gJoDYQr0xvZXw$tWFvrnR`Et`-5g&)|BJ1#(GOw_jVS?>oj%nlN;xh zgLU1LE{*Ml+J_kB@>KLD>H8<3m144w-!0!gR zK*!4hH1C1rq}EZUmM+qf6{*neUoC%!9*L;r(j&Y2*6dy3yI%@Mc6eYp4Y&mY1wEGh4&J2ABu#N4&Wo<9*%@vcpAw1z372JK%89&j@%2 z=L7{_UaB<+8b{Y)xUj!f?Dgq-K$*oKu9nB{XlG=jUjP{Wc8c(-{$ObPQ;5fxmr$@} z^Nzs!LE(z9S#@>7;R!VNMu3dc9g0+OiE0l#94ST#=RA7rs}tzLtXLH^h8Wb$v3MXk zYWxyjxNKa5kj2@MH`;~;1D@&%g+>h@4klDmMs~gsb*rtgB|l0;2HAq7b&;grTY9o! z11%oZ$uEIrqR%rbBt~xp$N|i)3=I9Hr;+edaC)*R*gY3PhUI=FSoL$`hsU^so>RI_ zWaEGhAb*@iXVEQp0eQ`Y5m6)fCV^kPT|)8GX!A;2p;Jnfgk4OGQ(bt!F9cpQmbB~N zS>vJBhu(-M4~L6NUZ)a;037R|7;Xuc1wL$MUpHgX`W&e95Y?5H;{ofb-E#oB9g)Iru8txs?m7P{1hFX1%mwQV|u?-a>&p0rgF2-nef z&w$MNstNdDL60xcBww%vzBp@u*}~#4GR;ZNTpqmuUs%-R@UxyA3aY3>M5v2Lf4_Zj z8GNHWK8i(Z3gYR<)yjLND=AR3)|zbHS&j!V3?6#wJ->6CNtz)LKQvDG?(p>%F8_@r z@9r2Q6ypxk&2<(uH7q)`FR*&KHcT~bB-B75*e<4?S>5|lu7pUQ<*7`IZ=y>c**+5V zPV!flS?V7rCxgKmPI&uh-Jf$Ikj>xMn?9M0y{YpjkmZ)){C)|z?vmL0Ryj84OT6${}>fIMulP>rprHw+h7cck~pTu6qbw(0_z?A$ByQ0(3EILAO9 zKc7i15X&FLe{0@>e-*0cs18%wHm~s9C7asqp-zM{~Q|W*K?ss1MAG(wsoFhVD;88gUPL zBe^|XppW=o`y5^o>?qXIaR$`lLd_*-!N=IeoKN3hk%7_fl0~d(n)sNGqbZ}+r+Uf4 zCQ%iV$HuMVgz_&kfV&(FPhiImsY^y8JD2yT)pLfl9 zAL>!K@y>bLkZ>VnmED-|X?7{kY3O2Z$MLdnmS_j2!uc&*t)c53jA&6?LriS)g_OeC zFNoI@hVQd|cHf{&`sbqSu%ZR|O9nU8qB_h$GovikWh-V~sO1DKS)$#aZf8 z%E;|xC+pBKf}`{*+=Lev`LhXnTt!cTS-UDhqNvp6_Tj@lNBH4AXDc&uM~j2+gFf@X zB4j-Lb90P;V7e5iy<%Umds#hH3UkJ=T;4>NJiq8>ZYecF}&gjh3Q(m_g4 zB;%0;WDX2;k=1+fd%y=Xk&i=6Q`!t*X1)bGeQ;wMaN#xRaEpD{Ih*V=Psl2xgdhY7 z|CS%jbwHVMToQaqC2NJYk&_oS@zOQsmLpld^1KB|PQe@rqnbIi*7LsZn+yjTI+eiW zya?^oV<&E+g?1ZFQ@VNW26^L4=jb1j$}YD~HUd!n3SkNxC18NmvW^mT4*^bjSH} z0%moaEH(r-CspMRJwhQOhQYGLc=GSn;NRHvpNUs3g_n>tcotqzi=N-uvL&@?jemV+ zSJO0FHo5{8-P4W<4^cAV=bwMGJXIu`DzBU0)*ct1Ruw~NQ;s3`Jh2Ym>KGh!TPFpy zH&?;T?vv;TY&63q$>dNZO{UsvtjG7sNp6zPqE!NHf6U%s30AA5F`>^YLl`3SkE0$U z9NCOMn3k6nqGgq4oS7hK(WPJ)1QNxsDW(-*TEvCWw#D#j!CpINP7Rz_m|^;-0Qz5PZQvzWm|UlUhRwTBc4_Zb5M}hRJB`oBT}(S8H7d zZr&U0Z`cTeFHr^TTmgDa7mVL8DJolH4x_y9qPH@Uqmr`ooA}>t8VkQ&uYko_<*xDk zi(<5e@5AWHHGFpX*yQqNB6Htgh#Zi-R{BrVeVbqGw<$GP*QXj~%(LDtSyv7!&z@wP zqUsK+M9*Er&lf!`Vp~7E=K%~1%E{1LuE)17*h-EHgP5?3Vp4WidC}H96EoRe{t1WXm}V1twRa+C(f&6qHSW?&p~6Oj&1;JQLY7vr70EMq3q(8uBK zR}r+s$D|944U!qjx7Op^1bTIwYD&eh9-|GQ5IF`oqtfS)_;`b^o-5LAsW>cBvcbo) zD3rc63blR1hw7^&foLxe0GAk~k1xJ3A3zu@adoI`%g5~7#0g^Gi?b>!))mV6kN96f zV7Dgo)g}DO>qLdMyWTJK-y-t1rA>2k>wXV;ywgO#9A6G{D7^Z>VQsL|TWIMI?0W+5 zLu8{8viw(@Hs@Ac$B@7Ep!h$8v<|w>N>7Tc8e90w83C)=A;pAr&K7WkqYY(tXUA&@ zsp(8$)?>wOPi;*BOJBHZc)xxxIKTCB`vixvn5Tbdbf(&DghYbfNJPtQzp&;R70Sos z_}owS+dCGd$|!!J)YnG*Z#~wtUe4m|Y=`s>C=X?m%tUY<;Re?Z4?YImPX3%zo5-K5 zk7gm+v*YPm*=)2c47gi0g9d-o^67yyf=}WrO(C6*lC=}ibL?^Dn13i%6{R1*#_)dJ z)K0GW$FMPXanm3{)obrXnvhE0oq|9GtMkxz=MiB*kj;!`?qBB`&!e2k34FO(OVVrt zQ^L>z#XEJ)t9Os#+(pfh$@>khj+8a7IK;K1u%mO7NBi#eC9~ z_QZwc_0*Y0wZgtNF-(_f1EAn;ru{FlR3b#X9&Y}Dl*uw>V>RLEkAj^jE>6(|_>;+u zZYhoyOb|=JYy`*Th?6uy}G3x9*EBI8_jWtYX`0a^KzxDHpF`S@aP3Y4L}ZKIUQNagPa3+c`k9Tu;vO@#BT7l!F$;gMn*s;H`C@lRW#*1>JP(6;N=o zLR_M6OQ1o27VzxPw@n@pqX=JF<(|OG`C&~)b+nRGrnvpOr35czl>b&ST@kP8?pTbP z?lh9LI1G*tMp1lHVTv-@5seg8-szU|L$G3YChesR*4;61LpZ`dlk*#rWRz%i_2V1X z(GTIPu#Jy$;K*20TQ^M9*cr1yNrOOsgNI=mL?N!cZx@Jb_E~f#6`qjhd_Mpto#mPU zhYnM#_>bTJ8O9i7sIVYKL0jL8yxmfd;2|QqT72M%z>{CQOaXv6+-`0`zh-vr)?|%d zH6|)wtM1Y>w_To&LWpN%ChAwO+IJ;L$^vNDfS2pYQ;9!=O%q2aY)zQz%pw5n{TFl~ zK>m2cFf&z9DBv4R0r29A=TgiZhz^u?*cbB z9qWlf0|k0=VGt57!`DZzn=Y`>_oioM-tW$hD(n{6`UQ(s1)o=ORsw%e_QLKspo8f; zgxiRa;4YwFQbWz#*Ej{K@!aR}f77#|;)Z0Eo!4&asM%kjEBSQk7XN5`w^8YR?dUX4 zO451=mS5ZKt|^fTP4IoENHN#6T4_fR4h0BB8~Y_x#_99Z=m&SvCK&nV|pnPlbK)0Njw?s3c){|Y*qy_4pu zy7ZUkjxdzSMS!Vtdd+>_m+j+|w%lj^Ex!rRE{W!{oej^dkFP#kq~l)?4w*TUXj%Bz zOd2|0Am|(108DGq&&cca!g+<}s8~Fl-|wds-#mQs%vVNO$$hRyw~IipA}21sxp6ru zfao*eC_~VGE$+EO%3Z#_-`UAVK`3@Y73-J=p{ZBPHasse(UaYA+^dF1jr0y)uQQ+& z2XL>03lQzvc%$iN&6j0u121>@?fk<{OpWBLEfNnPm+@eOjAAM8GLE{1e0vd(s?pMi zdj!Sv|2rvP9ZN<>+^6{tD8N2aVeMNuFfLA&^AF*@21>rneYcCvEiWQx--i1 zsvXZ9kYPy_ChHGhq+~Hx=c9||YM{W3-+0n(Nskxlms$<`yHMZy;;^c&s7j!uJ0SD{ zRHsBC^k0Cc_0Z-8=*_LaUY=a*{Rt;{BgWcsNMEuLSrbE**T0{FgZrboSHVbmiEV24 z!FDq{s*`gKb?%_M)hJIbBW?Yfx+dXcsTNM=1UWS+PDefaoS(M%S6jQ2?9?-84){(4 zRUe2gms^*skMb`|0#$R&>S`MMlCt5rJyHkV zFN4?#;ed_@OmGRhz6L;6i21adtN*)CL9Rs!ykE8h)uFnJpt-mwpq|3N+dCo{Qw3@L z;Mikl67SFq)qn#}o)>fN985YPPT)%?B7EPGk3wXeh-{*8a3_1NmLaW7R%~v3PC|Y+ zzq{}L%hotHN}Pp+Iu$s4I9Nkr_}(evqsK;=^N*{nTzl;480pO!0fwP=lx(gAEG?;I zp_;%^B5w7D6{Gt6g#=C0Hfpa+lq$@nDZS;qT16ZFSEOMpNDTiaHK4TEzvOUSBU>Sq zod^7ea+tuLAwXlJ16%C$QP$T%a`ibjj3_;bzzR6&3s2XD?X3DkYQ6eZ`e?Zi#^FAc zM4p_AX78kKKcZ$+pB1o2SQ)jko8f*TEVjG2@ZnK*bLsUtXy0Olq78?%M zM(MDcjjz;qb$+d_dqlOoh-!!5bVWRGbwUQcW?X2sh0NTLuJpyC6A3uwPpozIPpXiw zAADfWYzXj?W{-8^$w}D1K&j_giH3OqD{~d_3%YvM#(E`Sl71I3@CSaH1o|$+8WlN~ zXHL5r#h+Lm2LIwo4VNt|_US@o9h=|I^`czNc^1Lk1|0^C9gg?TDK`jI*fanh&iXJ3N#wPu-Qe3;nnkJOqlo{#f_#ZIa?)sj?`S!OFW&f@KcPw zVsC78Ds;%eoG4$Fx(fN5QaJ`N5?s zOc#Und4Lj85Up)_)981j*5W1^`$T1qDDkTx00?ZNPYGelxo!tF?~)AD2E5!3$XgzvgPkP;T z77U<$x&%dn*o_@b>Ex~F{#Hg;m~L)GNaE@!b(J&N>1WLgpXi^jiC`X6HR5o^AU~PH zi#u?$y`oDfPx-=%!F)c24uj{)e5Z^X$Q)>W@*Z%|sy}h9+CXPGB=Tcnu`u72W1KN) zZlq%czo3wYpm^7wjE0}dWaLsbvB4=iSl?0uQkw0=xLeb}W6LQ*F}P{(>fX}28V1o9 z&pdTu`vwBXGmx)ywz{m)8^;&Y)=(Wmg*cp`ln{hy0vs6eLS*7~z|i04ob%wozpt8s zS9sK!SNeq6$U$a7)0!10pu?f27g|dB)7G1aefcUNWh^%ajY$?ligQ2odT`?AX;j~@XE?0Q5Ue4h zGxnr_ugtH59mtbH4+uc#bSVznGzY1Hm8uw=;u4kdsG?4o(N$M4BV+0Wv=xcc^tYOL zBv*jgC5YA4MBT3(dxj57{&KAr^R^R;w#*ACiSUa921EA$mQQxZra<$aydGZ;-;E8= zNd$7;)#&u-qG1B5ABxk|!0$-0;9Jj%|Ks)(NTOQy3Y<=QwNreK4dLwQ;qMF~-3CjS zq2x;l{_R0S*FT>Aw1)Y4zJna%(iC`d!1R?7yitTYhX1MUZK!N6kq9f=38bIkjr7%X z5VbN!{t|g-4t1Wj9OJ8BLF79>L*1fwgl*R|ZrcdRaRK7`n=8)|>>dUpeCkPf`X~nn zKaJ8w%GZ$SOuF)={>XIXU7xhyXGB(wF$RzSGzqI#33D9BGovj9+qSq!<-cDi{|_Zh z1yXzrQTj(zf~48B#4{%2mX*0BW{XXq zv2Gx%*r7FFj`zF`qKbP$xE>`j@9#`-TTUeRCf{$)qMABjA0T)YY@aesEH;}FRR>H# zfTMw1x#Mryq{9Xk^fSHJ=w1=jM&4B-VJ040M1NmX^Z2 zuy!MX<)66IO1a(fOBI`}xNk4Xe^vK|hy`*KY`sXxDuf=nxB69VW+2%zu|x4n0v*;Y zU_!#r4M=IMm70*(?mu`XHfHk(YscyY_W52;e1aL^DMcDW!yZ*rLEh{?L8bs!Wq-gY z$G68;mXPuu`f-kDEF}VpQjZ-js4df{@Ayau$e?z)kuU)M#dc?3X?3ZV$aYP{?g`wX zpchpo9&+aSe?BmOXDNhv?G4^DC61jo+2B0hL~$9+*@*R6vyROSU_Crz@|_W$2BtMGAL z$26M|Er`&AH*HXB7)r>bqKrUXy53~zQ=4IoTX6T@{~fE8q)2g@>qyQKeB+-x+6H0NlXl4&EO zXJ~-mMSTX%Vmzl@+q$))E8_uevHmv--q@p!V z&y15HVLddq&>^hj(M3{Buz?>?&HDbs)cyV(7{30l(V`svc@4eBaUWq2$Iau>B^|d3 zlV6I1!=iwc?^7P4>bo^d30}GnbqAnAgSJIma`SAX&~EAD*bP{Sh-Ie-gCgUa@%0s} zw-*4oTs&*bT3!l+Fl3Md4C~1(ZcQ|wSq5R1DXNt0?9@WRuIjEN(GU*A5&@S@%oC2J zc~c5sDuY;qiwwM@(I(B%sOt#5_K$SdF0d}tt4q-4kZx&y)f|Ol5d(>9OGqgm^KVf@ zz~l>{k<)2zFZGvjJ^|w@OKgWz5n~c?CNnx6*UY=ocGl)q^u^GMeog7T>Cimqkmz&W zHC&~rK)jlNDE?K!H8ax!w>~oT$ae@n+6s#x!7Ii8t~^lChB?NQD)+mz-whlpXMY=& z&B4c0(l5YjL(gfXeCS3Go5C|spG&eo3`$XhZF$ldt!fu)?yZWs0BoQ6|8yDe-y#wd zoNyv#-O87B8G>4Zn8&!_TCUbU>6Aj@ern(bw%+=F+Xn$g8rC?n|c103+)@t_)YfQ~LUx zwo!(;Yz!e`Q>b8RV*%IF&CrmDR#azsp{&$Wu>Ipw)>Mz7=}4G77L(CRQ3vcnw}C2oFsTDkn^sg_&y9{VGHV+oRCJY za4A zc-K182d&A+>yNZAl<|L%{7BzW6~>_wHzVH9`y6ASi>{t<+tC}x_|Sr3DX88@Jhb{4 zk75`~DrL78ap*5XHn?yXx=z{);-EZR9y)Yd;|Md48s{GMvNN!)P6cawAs=hu!r(_F zWB%ZX475WNTmALd3qDxZOZ~eXlwsG3T9TC=t}=3j^!Ek39Y33E(Gw=asRIqYd!oNB z$ya8L%1B*+V03`~_k=3QD`LB?tmB1DOvS{j@!6(<6m(XN8~GU^Su$UI$}2W1(f*%A zX6&={;`U|iK+JNjqwx{`fMqDa8x6x#*3Ih46KEORon({k4-+e?JZmdgE^SrsG!R(3 zA-d{Ps@e-pU6hC9bV%i*CI>qW%{@f*k5m{OrotF654 zO408RB@(%*4>y+n&hDdHcT}b78VGl|92TL>_GeLkQcP+d#U3}8n<3LcFfZ<)4;idX zY8nMjL!brsSVMj2S#@%F|MRBB;A}T55*T!w5FWScPP)+t_PyXGVD(>rX=0|)y|ws* zMiOI#mCO`)Hv1n_;uLH3SOobWo*q2o1|^)+DR zyJv-}KxJ_rRaXsMcBEcBe+NIg~`H*sZ` zHZ{es3(P$pStp#g5{Su6mw1X3w(FfUr~mK`7|s&3PSuj3U&$1wF7QZ0iNAszTqX;wqSs53y~&{p`q>qKJ|MBG86q zpe8{*EqZvDYe$rP^Gq}ud&oUG;q6dwj1q-q)j+g)gMIUT2LHr-m~LB7%(zjfDy$c8 zwY(+3FLvi4#Zo|i-g&$PZ6$KGdBA!AGc$@uj9_lB`E&*mpdDUNk{>lc|UmFYMIev;him~N>wY(5sUiutj17U>V$9<=uCHQkh zuDJ1Gl3FmkxyFOrtsrc6-tuH25bTB@(;A7i#84&+61vqdmi+MBqiZ!s9o>*#omS2M zIrTCD@I0rlo3CaMEK?`YBjsY zx8F~rD2d$mOIxGyybgAiI)KvGh}_)iGO1$b2hGWjzHgQ<1A%{-MUVvQEh%3N1Gz@wTQ?UGr(>3TVOAd(V^6uus94I{4nc3}w%;Eqf2)PPXN0 zj7WEbMq33Q7VNj%?KjTWzST;Lt@oHWb5qWl0VOqtHigfNkgX-`Nw|q5xZXLm(YlJQ z&5c-pv5rg~wIqeprbgOLc7!do!c0bMdc??7 zo?@Utly729;KSjHc-W{db6pG9rp+yyGDxMr9X{$www6w_38{gvQF^GjCKo)Jo6`J5 zNWNr!a^O*8CB{6h5QzyuVf_W8OaRo1R9c=a-xHI`naD*(lC{jNatj4E-ucN|93voh zYz#stsm-&Oo7GJ(&q!(plj5_t0aT7kd6|AyG%{x-2=#|G2xvplcOwZqUwfzT zi4&CXzQLGq%Slf~0}WcMjxPrzNyLQy?_npA+LD&9=tM`OzdHt3vKb@KmhI?2*k_Ge z<|$A9HEjHzqpxxGZyr~-H5x@8X$k~AO{7tCZs8Y%u=S%l@~MDT`%_h*6fH=GVG0#> zNdA9X;tr36{&y0=C)_Z3lI-Z)Wqij=Yks5gD^*^q%dTGk#Eu(TC|KObrQZ1ZDQapk z4~CC4OH`;{0V(9>c&Z=71bv}wDNzpf2l@0ME9}vi7j;i2_s)QLLHyeD&gGonEkoI@ zg89R{WY8L_Lq6kEYo}k!u3-K_=?SW8?Oyy(X3<7Zmb+c?_sSgOo_ifvXpf9bp~v6w z3`56eJ@;p25k!R*>W*$C-5Qu@p~d1b=^%?8wWU0Vy(#E$W=eoh%PDApK?K@+nkS4; zwF44&*|D0Pd+-@fDcIVG_UgA~;?H>_2gQaFL^Pb7tPNcT$*upE*8dyx`Xa;BwaF_J z)HtO0Onm3?HpokFl7{QOC+aXDGE11$_-Va3_-7o3yYgq-xvKwg*>|0apt2LxRnT+I zH^mkehBdtI0!QkOVSY<$2-5i_ajiQ`wRR!Sojww6OGI{=uwY>i6H6yOf<;pcNXoAs z&%?f}b_-4gl)hyb#B-}#kO*B93mPe1_~1LaA!39p>$OH9c%~v}Ii3?lc~rs_J1{>X z$mWrlL8I7F(R0HeFd%hA{!M*pllyu~H=B7FMp^l)v1N~1DrutI;hL2JPq|+u=XE-j zJbo+Ru(On!LGF4oQ!Mz#V#uz^g6W(|jny|&qbpKB#A>p4yEb9rH>i|hVz+30fb>$R z{4cdaqmUHlV8ZD$mZ)l{e$NWv{I*hXi$_23qW`ew>Ps}&rlByToUa)Q@azO;J07!1 zE-Zhlzi%G|-BoPE36y1lYdfn2-Ps3=6!b*!BALKoBxj)&d1<1fLv+`I{K%q}(ZM$D z_z^@}bA=}8PR1h%Di7kMy4?_|47m;QS6d3X4TDvaio`UQHzL-dW%e|+Y3`#)O2jLGhue8QGrp0Q~&;r1f?k}|fk7R`$jUNvhfrjeNi-kta8!w=mPP@_= zs@Ea0Ijlt?xBOUPSWZbmITTKVG=!(V0IY`35 zB%q=n({gEpFFqpb-7gif(7|9$=~YwU_`SEI^&ANErN;~OkQ54Lr&#tlr3sKOUhNhX zoSw;@wk`%@7t%NmAC+|7*47l`3f(?qEPMdKK3(yK;K@Qeb$C=7EF8#?TnKs=j_|2^spcx1UI$S$#Mm+X2E~~) zAZT>SY3Vyrh~X{Wa87d#PRaqdKs0*~7D3%x1NtO%-9~c5xUb~J=4iV&8C2df=m-_j zzv)!$;^k@ME{xGeobd+-lyaRjh!}3)#1Da6GR3$>z!-nmvXjb;E5V>tZ64kFvjz3EX2>|e#8FkQg z=rfu8f*MG^RV?x#(NFR?jidVu+?k?3+oocf+Imkz6lv*RF;V9mqalRU!nA2_{!YU` z(X`SZiyAa>(gfVwt7R#&Ihj6`|8Vuxdi@LRAT=!1bTv)SUCJD_qkIG54V#*$CXuQh zVnweZyRh#j3P#=&`)0)FP9XEc=jSo@jW;SP&*vp+UZEHF*b#(L8a}d*_9KfGF>JBE zR|sftr=XfDwaK`T?7M0ji<3tKE;6z-%Eh<-o--*+Yy{eJGK>yM4$kWsgH=T#KM1n^ ze^dkYn)a%aZ5gZ3J-u=-no`yZ@BvsP5LL<#iC>)843;NqjM7e42H_thM>zve1WmPnt2+D-Oa{aXhfnl5u7Xlc`DhqG8R| ztZn=IfHK%zz9{%^Jk=#`)9rRX_c#;5uGb3K^AK1aL}2vbn=Wfz1Kd2hec{2|phz(c zCtp7}@F9+y(R#4)v)Tjjp(;f>)^RFoxR+p4{x82@BWv{dil_EkQ}cOQC?7a}h-ESy z?l)r0ms@5lKZT^Pm#A?Q0RDSMhzy`FZt=xO$+0)sD7!Wwu%c5Di#XNgNuYH8g%)wPV zVN4fBs~@jE(LV4b8I>I;0+y)ep8X&n=sXH8GG6t2rqY;YcCw+sRY9d5UI7n~1Ty_U zWX5}a9XY(d*`|a;+zBSpn@d4vfpa(nmt5ZDBFr&O34}%8z#aJ((k4^Z-~K%+To0f@ zU?xL8g{xz>t?zYlwJ=Y%MuK)=izHv8NOu5;y=RuHi`#VE*v6?=5_yl>#>(y4W44`+ zKfHU2S=i$$ycCQ5XR{P`-MfJpGX{Fyonvr3I@SMTVU=i$0|nZiQ7y!HRR7Rd)f@@` zP*wNSVCTY7z$Uz2!)i%$Q}_})+F^E?gA5s_H)zaJ7C8^%>h0k94lMsZ&n-YyhV<` z3cc718jp4Sc#wo+e^ujLZf^q5X5>HPn>U;%#zFrn22e{HY4AsNq%WXx%HQ)4N=)Kn z5Hdt`YYX|uaqh7um^pMSLW<;jU6~X}Hl4zRJsv|TfhwZ;^IV+MDE93bkX0IDJ;8N3 z&?E?|RLw`%{!tNCfFFZzKP;CEZw-jk9%t?ciIUxo-rSAi1R_L*m@B2~L%_{vVqES& zmk2j%hxx)>fIpjqgr>B;*;u(&2yt3cn}C5kH(*K-{pL03p3;W`&3(Gi!n>nzu8!^e ze}3z&*IzYV=FV#yw6aYLLy@ z4_%Ta#!`4QOqn?}s=odJ@rJWKduJH9?VTloL1%e$CxvaU&HDS9yQn!|l^FVBoyClkwN@%VQJJ>rrHUG!JYcqrPmRJ7 zKv}z;#WU-WyQ`T5JG`LOk9nI!+sYkQfvSi{n_>{~#5OvANnzV_-lVIrmv4#ErmWP7 zWyi8h8q`2Wnbnbd$z=W&K zd~=Pz^IkaKT!aNrBMXm9*FXf;p!{4(SW!;dGmo1!uD?%(R92Z~ujriHAi#nqRn3o> zqa=M7D8e|g29Lt!UkVN%NtV)c!w$XG_?@{8`$*wivl09oX%2%FR^-2BT-Z7I3?O&>Vt4e?qe+*m_~D5?_M+2$ z3r%$;Rn3M%9EZOhw@EL}Y5x8NsneFTqh;BQEalTk)=6Q1mU&?=kp}00C>|+3$}8Ol zC4&OpPI)Ciu@x2i*}rv{U&D@o%B&t+J~Xp!|FS_X)u1?^QreZF(^RR)1ZV2*^J<AF?D0_r_dUFa&ApukzD7H^*{t$6VLmn=_7B`mFDiHmY7VKthy(n3EONBm zvlVOLIql^&z&|+MNKW-UCc4`q#yi$i0z~Q;Uv%zc%k@3TYc^DQu<4~Q5YGvZBDB_& zY7w_iZ#V9Iz+!*5uc64-Mah)cZ5z@z_upnYVG!U3INU7LyX*WKhyy zEhghH9)s`5z%pDx7|^qsMr512T~lIrH$DIerw0n?BLPpFVZ}{%u0Ybj14=P_JRnvN zIttDgDQH$W85vJb|AK)vHK$RXIt2*_+%}nv&;<)eBPM)gc|M5;)k|G=z<*R;yR(YJ z?(zaq6joJulLUI*4tu$IP6^#e%f7H{_WrS&knNaQCp7(c-It=47&;c4O{y=_gvjIA zETeQ{DZsB<9KCiQuC(>93lKJi%_~x!Q~#>Pt~lO2A>b^9QJh{-P?upO99Ar~m=PXfVsObKbDHgb4xl6WNxy$?)gECATiw(S=HG zVUOq)FEnnjYVb(0_s^9S zCzoW80mwN`Ra-&%5xWUv+&+n3*&<3f_j4b41-XhOkZxQiN(<( zB`rLZ!uOIDcdxF#%k1|QfkTc0oFrze^F*uO3+xuHKGT1X*bL+_PyR7K32%nQ^W?Wu zEN0DU>fGsMtH9dLjBWL|;fM-q#yrovhHxMq-0wdN6YD zCf7u%dN+8>E2a&}Yse0~W8OVmOg$)!@dJ$-J@=~_AItj$rcGL^7`r_kq5aJ27}IgF z^yWRDlXPs22dVGpc1Z#f%z1h#lSEHy;D{TQ)C;A>%AKg^7yWUy6AVj^U9L(Ou75}4 z6j$&=@S)-MvQdy93E~wDXeTbm-J~UZQhF>)!zBxevHv(_iJCJkvako;=@ca^zAEQG z1MGotg`UjU47XG4|2hXZg;k8cHrARzX+`(xA(-g4@Ek= zqOZMGq9i*hpvI5DH&0M~tckh6%%f4=hLit%5m)>A{M^H)zTWl1;*}wfKD@sJ7i3L2 z-f6QnHpli=H*JMo>h~S`ZZo0h%84kkceBCq;I2756D}@Cj_&^nf_^r-Hv##Jwzv)_ z4-tx;;qor6f6mj#$F*peoqj7FugE$GeI@xGRqfrd;N3gMzH~Ge{*c@2X zU_YzP@6Tv>G#WTFA67wCUYf})kIa&ZCSVhve3RonKoEuC`CBs9!*f~URd2KnIE}7*U6LYjnZ#4 zJ$EtiI%#fFW3UVqge*{MCSuu=N9eVX*+)Ra+*sg?MsE*F9e`PXmnWw0{W5r`4Vucm!enT3Efi0Q?8O|$PZ9udHW<)* zusm*b34)0h|6gN`M~dm(!|0KfO#blxm9QD`m~oNdP8hvgCD;tpB^L|kLN03C+PmKj zJHubaN+W4$+y_4hhyrOGD)!dWo9d%ElFJNn;v=6)M=&p2$2p#tj`N4DaGDN1BBVm6VLSy@x*RYzs zTdLI4i;M{yk|JCri>Pr#u2n9Har!-iKenS6`U6OxJlqykTRxd0^N-qdf0+cOBnVN~ zRKd{=eeko8nc>2khGO=Z%i-iVY7y!qMRIwT-8JB?)#cv+%!`7qY$v%1y{$E63pzUm zUe4D9PiI~RgFo9g>S`bX<=iIy=GnQ8Kf8mK*r~`t=~yx8Ni=0gtthX3zdph|)|o)N z5fREmZ&Wu@nNVzrmAAy2|Jz!$olVnSH}TmOSUtdqq=Z8_(|?Hd7jur28_AIV1A+yLJ9AE!U3vAAFyB^9zoa#eVFm z-T~m$D4G`d}y(86VGuVmDh2hhl1?^9Gs5Zk^?PdS<60j1| z_>Du1-)K?2bdTcx_)b63Z3i*Nf29rZa7jses_mPNQ7 zkZtGhu!X4OeHsnH<{(j)J7-JTp%o2N*>!PD{OS8h3Yn}e8Xoag>>5!G?K`2$c zsrG~lc_%B*poW`6gdE#~>4ZnV;7WQfpI#4tGnF^aa^q|Sho(z7&LP;L3|2QvnMElB zzwg}yz0tq+UPWA8sFxXFJl|R7ffi3B#8_Sbk&iTi<(nZYoP)IwP_>Lk16$rg``=|4D+~4(FWUWt1T)&g(k=-4HC}V-Ra2J zOa1bJ+b4ba|GR76F-4^=8Yfwu%?$^mM<+)2IImzgLBal1u&Kj?OJxlw#o~J&I*Tmj zv_jDRdxpi>`ek}5H@ zBl^{VrxXVd(t4oD-(wRAH0nVUIHy}PYbtG%+psU<>IYjN+DDLCCSjsDTsZ))^qW!qlyaKxM#txkxHx2lncDGKMDPHO28P(3#wHGW`$9Pc1!g1D zpl~46C4FL=%HA9u5^;SKr+u&eiuu&LFafd+d?E!T8)-DW^aMypi4@sEEFT-@WT?C1 zCqP|NEcv2f4`bG|D7g~)`ymJWHB(w}GKMYtm@gw(EVqpO(TNI`E1{Rrz= zQH&~7b5LWHS4kP*LX4#&Vq`yVp@$;hjD>9_K5^BxBMTV)7kEpYC+Iz*sU$#hnSCt+ z)y$IPXz(rJ(w>`eK4F}j>5?VE?RzpZy`l@&+#P+_|3OFo5#5H3F@4zk(IDMEd$4vc zf}JS|Fkqi0SWMCCJwP&?I=63T*fR?b7uP(wKvX3&I!;yH^B|H!_AF7}@( zVP(#_V7};npj$;zE>1xI#zcDkwXC-K5zmiKb>Ar>p3f%(S=(IqLFtchAGQPFc*_db zJxw7rBLLG?%|lh{^xJMTC0gz~(?=(uMW3WRfu5&W{+Y8iF+x&>jOyhIf=Q-e+0M3~ zs;MyN*9jXJ%Ngbj&~1V}d~TC@gbX1W44se9Uv%Exewx4sgSLRJbEetMGUmHZ)X!1LRxfj)LqG zV>2aBE_W($ZM_V~+N%8VrfDSV!Rx{YhL0PeUWDQpe0B?-s=qJ$S8s$idxf#7w;?5a zkp86zFeU~Wf1Uvi>PxaQx>3*F5<@I*DiLSf)kO8@7R3)BTOl{cPCAA` z!>^r+G^UiOOMlm|FYAXhgh}|9`l+-YGN!ccO;ib16=RJ2Ft58cXyBaVisC;5>uMSX+7+^s>xKYx( zig2kqkP5ODmJwL(eLDJpGu0!%C1tZfE z+r1_=y;_5T6wna+0r2>hFV;ca;;CaSg(6>XBY0Kj->&f8@qcja(2D(ip)3O`EJmRP z-mpRe2LW4c_>+5+CNrSb>iQ^SS}GPy@s-?Q)*YIC#5gU!%IN=vAko3$J)+)Ll#1f1 zA4_qMK-g?TV2T(q>c{OZNUpiAs3DH#Vx*E~TSyw;DwyA@x9NBn@08XEqv98M+p>|8 z6uB+ApO~=tJNJ4+BV7p0Uh~9{<2xc5CKR}&{C7~d&)eK;cvAQto)Nk2d0+leiq z4X$&smhQ}YwfAA{|Yg? z{XBWm6AAs4ej;_Jjp>DNsN&HkpgoEESf^|x=$2xCwvPRuZH`knJtsZzlII#-1e<<% ziN_OjmI^c~PjB4yn!QY4`82>qU8aE&)p^I>s?waw-Ga_~FXzHv9NzjcE~(Wx`?8!% zsv}i{b0&7d_k>58!^6Bex8R%~pdPI5+WV=*xw=S4n^GATQCXDNy@|5mv>11Z{NBiA z2NqEsU4RL7{ZC8L@+2K+^;x@HV0GB=g%Ykky;nt+XvXc)re;4 zf4HV0m&MbxU0!6>yxnTS*tnEhb&ClC8;-7L+4<;w@Ijg50bd3f>1$;b~XHsy%QYoL{u7!8?GK6 z#Bm7p(;-F?{0R>vG3cf;NA)|27roZEg=htis*itz3K~!c)SP?b;zXQTIl;vDiOT4> zVDuTW&XLST$wcys%wq2M)CBnJgu$S99z3D?l{rgIOq0vnUS~{@vhWa+d&=Fz`I{j* zF)E?sEyRn?@|ngk#X?_g{-Og9W3p+QIKd8abAyk2#GuhJeY31(KcxY=3D z?rIqB{7eDy`fg~^*Ry0no&t6AM@23zvj%+gEuHqZn zKQ7dsvZp-Sx=O&{1LbjAg^Re(&4$5MGYZ8R>n#`#R7qYg%M}8o=|x*}`Dp-MlBc!w z$=uDKsi#G{GILO5)L$=Vt1$$CdZ5~@|3CH{%^uO5?IzlE4P?n}`-avywTe_XSg@c- zm4r&DPPo$X#=g`uf_Tv$1s?-ty2#n`#u8KDOYSAVa-k%O*Q4BBcY(QTc&y&>1OB@AJi z!al=jI)>}Vm377jC0S-AfX@D!7FJnlNoHIiBKOhDElP~Fw@`>JN`7Fh;w{v8e4GgD zLOjT9;$?$c7Vb;`_Mib&t9q~I+Hl7n0_WQSZ=vX-M7slOja)mg1h9@JFL=P!giqN1 zwA<(oN1GR$3ZCh0Y8Rp~`ZzGz5b$axdLm#UgiW>XBXFt{ zvGkPx5?cIB>^!00d9;gYKhY4|YaT+QFtP9O?+2aZ({lqso1y6`V+6BI2G9I1Ss)Xa z)lF&Vj=jv1{j}LDC}-5#?@3CFgs2PVCns$fZDBHStxS1MTlZ$QLuy%&kRS0HZL)f} z?zpBB?G$67mN0=nvl3*BGMb!2*|bYLliPb!bp6z61^k(Aer=+)e_KI!8F-e9sO?qA z2SrKYg0KgW0w>6pIH1E-q zIUW=?U3{3J>W#M33p}~&epiH<>P+4+2)!tLZ_d`wbRNSdRE$PjCP_#P{A zo`Pr*m?p5-@W7UuwfIp(rbS1RWg0RakdD7C?<9iD1X8iU#Z{!Nu7LF<#xzSMMvKO5Wm;jKZWD)W62n~OsEUsz z*92UYoj_)zdf4&kV+>g804v;BW$8dC)uR68tmcgn+wMq6FXL2tTaj|6r!sg zl)w5_-G$SZw8qs;AgJ{%UT~Oj7sDZPrK6Q8Z0TPb{liMYT~-|>LSiMJ`gv)#>~!Yw z`~B-c!icchdCV4^6@kH?grh^dYX?9ELelSS1@`T2$7o1ba#ok;^Yn6^WPR~bo`!Hu9reXdqv0aCiTgkh{OUMh?( z2a2$p##VqeH5kouHzyqziW0S-2>*wRRbQebJ+%!-X0|~7$*$?sQT4I(>25;CU9?$a zm*7jSF=N%2vLDyQ*^%rNHG3C{BT*#G``cBZLHVi^v+1dm9kZ4I zgJN*dmJm==9P^ZcKG4@gb`6R02KA$RqzH+<*;rYhF>@##Vjpn$@Zt2ZMg}qY3CgxO zJ8eseOn@&vJB(3`)*9g{>5f_4y=;CO#qmbU=(Xu2DATEhwU*t#)(w*y$0j&5dI|Rk zk=F<+>vbUG1M;3s3>N2+2WHeHqsUy4LIx{p*xwU@L;{Ei7_X}xd?d=hgbKWOhAjb_a;EQTtWuy6ctPvS*dE<4ZtSyLtr8za7+$(#j zHhgxn!w$P$MWVbM-axvMW>UjIhR!EtupUok!`*ye(U8p%!X+#EA#hZRGCt@)ehi~~ z9gU;=cEv6bqz0KCNR`AvzOwb2n`$RyS`}yl09<3n7{$h76y_f%6zdXq6L<5hmhz61 z#nDBtPjV3kgAOX6r}1lHN}WLs?5MHq(iiurelBOCpl5z+(H3kmB0^@7J4bgxw^9D_ zzBns)UZIP|Q>aD@;(+T&2Z0d~q}2HkHqSfAY!#BU4)rsL7s5ce0;zS(k#xYI-OoE# z&ZR*`-vcECCH4D85V3*n7v&Wj405#?*uXOh*gGM|=81Xm;P?1{CbBHjn)a9$Ah^jP zCFqL$Gu#VMT*?;u7r-O7B=Y*?YyaQUSpCVl@u}v^xHpwbiIWteu~%U*;SHbk9A9`^ zJxw~Hh0O3vnwBoT6v!*u({U8$SU9#TcZm7T7L`Oq|^Yj-Vl73;VjUp47 z<~OF|yx9t<7<OuO=3@6=!lz(La{1R$LpT^ra9M5oD+w+>0(c zW$Yy)bpUu|XQ`_@p`CL@d~hj|H^RQ_4t@Ig@){tbl`Me5x2TgvR_a9c@Kd za-ZXB$zcq8A3UK^vjE**5tJ3~c;`@f;5N|T@YH=>B}fb`hY3Gf7LXdXwFlkj)C*wi zirUop+CaBy3NYNs7-!sBX@O+AdP1FDO;Y%3kFz{Fbjpdd28@kyu2J<5KV4wHH9p&e zf>N_vQ$RO5ItB{emI)8&d7#}z$X;g_Hn^tEd4#1;ZL_JpEJXdW(EXK$d3?ww7re{t z5O08ueC7Hh$wvxzqy&)KT490*5$Mh$bCn_dgdI!75rZ=8+ocMhK*NaM0IGLRe(k5W zl#^qU$}o?g+5Wumc&q4GREXC!OA4hm2!PyuPDRVCs;%LrW_FKEF|xM*u4b3GP<;!r zh((-X9YwXhkV}-li~cP8_^by;fGEOM_fKQ|y1?M3&{Z|VYnrUa9fmtUF!?16@)Z|U zMT}ztAYoqsZK{;IC+CAQYYAixqxMKZ=qUY@S&Xpfx+PZD`#MRT=MrgC;O1n7{zIW6C{82EB@{s5nlHwz}+P z{?mR}S-}**N{Z$cmXkQ6TtG{Z%GF`-MBDZyZVoBrlIgHz{B6ibo7J^8x~@Cd3lX(n z3W)oD>qbV@6y-THwvKBMg`-v=-`H<5IVkwC$;*)o6mf|+I(KmyaZzaJAGg63fGgW+ zfXBVU?(9w=skDv9HTVPkL<4loosy!i>D-sVWO6wow*+Sv{+~l889BvyK|O|ceCn(0 ze==~9i74VeG*pxt)1^?LGLNDaC8YjAorae+QFD#vx&FF40hO2-KNFa`9rLQ`xSS6v zB1Sy)Q(!r)9HOK!0TvAug9unn6nF+!a;d{b9s*_xNN>qHxM}_Upni=2_@V6V0GM3} zX!}jf^Qm`c!_Lq{jGoC+$7Y>O4hj2G->CbN6Y)g`wp7FihX6l7z`qr)EM~kn@Sd1c ztM)`!!sc@GEgLB48k#50MA7;_Tfz!ayf_6GZX>Clr)Q3)4FcNo8&mZ z;h&69(sSkHCNhZPJvJOyjs1uqr$1>#aIDppR}%V%*T+b%rU&g$oT2z2f*N1To-MB@h~b8n&eW5_*G; zUh}_)ts)WIs437j!YX_k37ZK)XXfrw+;&wNWU9NY27ry2!$=!i9#Mi1Jbc-)7Q8VD zTK?bSiCxFfW?^jid$~HP57%a{(pF~YEw_l?!GQA!PO ziWc-hvVjm(-%XEkW=3B*99&!)QR11=UrqjXQyHzWIxv)*RaB|knA=^Mbp%lItPEmxB>RbX5p1rxL! z4|xfYaE_X}lC0OMYo=%}uZJ50Sci{6c&usY0&JQZ#Ptf|Xsj!4r|4ePEpw@JpVyVz z>w@b?BmaJ!+-7ihKV}tHX|RA%dfT%aA5_IY4{A z&c{lDueuiD@qWB)`R#zgy$&`d<7cW zu-kkZ2^^g_z6m7NS)3&FWn46kq%P0|6#Pz4e@wnqTu?+SMbB}3yr;xu3oS&;_8gJx zMF1N+^g915*s0sSdE^8$zv0d9^m{}mvWmWH7>%k^*u_`0r-sX%0GQyK=|?N~SfabZ z)%}ekC#c-5(Akdd9`+P8t-g2e$Nf2>j?3k8m^G2-Lag;{~@-dei;7MNPG(~!HCcnsGT~tX(TX9 zQPre@6w__+@|VJccrv$~4&6xp22m!DfOJ8P#S@2$_&Ha>BU7`#;6L7ZnbDxH+cbjt zrAYW14VKLVJy66nVpH3PhHgXXU~?p~LmNLH*AMVz#smLNnnLFf6duXc{Yg%{7h@pf zKL$gd4}aLfS@A-EB?ruFYmKRmW~H4=iocO|pyAQv*k<@@2FDnjo&d)_zePv;d0*D2 z$mTjqPh6$gg~g-2Aw6MuFncbhQe7PH)QDbnIkZ>Bdfov#WFCL~^%9d4MBj`}Ks1C& zhfBCp)jf+oAnrZwt#DKB!$m=RudiEN52WzD^RCAu2u9JQhX|M>2F%Ae4)042MEmL` z!jaoo|DwFOo?|#xQc}=FYK$~{NHM5zQ@oH-=1tn6f!H+u#x<<>hVf+krcwyIkNCPE zEN4MZ8%u7;Jfb6agZk`LA<1p156kTNMjze_qO$PJHVnZD%K20BXrU{So4 zP$+hx=?OVKdW6!%0&J&Ut?+t&+|BNqUJr_$#Gm%}N(rf^z7u>O!$h21;O-z3VD6_W z#(sS9C(>n>y>oz(+rDptrfc9%E-bDL)s*|!eVL76dopVw*2kCcklmY#>kW<8Fv8hb zkPY_fDv%jfA-ZG~FQs}~RNDfp5UqWn4<5;Tc1Q5tCrgAP`DHmfML}1Vei{3&<2IMg zP2!7pMU%uj;8jKYscU~|C?H1GwkRg-$%eNQO|X-m&9R|)7u(#?57kpQS;*A~2GKzh z&>GKzoeK4#xY>^45%h-N?6cWvaTGYt?Fn+#AH@8I;M{cr0`aCgDr{bZu)w;w@xOL9 zz4?#$)ginqwI9gFc_8qhzr3PeP!2FrT%56A8SK8$?@`Ydzfe4lv;Uc*)o|CyWG_Ap zAC~zNN}yoBuOzJ#VUIe_n?Ms}5SEP20mg+PA88Q48z)~EiM~~Rdc{pnwf<#|BMyyD zpjkZcUv7%W4NQTaS|B+HBKJ=b8>I#j3#voQNfCh7@2dxvtKQ1Q)xOH16%M0_YtJ~l zZKf@Q{X~o!V>OPU*5$VmW?FJWWsPRXJ3&VW_(PC30ly`Zf}HglhE&L<7f~^IWw&!U z4#Z%FJ&ljI?SnSvGdD4i}^wXAIqGQp<+j4-2fqOvs7^#Y3OdVKgrl7?cAjekyHuU-W|s%ZzM_-lG=7S19N zFYlaah%TF+^$vL!BSz}@K}WOZj)6ZaLMge5lUZ z3+t}&5xeN@iX}c!UD=&xi7%Mu1K3 zCzD?lYbAL4YTV6Y5xT&>pBnf9diDhjPAsBxkUT(fY%I79LmhpAD-w3+i0|-BdRW8*^LtCcZKj=j$>@kaH8C6+xc$1&j;+}0$x;@rXRAP%{};XX zf|bmj*nl3Kb;NVd1&eO_%#y;d5E5)rJ~Y59Uh&GlJK}NMm+ig>NP3yGXp7Y6r$;7| zF>k$oreovnz9iF3Nxu>E1vGJTc*(b{R*fPbw(X(-qA9c~FndigFKP&^P+OF9khVnN zMQL{?F7Bg5RxIIb0YvD&CZX5KHBgazr12}*uImif(_9jql9_xk#WJ);UhMin@^wM| z95}Rg;_2tXV=Et5_}Aoqo}xT2Jw>|SNtRDdEz$+b?G;_Z+QpaH)E!>Ea3b;wY9)Jh zv_FbHqdW`_VdHNgu0@litI6zj)3tN zCXs<+a`Cw~NP%w(w(PhJeE_+@3JDatwfSe;5;>hjg$5k_(Qvs$EF$LGm6!)V7FO?$ zd0~QtMHimFT}FUCwzwRgSCx6gJcxdy>IeK1feY~-9h3Vvc3>%(b{9T%9B|%*d=YCn z<{)f@HaP{rse>>T?=(`Icym9LC9z^#-iv(fdY zzzDisVN|z(ayxBDiB4F6V}lovn6YzI!a8bH*lUCh_Brv9+DPGDeRtZC=m}@6@!dh@ z%MYtg#^M1wP|!DzgW+Q74d^tmi+#JYlCSV5!LRWNiqm~Qe6~LD$VcOzjl@VudAt&3 z=m~V-3(L#bSO_(xsR|PAK#AxKggWPh3os20zymY3gT5c1S6x4EOXVr^^K*o5KTSfg zoM74XcR=o_gGTi>#Q5fmfUyje?Cy$^HbzVS2q|=ZeG=|UmlPOh{5v{%|8gt69WX_~ zYM6w>q81edxFKIwnXNBUQ2Q^JZx19&5IEoPJ6@n(OIY}ILapg00i`n(T#1|z3hNAv zHs!DoKK-*V3|GgbQsk6EMl$_jHKz$T{cEZGEYL3Y5AQKPE%UsmAjewKk0>&VsN&BQm${5&X7sV4x(OeJ@>c2KH^I-Zug z`b&IY!JSHCsFS4e#th?F@<7^((GkMYIeQcFioHktQ6&VN!-=+U8ME63&jcV1X0 zc+Cw;H5}2srokcWN$tX`0WEC<+*P?ak;ivV2x0I?XC ztky&R`%XY%kl42}Z{!s@1Ib#%JLm%$o$L5cD^kV52j$QG^!_rgCo&UZn`gR+eT7Cde*8>`0jC~E}Rs!*W{NjH#V76RzxH!bCK4+1#D=!2yB5W)-v?$tQ zL2+H7STUUCnM~ig>OQYiMe>_79tm{|IiluD&wBuxmpp(8ym^CBTYc-BtE`n95C@(K zjn54VitWn|9P@KqD*p&1Fg!?Gzpk9ideFPh8&}K9!A+vP%#D`}H@sF(%uX8paNcYQ zcKS+TKGHlGn1uylMQ)d~nG{lzRQe}9u@gLveMg;(%y-!ydo7YYzBS-UQ=O_{@pJ-# ze_f=~S+axuovn!EUtnMJKQ=V7&Gj#}!FbiuTZR(o!jSg`{_M2O6465uGXSH{{HtGo zt|0y=58((TqZm|HTZBkv;gG8u3Saf`yLk{K{%-)ho>+BVmTtFQCht(TTAdqtzsu|b z4XkEyBxU9Ph! zq<^#<=k_dF9==V!`b*zZDBgf5`*h&|%NXb*RxlT5>zR_J1zft7Zj&Oyv0uwD=-zaQ zB^?_L<(8vvjZ-Y+QKz3{jo!l~Jr2%_(+F~08Qg0$`pA<{Y*p1fc3vS=VntoGn=3tl z3iC&SG5K{V;6OHXk*)w_48^9@ z&sx72Ro07jTY|Jtkp;Sw9F-FC?U~87$!V*ffNNsQUj2wv+r+7n>%W@Ji1^nyH*SD9 z{M@K#DE}rHWQ!NU`mhA=yllRD!r`2CCFRxL8|Kj~dHNGQxh@*_^c*>ny-#L9! z{V5|b0Nc@mu?83Iia7-rhBC$FfMnK>pA_70n5wZ++mJXzT=IND z=c`8LVL9&C&ty@>%w(X+7k)EoaG?!_OTho9ifPnY&(9FMD)1RDJGf?{(Vthy`Njc6W9IY^G}x`BWu*SbI9NGItflz&rbOcryY_tYf<9IG`Q5%| zg=hH?NyYLPqLq~5X}p~lss`|Nl`QK39tI*pY0bp@aFt@zhXhoT{f9aw zS4bq*z9e~IAr`qvVWa6RT9;A_$L&6@^$w@@X<{KOBj_?O?=&0r%i*WKpGJ+#R5nk znwNEO7}GTDfXRGAn4R{Pr$GAhHw<=K<|tUWcu41ABWwLH;N`Uv>m>JsJ!OhZ+5&D% z{bh+W9)6_4Veqt}vz7cp%fMBUN=gufi-8j-tB*<-9aeYqaHx2M#cI$i%jZr%A{*RV8OJk^ zHxO`VUG*#NrqH$T({SRQhupA=#E%ZKw!Ci+cBs0w1=~VeB8C7Buwqe(&(=^|uZdS9& z(fh(l5rMBx@}pYvn=T=CKSVfLx|}5Uhqi9wFW!U3N#f3Ps&$cu1R}zio;pfgK)ZMr z3RGFjZBuXSpKY=Hm2LLWo5gvKC)O1v!2&G|2q1Q7)#aal2z6zCO$UJ3e3chg#nY+1 z`F#8wz}RVAH|a&((bKxpM72Y{w1n7(V|kS5yz@Iu&Rh55X~#KlAb~*Cl(FkxpQNu+ zC$ht4TXBfHOcp#2m)s`SlRC;XA>VW*uTtVWyc2(7t9L0CV3v~hh(1*>OoNK4awJWo zr9IAJ2fV)cQnaaXM!_sEapbaE2>sLm=#4Lp9>Z+5aX{l~c-Bc-nLk55;b*8zujdq$ z{?|>bwwN#*T7zQ7;O@pdOUFY|c+NrTdJ5s{xU)_B1_(YDvl8zCMPv9TKjZO24Q|~C z*4>Q~ZJCaGk<31%BiM=rNlNNjsE2@Y=42^L`I5S=d6_5dzSSth{TR`5<^|6yy$ECBr_}A$Y7NQ3=(RecOOm+WfEQM5 zD>g{EZ~(R{iKDT@XUTrDjs%y0%d2@0^Xpv#K4(cP2DaE(#sb*d&kKdS+icV#-H_r6 zfGl_tn+n(i25T*2jAjGvb@gbtTu zxWd{95PikDW5G#6hQO)?L3LQZe-#fuTBkl^)%}_~ZJ1)KBEClJC7yBcalB+(T&s!LeSLO zD`tfKYICaSNJ?5Hk6kWg!r3D)LOt+2o&;CtV=nU}m4$HE_ppzPK38I7Z(0y~uy`+c z+|BckSx2)Rqg{dPw4Qt``78~Rv`(k2u+sg>CB3d~L9EIVW(KL(jUn5odFAo%>C?-m zmMRec%vZL^j$vFFRqy+Ghbo0Kx=BQqCd~6R*>O|Qkc}SHr@nEV$KaGTofsr1^gmY5 z-IR2QrPypP8Xl8ubY^|M{ph_{8U?t? z@D00J02pb1eRD1GkMaZLGXvB(Q&8HeGd}pJ`lhn93@bI`)=}l&;%jG`vMMaU9q;g7 zeq{QGh2Kbk=Q%t(YioUW)X5^ul92QbuDsu;Cr3K#@fY*d+;<}57+LC(B`d8)BB^!5 z?FS5i$GzS;jBd8@vp2r+=OF7a1!1hhIMI-wB)u~0qQ##u%dakY)h<3@Q#1``)!YHu-M)DASwytkA(;8 zX-Il0hzUQa&Ye1T`xM8;wHx#as63#ZB3Vae7hAs-K+a+}Q++2DaqHPlzJESS9_Nb! z47qCyhG)mIwVz<3W8T2dDU1KmFL%*;q9S6+5?&8^GeHV>*!uCa@ITZT9qiOeq9rsd z5=p%Ajnjze>dEw&Je@r3&dbileUBlaPz~h7Xlbw}1_TbM13cSqqM)ca(0TnC4Z`cD ztPbSVpb^*0T)`F1EK1sT&gcPshUc};L3?jfqO-Jx?SWgea9EEBWw6e5-E~P%*uq*C z(Y|+W%g9kW1PzLgY2#E{LHz@`K%n0Cx2>h(n;0H$qU7u>+^2J|AXPqgbZ$+^hiYXmO3 z%`qF$P&2bH#0^x0m#y^0U4t9y4}mU6Cah2ftJM#-oYDz%aZA(7v#ZG_lQQ}>LXzJQ zV{~f-Bi9FWA?J?b0tvRzo-CPhO_OF;R5)%4Iy7($#)mjh)3J5DXn}B7teHcqr31kS zRU4L#QV=I(L)GNLw?g+@%yZuPqv`63WihX)o<_~)=T8c1WMTIWwcB5wDU7v6rv}Yk zJftpOc)E?u8C6nKr$Q=mdF%ZBFzE0)!NB`@z018J4O5BexVwmPZ#zI0=5o?{Gxm~u(IUYuay1up* zMOGAA=bv`9gD?aT>@jDI?D@dk@&CC89NYzQiqy8+u^s*>tk> z`PBAHHvdvd!$a;y_XN7B^XVpyymgv?#~yde>lS=zyngWwq>;({^%-QiS7A+92=o)E z`)m}MNGZI>4{-^tsn}-BmJ%wfy>lb)CE2)c}obhZD*B2_0xlfvE+ zFyirj^#RRvxkUd;%HIM}?of`M_H`T27pC>0I8wKPL$P$b0yeV!iqI_3W31*(9sXE-G%LY+Qt%@l)@MZ8bSjD5zgjOli67;>xP)PhdsL z4@RPY8B+i34a&)dkqu9zs04?!PI&v$ZDH-LH4-3%r9W9_5h~vSrBge~eP#WnE6By= zt;OEY5CeIq1xPS_>ZeP_Bqy*RK@MlNrg(p(x3fWozVAsO1(uaI>&Hw)=5Z_Tk1(&^ z=-z7q#J~B+o9bP`6;CjI1(ho+zcY8k9XcTRe=@z z3&Iv3ma=8kZI1sO>pA|OmJ4r{epJ|x>PttxoTKm{Gu!tlN?A1kLPHMC zhs%Wh9c*V@(bO3Enox=219Q;!#tqG^lLNKIYzH}Ce20+m^kes8lUsH`c0ndzX+zFR zr$#mYD6b`!uhnnwEsDeaHJ9#8=Z3Lq!UDb?G9>oVFP8v03xHthEiAE7ID{E&m6vPR zIxxr}A6o&`fC_dctVb>d7yr+y2~XCqNnUWa#ZOgrChEpKF1%8J&VJnA_x9u0V;7WP_XVM{a*BLy>=0g5*Ro#_@YvR2pC8GInXku2__{~kG#$|2{(xQm^|zwl3V3S5?pR zoYh-qJNs!VcvjF?8w-#1fB{;FX-)U;cx=^A0h0}y?(oE2nDx$Km3P;k1)~yixC|Vp zt1L>6GD_}WtVV+4esmv76@yTYEAWDv8a2Ae5a9g`#m!Ctqliqg&Eaa9|2UeoE%lmJ zfMxLa9)gtQJBlX5N=5mbR3kmjm2$#u1<|r)wJms^m86=EPAtnw9UOt+`8HPlk7g8V z%It5s!e+BcmdjcIX0{rwfUo&B(Qv2Oz(;TiEvu7!k?3DchuBa#lI0taow93wnyBlG zrBNBnpk$#+Ed_J>K<3^Ygu%y5zjj3dboDA$#FjV&M{DjgCs5Hy^&m2j)EIrv z5R$|Du}Ljy;5FXDFd=9XM2T6ik6z&IKJc#-!;xbNlxop@eADoakGVI3k>{~Ea|3da;N8f z950Nnw!^>QU*SN}aA|mFBvF^r_M#=}tREMUj|`fx@fAt|pz%oeO|?0#^ia*2^Bf?JHE=~`JpCja!|=0psjs?*(%Pm)|YmCMNaN%26M_)&KC%vm_eQIdUk&o* z@v}fb%rISvVV4{Ujka#pp9d1`cp{NxPi(%p>YeZ!=v43vbBMS(9QV7?q0wmM85HbB zh(>+wTpI`Y`_WbNVRZ+NMox6%>K?s8$a`vJvsghgLP4XJ(V|eov4l(kC`El%t!j@t zdU%6QCEYAax$B?j=uu56`G|8~)vsI~(lEqW>xY+TEt!iQkVA$Fg8N#$V zg)51XRSr{!PAwaw2K`JQij2KL>Ej!7#a2vfF}!34fZ}+0q9U4gb0yZ<7nj9(-eh&U zc*b&s1)p9f!Eq2H=E}M95mRrA($hnn%#x2yx{8AYAXM+mvMDN*y5Qx+H>?5+w*?PC zgAwWf7s?7VaCWj_3+jc#xuvLwC>YIe!OJ9Rs*4%hbr!vsY5&3E22D*?&8Lemh^GNYfY8`$V2mlcSl#EVq9at8zL#dseTL3fLi|TejA2|HlakSw9P6SNR>yR+yYGMMV zG_bX&g`I&eR5>NOdq^JpC9AlYn4YEwSFyqZrDQHkhN$n-?xBn|C zG(R9=IC%ifTJ2?;YSOACz#I8d6Y)ZPe|VjSd{tT1Eu5-!NJP5sB8!-1SQo zEXg$wTK3F;FNn7g;A%k6)JU+wM_h&OEv)5Ra3gJ#GB@iC#rn6uyR^LubQRaMg7lnJ zp>6I!W)Y-y`CKcr>b&~UmG5=qPc%S|kAbqwETEBMY-RRm z;<&a&N63!>q_rs)>J)npy+|`>!UiH^&9D5Iz<8~)o3j+s>B2?rGxMi8u8nN;L6uDd z%HhSVP>4OSe6X#xYKXKG3%o5iJ2Sd-ct@9q*Sv`ms((PE5K-df?t<|+sf&W>%@taxOUoFf_#J_F(_*()9 z!7L^ZDf-wLiuaNK<}pd^m_K!wn#2q1+bAhdMwfmDA}%{?hJ_ElM9#ipaJt7(1Ul8k zNTY0g^7_;k77oYpTcSZRW&9ZehGooLbNPuf5wP|je!sFeWh9XgnZ@eDC`VE%W^PEaGo*jhJdP!0-4|C(x%ufM%2&F^Zgj)$QbWmANt8on^IhyMCO3m_jdD zkqfdDHWjDb9B~9wnHAt})5a6Oq0dXvpdG%Iq%za1GPDEy3~?G?cWrnVn|q65yte<` ziw*~qU=EA~C14*JA{V8zm5h*0{herJra-MZ!;3!Hm_Q`ueu)QsyDIdP$kNN>ow}ai z)<+H<9aNURS28L5atJC4g-l87~5#9dfITgs{=)Z_czMGdbzB-YZE;Z?TJqgazf=)rgwmB)W` zeI7oxI#q;;SAl}|XSxc&MwP*oLrmaRBmnsc;wz_8$qGjg=dLoz>0I(H8OK=Psu2jB zA~>qM5#`QrrW)d;D25Qlm<>Qy*!6#EB8JF&{abcYY=eck?0D8#tdw4HtugcdTadqz z(wuewaWm;U`a;{n=eOo&Z|q}QMQfY=&)fQa{FD!L(KI795-X`;Wga}yn1g(ZX|Ja> zK|;`X7??0G@B6g8lGKNY_|pg;#DMeuWe%x5;GH4q#+J0)6k4o@RApycR`S}p_L^%q z@5>4uj%0@DuZs*hTqe|7enpBw{Zk-ctyhL7BRLQ`zFegR9}Q`*faa|5lWcwbfh!uW z40s?U^G2Jizy8B!j6V*Z#0_T)RHn}u>0~g>a^%Wcc@gz;|3%j+-B%hg=NP7BldFj+ z)mVn6JgM5Du(C0K$k#ykck#w}zzLK`3$Bxw`2Qoh6lX_a^s{F{yv0|8Rb)(iInTIv z868V7(uBmGJcf<4{a=Fa1L)Hexz%j2$`dyqeN%ALvnPuO3**-=L*iYZWB*GgmY{DYq3gk$ zdBR9+>h+#=R1`%lj2`b3!XOdRacFwHXkUHQBL(?8jjAroQ3X+g>Q^_uty4rXYRIe# zU>{87=3d`!2duk0|7BC;Uy%-E?&ZU_rcgb{K?39k*Rx%~000QY24-V_OE{0j$taAC zyXOdT#Lc);9_&Ap6?xIe3~M#oyv<-P1wFpn6E4teztT^mJ(i(AxK>@x7ruzd#k-Ut z;sqR7>sbN5D|RM;(bJ3oP{sd8B<9Ari4voRfJU3)G|N@~ee2cNefT-N5UUSssqR!3 zc%2gG0dnR*p5vyz{@_b!$9Z%8lKt&v9%Qvu9bN8m$s2lmIUblHKQlXE2iMkdvx;aO zpxNHvHjRPyy-n_K7rgRS!Zj>r6Gu<}07}A>IO_OYrPC}BEQ(cU z{x-Z6n?pS#MhlQxs|kir%p|mpdJccPw-&#ntQ{PoS{x45GE`9(T9E)mp zygsVMCb?%cEo!jXpV>_7*EixaicqDtkC|yPDqbxbrece{0!Ph|d_w-{eitDEBA=j& zE0fEHomCVEl7OE(8b>1n#HC#Do)6>n82ucksH~R?67)U4*}k+Id(zRWH8dVg%VJ50 zSm>}0Q;9`il9x$*xr6DUZ061h{$y*c@Z2kB+AgMP8xPBl_t3w^))h?TG8EoE$u@*8 zR=(Km?7U0>&DuW=|8P&U0wCQFEcc$osn!a<&8FLE5^?jYEXkp;CA7pSbGppF47xXL z;My7OwVOUw?vm)~N~pYu{b@tAr$fw724PauC8#v9^OxoDE0FoDG${m!!@umCcDXYldSIHAoT8CxOO4D;Ku(O!$AHG|ASB{X@rZF6belC42 zrzv6W(K2Y`Ar8P*R$9)3Cc+~`kru74RQfxlfBrBC1dba)ACcjZXp4RTgncudsmFO2 zMj>1!@fWczS*upghBy;pdx@30@A~+Yj{n8?#83DNN_08V=HyM&rn*eEzrt3c0}3Q| zag>t5=6VHv6qw{~i6rQ!$rb+SDmcnLS@}x-LUi#xLoO}G>-ZLSayK?F-bA>qia#r( z@oZ{sVOrWF9uU0AGR{+HT($fT|w#QkisxLI{d8_y6QN4sKPcbW+w}ok-SKZ z3u?}IWpm#&&D~BqJPiv3OPl;>yN%t{sx`GQmNG~3 z_#^cnw?}#Bp|&dI0#&@qyuI(BqOhB^!{kIJ-yd4Yn><9pZa%5X@J8^UP zxUX9A;onJ6VIt!^zjlby_8F0f6KCRG5$FP$O!{*dkU3p6$yH6--qASJB~TtgDbn+a zze6xfEE?r-?t3ZhRs+1mH=a=ETR+8W*ZX4nybv0zVE#hOQ#jt3fkV7XjHb0b|Mm`x zZLrv5&kUhZKx59(uKtw*aep5D3Ymxf2pBuk0uNS1U5^8ePX75MJ){e>WJL>|PM5fd z#5z1^YxXUN==KGOLYT*K^iEBC0MrVN$CY-UO3n1QS4(Yclnl->g*Um=p7Xyu|E>1F zDhHdqKzYn3I&&=RA)6|*L?>`3wJ%T$Tb^6yZ`i9N=pvY670FBE*x~bZZt-cv(ZP;WJ$N*Njrl`$MJ&8>Dk`F7;VaCz+PHC|YVoP(RESIA z91_JmcxLeb*p**91I(NGZdbg+d2Q)7gf6dp3v{h?p9IDh%# zLY_Koo3nG=$~LIrpkHJV`mg@M36XxtzzxYJLwxBL(0m@Hg{01zW5|#AYg|w4@#=8y zLMytLi4YU}j2haY3wcGoPf`eMc7|QCb+xPo$xpL^9F95@)0v_F4&@B&RH>=D4c6^P zJaLhG_Pv|#OHGhUrzkDrh^Uym!-wKf`-5f2^!E~Qh%3|`WaiN^k5CGQdU*>>;NsAG z*v2R%a9KBC^fyx8971KbDSjaDl2k@e70b65w$`M!#SIj|vUn=Bwg2mX@n8s1)vh_e z5EYHbOx=;pu#c&nE*=NxF2id7&ZO{~CiIcw^ptEY_U)spRX0TXMUH#XITgVq!OO&K zaWmU>sOf2{toqSlKXL?w3G&kDUq*LNIv)2W(?(E4>w_YmeKv6jL*?tC0xmp@>8X7&YssX`{`%!s@LAX!vkrYx+aYr^ zQ`$f;&8yRd7Q>b|n1wWQcX?1ICN&(#zQF`Y0>E%~Dt{9b7-i9z&6kE>fbo`L-_hhR zGTrDLpmhipuq*KXZ~I;2bq`&&=5s4zG`8;4!4eu&rv(qUr_-egz8Kj`>8%J9sHBmqmB3@-f^~Z$Ip<+5U8fTXFZsZ&=#b%(8924n(;asgc7fk%F`cL}Sy4?6u-dL_y)=VFW+=#j5mjByZElK&-1A$iNYfEf0 z(g8K)rUy3>A6vtm9o}V5I?KXx3_|R_H3W;HEId)tr8d7)lPFZryIp%G)1ygzB)Zf` zajyM={a|tErK9u9#%orB9=WvGiv^bO8hd+N6zF4W>#jsaXMNo4=7MQ<>nomKO1H2X zPEST)d;}k@wOlh~zQprGN>yeO!7{R4qHJ_}j=%P;v5=?D@j-T_R!hI#>%(&oYEqgi zXYN-b1Ac#nESoWJBiYN?YSc^C%o^vdd|n}h8DT~#UR_=3eWeGx?Vq7~F^U~Uw4i>7 zB&eJHA}avGgk|k^JZh*6yMGL21c@>#jPx^Pq+-kF$bioTEyM~tXHe9+V0-!P_C4&Y z@fu0Y%gX=GHZ5NEGJEzz>Jx1jC4b{GI}fgZ=*hw(Gu+M-$wISj1u*{0yBmFNUd3eU z`84UOH0zfD2kW-g!sTHGpI)<1Jdkxp#R8$k?I2m2{@kYu$Q%7>x?JVC5w;*$&8SNsf!RG_wouP~}VzFf)kqOK-hA zB)!`Ug*ukuUm)l}BnU?mbobBO!d~6Uqzd;=->!DY4pXG55rOyyxWSs<3+*uzv-Z~jAygr_8s{(k$*GQRQ$x{T%`~eI zRL;o_x)kG89SfkT=`^wB8*%yOInRS#Xtv#8u2AtdSorL1khp5;XFYj@svS_%eH09Q zh8aezDnM4B$SL-KpXVE(>2p8-ud=mX1(0SizS)X{+Ya~IUHDZr)Oh{Gvv5ZdR(~$AN9#){5v|&_;u4U8L-@OH=O|!d+{qjEmpvF=h(_aj)5;z?W|*Y z?Ux)TldK#@nRAb9O4amJ{}ZVkCEzexGlm-xxcT3`@}JhH)GQSnpKvE6_uRfhCoE;% z(D|6=fi3Fnyas%G8SEoR5KFnI)DviTU&KvWWgJs1FlIyW%V`Y+z|-6j>qi#w>k_!& zdjga2Ob-xh;fX3O$(GtHiaO7U9Fah92!ukIsLcyWQRYvlr^p;MKW(=ZSVpPY=N}Mb z`!mj~KpwfdH_*D>nysHi8e8kEf2%G{;~U zvM?99dXZ~DSk&#hM<@G#6YqntS$S{R|K=#(HY8)2f!^ccR;K)G1PQHiou!~vm}{C@ zrU`iXMnf;3I1a#G$t8U?jz1Q>LsqjEbMsGE)$xWtx~U?yhofe8G6k-MFA$HNi{a{| zi@n``j3!zby;{gDD(eEMIEEA?8qn)0&Y^%BzhYyb@_ejvp`Fj6gsP46J4gt4e_Cak zB~l8xK8V4!*jyJhZ*^O5=(Bhb2|I9WEJ`-%H~UA@>WP)JcQS9I0Iml7Cz@FrONl|c zSt1km_0aCh#&+WZ5FEdsjvnHES{fy0FOEsOT}p*1<*~C>Y{XWCJm!Yp8d6gN)#d}O za!-7@8n>}EdrMgu_vfttUP)3Y42uJ^*Al03pfo@gn6c8Rz`+C6jM&CNRI75LkE@ZxV{|lZI0Y9sGrWtL-G@sJ?0t>VIit(v1bWfb zrDJBWZS%k5e4IemTKO4A4u8rBkA|YR0c&e%Qd7v&J;cp|M;tO4^O`E|T7U!>K{(b= zEf`G%VAv^$wDlUA?R(1l8{mWRRpspx4IFL|C{9AtxCpySBoWVe<#rqisw)}Amu@$- z)O~Ib?6WvGhf`&)?~A}o*(%yk<(x!SU^UL}gR2PW;02c@ur5gy7&Zl3l?LY8JrFb? z0~q#*3fcX5jGUrFB1_|+%@PD;?jvvwWXZje#O>eUq<@`8isZE@fyyp}f zfKy44^5bSm{PhWU*IfV2*ZQH+TRMiqsN}^7QUn@7{$u(BiPE_Dil55_K$uz>q(`v} zz|ulvUjG4ux&J>W^x9dZvKOdW#ieaYi)LHy`+V^16&!7YAOOU9g2k}wQ~XdkNm z!X1R$znLm=ch*;CS8Z8eeQmd{hTAKRUK(*o6cN&aUBA_1mDL?x0HmHey%Q3fuh#e@A|2M9!?BXdnr6gD>sk|vDGjTE?q_9d%HjZVzd@GdyBK)uc~$G z;4p>I5CfzT91p`VTLN$`j8~<27voic1Nqt}qJG!`x(qo)QmSc%8T4fyyEMCa^b(p9V_+8Er$; zhmZynd7{tSl`y|~%F^!VoxT=NzBZV@BdEQup*ca=A`30F0aU*8N>x_KNmOpBb9pcy z`7X-sR0lxW!3>|_7&DZ@^6Jak?QL*S{D-P4sPWHl##^StRxc{K#hx2~$h1S_F=ZN3 zS5-Sz7Nl9hFfxhHisx`?!mKstW!VwU`Czd2HmU@5&h0A$jd%7_`F_<3KNF75QN2A` zgDZ_auOpX*>di`~HMxu@3a=|5(@;J${W((p*{Bpg?P;@Ok&l+fdASdsKjEloAMoA; zqZ6^ugAz!ryW7s=DrcHM=H9lmo#MfRJV04CHwO>nYdh>&FARv7s4ZL(ka6phY+gQ9 z4DO~4YG7$7F#d1F4K?9I=OtXcs!nI%l~uS}?B>?`he3|6am*h)#>eLt2V7x&Qt&Ya z5a)xEu&csRf!7FuMM8QMp z)$W!Y9}%uK{)F4`#h<@(tXPaN_CWK28ZW@O_o8SU4-rY>HJRIcW}wct2^Xs?+Pf{^ z5^gB>r2sKN&cEJ%`*e5<5BenzVVZGqp`m_sm;vZ@-h|>-Rgge^*LTP49Nl{h|tL1*XFe z^{8>d*>BEJJ5#4^D`;;>)#OP!=HdX_TI*|!dN==ra|d&v`Z_pgpf_Cx$X`jm{tmIT zcT#zvK5bYMS7DT^YTwY6Hjq1b_T6G*c*m3rNz3LB$dKiX$)jg%eM2n0d>pwI0H6)T zyOZ9kwCZgPK>M2HKiQ@cK}VlRRP*P~(ft+`mZU7QQey+`gpyY|S!Cca&#GL{xTU!w zrw}U-?9l6+O(8Yx!G8_T>>cHOLZpim(R-)=Ghp|;c#gfD%`8ww`UNC_-jhsNXe8!a1R}G_S(z9+( z{zT!1J)*}dEpS7VP^RT=n_c4uS>5^S^_1oqo12SGgLa5^dWNjpSH(XUxa$gAji z+}6l@;V|@qLBOALk>Kk2520$fo$|_}alX@l#b+_A`Za2nUDFu*`9fo2%a$+^GpuZ# zn7W{&bwz_nay7qrxaBr7a)44oG=6T}=5l^}i?@RrnWd9+F=&C@rqqF$P5wp=>u+IS z=M9Mu`T%#{M|r}VAP(`4o#H8|$%KCf0${>5I_&ui-Bi+##O1kNB9jjNiV{~4JEsjh zLE8&ch)Mb8ZV5-bR5QtEe&e`%J&8D)$t4ow-UhKNa>GMEofyeMm(?g^8s-a$i%<{* z$;bAa{6qUZI01myq$JvgaUh%;j}Iws^J?<=TvnoDECdk5t#JZ*N}pO`OXxAK~2j z*#Zs%Uhm+RWu^)i^we&^a`PS$=d;h+!t$dqwPi<0TWYayP8R-@uuj!Di|< z1Z6Wt?$kTSmWcqRx0!U(H+FCe&Iz_9VDeqpOK}c+`<@mkMd3Pi`pn!`8(fx8+MPh? zc8tH3QF(!;0dR0kIXRd?6Q*vm98z^LDCtT~h^0(Ir^J&XGk@G`+NTjiDq~>PiYDEe zR50xM>HZJ%j^yz~;=H*Vx35uGqYh2}w&03_;*d$9{f{vUZge-;2rpl``{q(%*S~)3 zIZ=c^IX^8y==gej4vTs!^1SnxbkoVU<7Q&XAttH(*D`{7 zdW9eG>}$=dz_8GYdL9*;LTSD^rgoDA> zh>0V$4Ei5nAOb&QX3emHb45sq-rAOr{0OOB7H<{oFEWtkx<(f4G`;kO4iRzyLZ3^! zrPl5i(Q$~kp$73mXs{%6bBDF}IMH7j>s6o4$B;v2zB;#U)Xw;Wp6EUWLe5 z32?K;J(v6wP}_;08>l2%NEnIhHbsASWlW?e}J zQLY09mI9=?2M5$}M=B?aZs<6c@lom=znn*_qUqF;s9&Hqr8z?$#dt)raE$&CzW+K#IwE#{g3=6 z$Z$)(MDG(TZ?*<*nFzgL>)J>w6Qh)tiV4lcs4r*_fgM;hHN49Annse1!6t{EIX0y9 zA@XZAw4xGh$GERgfNfjC1JXtJ^CME zWm)}+hS)9FJ7-<1^b6WXRt$zULi3;yHN_J{vb}RZT;ZUXYM~m^`@-S8g=~4S$;+S3 z2^BtzjBi;Zb_@JPN*6NI3K(v#oH{f~T4wtlH=i6T+*FlD>h`(F&IWVbYW~9ew9EIT zyd!kVAWbJ8J4Dx}dMHreZjQ^}PSuE}8pYvt*dsNoJUP7oaUJ99mycT@hq3M()QIeT zl@v#gX-9JX2~1L7PX;dx0M7*tqP^Scgo6j6TuBE?MMHvvxWNdHrS((ZmH;%Xf$he3=hDy!VMA087Hfkb zr9E%LZt4yz{Z;_6La^N)j!tA0X#7ue9H{nlN z@Nsp2MQ=AEUwamu#RTKgo|HY*|61LAzlO+AB});dp->rKtuPcWjN-9xT9X1BRIo}; z4-OPy_qC{)BTd;?VYlVn;5SvPM9)M?ZY(WWP!q$Btd@AsL&cYa3(uZWsD=>g7 zF&a}^`EZ4aGC|LBuW@ekOE~NUB)&?agb=oSP%nCly@;R@NVFo|c7L2EeS|Mm*06OD z(;(kB%oY?3`!ziUgqXfN#A+U@w&l>2{1*VaJ4Mx=Y$>(HR(d31AkchfC^Ktuj4A>E zdWl`8u{#`F!+m~rUs30)@XHiCiK3n(3-YCE{Zjx;-kw$BSg7*U^$V~p20yLiCVq+f zEr8x&Sz1-iwJ-5SUxzDZN}2)h19o1+NoDPfUBV#BM8AeCG21#82FgW$A@*BI!K zMw63glqLV9^*NfSmI2(O>;p2%45NBSx%ZU6>@DqueJ=P5F?Stk2hD+aP`M2j-Crf9ls0 zy1|smIi{bJg;8@0MaFA4@Cjg7OV&K&MT#a2S;3c#=4-t#3l1rQ|AIu1^e!`u$W8&i zxa}`rdbziqsrz@SY$9M?Zwi)lxaDP5IGCZ-Z+`d4B2#aweaWX zAIlZ5BcSw;6l2dY?9gJ9Y*TLASpyhnAg8muTao5LI;z$D` zR$3@4iH6GP;U?dnWh?V81@?cU>*KKMx`!5FK3k0L|LmRPZ^{!r%N^`S%@J5CuRrW2 z!N((^pwg_=m7^-8_;@j3+&B5RL0Kpm-q#C~Rg)}9BbzK?px*EYmOme!m>OB-SgItN z`cBRYB7!u3eIOdGBdzVFocvKy1zb~VU2PQ?+d=WpI#%(c`xrJuK{$L9}h|UL%!776qKDXln5b&660nw(Stsl7Q=u3{K&2F2P zddbbynJJL?gA$SXUTikY=X)QzeDicI=Dch49@Nkew*1c#81`9yB`HUCLm6Ba7?=Y_ zc^iYTSm2?PV3N(F2YcMT1GD!Cdpx!vRTts`IRy}aLi*2W;=~uk%rEg}L<;I-@gRK9g1Fg*mq1L{_hkY_Q+y<6ceLXq@TJ@kU=2} zqOZZh2CUptRKG1Vznk>h$%ZnjXK}|NOzgpo3&|%tw|>xwi5eWS|)8 z=ufO{7@9dOYKm#d|01Ecvpxkw1u(>Q@n-m1HJ)XA)l3vIS?$Nv9A2PO*(Aj*XjUqR z5S-3dUw~=ZehDT+%{C>Pme9KPgZJ5w5hG02rZF(b7rMto@r$19p{*{` z5Se@kO~iLAVYA<2{{LF?d9PgZ0ggii=`zhXd$5$+geD=60%WLpMyYxh{0|A}6{K`W zb2+~z-MEDISSH9FZu=5E`2A@?NANm`yYm2)kz!>*qK5I+onl3-d-r&l8(abhUh1ho zN$keF=$Yha`AK7WceHwC>a9lhPfDA$)MmR$`Ss9usA)x+A>(_t2cf+j9856JE}tgK z=ZFyq7{N~l&WEH0DWrW5XvBK((2-8LLPt^fvE%@E|j5gj?js2(gHky4sJ(v1r< zRjFLw_2(I69*q9NBLZ{eAjz;9E(3TI_0XOyzRVrvhc$1>fL;T?XSK=;)IdYHToP0} z0%~j4YY+&3J0LiGgo;O;URCjbtOY*0WKzL>QBy>YY*VYXF)vnKd zC!d95N9f6e<4vQ8-(i@}s6v@obc1oul;(CK#zfEGAz$vj=3n*)n9Gp?xh=McsK0O*{RBDhMcoHXUEMII^cO3vtB; zOOg17fbD|-F3X^Nj&2Gjhm(uqkUO>iJsVXFf_A3s=wssx8D_DvLq2XH*n+(LSqY2{ z-I5k#O02nwCSwdY9}zoA0vkK4kxfL$j+5>C*(Pb6cT!*DD^uQrTb*M|ny?eBlSx<3 z=kM70*cFluOoQj(^h_|!qU7wM^1|k~)!GL1%DiLaQQta1&;xzUA*B{q(#G=Lrnvl2 zJk-|}mfgq3<$uz)RQFEPaEEXnZhV=>mS4|gdye)2bgW{PZxeBFyTYW8z=w*lo#h;T=9K zLie5&$pc`}uR0}&RSEm4q$KXC?16CZ{w)zUQlbCkhf30@+?5QdL&4Fk%R|JR{_u`) zWk&YURa~*rJd%xGgG1zW#9W5Kf=(rYk*8b%aR}V6c2l}o#r8Jea_9UGs4Q8jn#JTk zd2|9GEQP!~71W{Jh(UmTjHE`(HN@+9e0pO&e(XTUnETA9@j6zM45tRL6=g1)O_?-E#}w;ufAh|yfyU+h1M-7Yw@3L9z?t}vu)q)ki?XnxkQ zv;s;4SXQQ?ND|2{w-U|0VOd8VAiX)rhvg1?>gmZ9!PkoT}wA zDz6K50TJO%e+~KTJ7IhVq=Tv))F9s~Mh%8>Y@>bIG~6!R%qqK~6GCtmk#EL|`SKtc zckNWX%|Ip07!lcmGkt^+iRhMy4;I|GUG5Pd6%+&pI>lx_I!J(jo4^VR=9h$3N{L*$ z^H0|?RN;{|9DJe7A}GAEm6QOZ>kGnCD~W15j9U1e@H(?walpi)^#Y_}qhkXcqi4FJ zc&;4i6SpQSOIpiAvT_JVPrv^ayftJ zo}ZBArMCsV4sP;vT5@^2l0aATGF1Mg_&3rcio~b-F`@z8DollzTKL*yClYpjUffoM zIpgFC|K6}80ZH6XqpxPHNLL7TNw*hu6Cz06&kpyQb>p1%aC5lV#^ zn!j%T!HK<%-bsiHq!vN+wR1Ji(OO&0);9*SYk8tqvm&^gqM`ErNwP3a0*E$Od39oD zAw5)B*Ni78`5fA%_9fM{fb%}MSyhJ+itV{@U(SuJK z@wl4*!^NUAbE+bxkXtz&9(vD%_0_e*Y3~Wxz?>*KY8wvAHZL>lLZzu3w2HA%>>nJ# z-Ui+2JlVVTLBr|+z6(7koRxu!hi~m6sMg>-r$f-Na(0A@2MEsl_CC#)+C-@bK$gGl4VFAQg%d3_nAtCe$nq zQ53B*$lZ07wJZP4zEA7vYmHWhJlb88-_Ra?&FG@DR^R%Tjwc&7RxltgJ?+*bxYoTj z;}mpGI-q|Yk&8|7NXM=AqtUzw16OSL1cgm8ND1G}BHvXfV9;cPpUad>2HYTeZzvIZ z+4$L+&;kVDVZogL@^o9#ffOuu+I&}4JC9m7ZIk7h1giXBa3UsZCd1EcD*3SIuYYRU zIu2y`mPrO!+Rqg?^pAT38d7V>w81`0C-m=sL`2lRUvfYolT3qlE33ifnO3#zo1rur zviFtjL|78fHLvrRZ^ezt`@~*Ur=A-_?D$xok3Ghb*N~vOoCd@d3YnQdUnJ>zM*v<~ zklC$C@D0S5pwYyKG=&&Iy#3R%?Zz%KO8|VnvH-;%fy(|+v0VUCcZT+b;BjYN8)!`` zBPasaOtYF+N5BD>E15YqCckY}l8mH18(Z3C7NeQOe0FL+RAFCT4z0tvY`OOUz}^Ypbfe8zF%`!XWbldt+1Jc9~E_ zz^z{n;w|TkM@uK)5e3xAabDk(@l9Br|8{8)g0yvpD+)bxizQ}{9)~P59=(f5*%}1@ zG0Rm{cz9l{^VPCr1>JdnJZ_)9EZ1c+^+Bpd+Ba;yO}ccETFd3 zz=6;~@7{Y;er=`%MAQe#@l#Pdwevmt zH_hFr+Tg88r}M_*_$z)!SqEI0-;1ezi$|3c{dtzyeHq!g6+qs$0v z=SN)dfAMXz_)^A)0WE6hZcGO;@?!7O;D9^c&BlB=Wb+p>RWBMtSt(xImz z)LAhJg4-bb8l`oIqlp}Co_7j2WGrwh@T9dJ$=Fuzeg6GQB`9%LL$vi%V$wjF>N7=r za7PI7oYB3PT1eYdmiNFWp#RBQ$Q=x~!lS4{kw_5Rj_drkQAE2jDF5mrc=56Gbmb>+ z*kmVhEddAOm)kqX&sH%6yD;OA+f}s~hEw5Tb6hHD+~6Hte3BTsb6~SrB;mqF0RDGd zK^CZ^v0xrK)Lb=KvvHAlb{WJyV15Q=nT?EL`7mQ^539HfuvD9~1;(?M{=s1w71G+A zb_*w#xj1=+&#}{fXhI2NN20}69AExn$|}ze;&yptk7y8%&&1=&m(M`%Q8rFA@>1)t zAMVM>`dO%t50L2~zd${=pu6`@1|YO!#^x4`k$Y7;_m_4R$$3_lnk}`mwv4_SnCwHwB0#IA*of};a;R1=o;=5<^lnQK5@@7_jWab^vmxrz^6|C zPabM5p!vAqSn(Bx3VGy|I}QL>G*mW7Po)zOLV+D%xXxd&?>2AX+RRlY`K;@iN^2_? z`1&P5A}V(|F&OU!b$$MnAXEf=HX_^%Il8b>C;0JR3u7OZHR)(x!mc+K(NrY2)3O#T zUtFQfM8bEVLozcLqCuVPIEi+B#63vHD~&=#{ZK~wja#jyarOq2vmBo0;4N0=Y>BaN zV-DC|yVwcIxXHq&%G+BQ7ZxXTDZ}=6wlGxl6%OxIOC`P?OEiO>_yY%J(s`^*>o^1Y z;1TkmD|=4ye<>PxS|G!l6XhPVEb#4@$9wq!h8dXoKgaaa@b|w~|JzpeH}#chMXKgx zroRexm{ow%IocB+l!2R=6|Dm%VjiDx&422pL%3-vB2*Lhi zS@Fgxr;FT}!I1%R)l6UQc5s(JBOX(6dY5P%Cr#hQ#%UF4K`iVUX=!%{?+-%+j!V&V zV0YKDiOYr|g#D^sXfkY%oU@eA`L!;<$`%T>|2yR{9Sg*+-BeRaUcS`5pJ2J3Yb*C!L1mv zec&@Z_&~Wu{tKT5EQ6i@@nzE)1YY42{C6Ez9-H#U@CYEAdOCrn9q=G(%#Hl>atyLp z*SK+8K!&kIu^0Ik3H}jl^7n2J%uyMzo$cFxnz~NTwS&AQ9ufdEVZ^eb#g{;?<@7#o zWWU%F?*qr5v6ig-?0Qt!eOY3bV^@*>V_q+hfn7=#8dtVWjtI~HSYJe;&1;uT!1Irz zNEilN3?}Zr8cFJSUrm|mb6;3fUQ~kJKzqoM?{0e`=i@}VZ~q>DByIiH^NG1@|D~-s zx(iExem?a_p8v{=@Elb1i;pnK?%@b)#7LC}<3Y78wJM7pDzm*1dhg7QyySK;he&{3 z)g8oqoYd(!&tp&k3pJEXhf}7IIl={nHX>3ap78VyaC?Qm= zlK|!|C4yupDb6Mr*DY%(hf1~xXm*DD@ZxtVR2?u|AxFJvF2ySD?tN8g4#Z5W|1xWl zv3*U8c1woFSIOP!>P0E2*fZA(&)6aF0e_m)v9YU}?%n2~&Z_#D(JX_N4OGfQfqjhCwB6D+%O*`=0+5kqayqB*S-3j^xw zR>eK&a{+eM-ZKzZMSdJk>T^M*lr=of(EpJHiXv+qAR{Gt@GIo{o)ta76H+=)7Q^cm zCmuZYV(O%yqMC5p&~?h=yb>8Zk9|l8VO#9h-;gwatD~0lKLolX56=!jp>!rp%XQ4u zK?AFd!Pyfx7%K^=9&}x!s=LqV?Q#=rMaYz=W5F*J9Nmmh=FK-+RGbE5@7m=M>$W&6 zQtox*7KDfm?WG9<)aaj%e}L~M3Yj7S}S?NH;s044SSYSC3Q=^|zm3_?&V=Bi_!u2?zufop}( z@YD1q)yRF38)_;gB+$|aRAxf|p!ecI_8c?^_J;EkFr0Ld@pS~bb{e>0G>?CA$;$L2 zr$zW-;e8N|)jqsEHdODs)hZ7o6=@w{szCl|Ya$v0V5|Ez3nMDv(+TpCfzX5E4dmj+ z2i>IbZDf$>{y>LPN$VcvAfUH5wo#?C@7ro`{tu&trEk4<=^bCHj&5xKL}Z{M_^>a$ z^G>#aAf(LJ!+|6)0~=Ge=>U`Ev!+JS`G@P!9_EAAl=hm`kA4gtqQXzJj>@>7q)Crd zA+qf;+KX9M9Rdl31YGig#Xgcc-lGJ`^H70rDMt%lybc*ys%u(>!u@P}GYQ{1ZekYn zNyXE#zjBnsK)c#z#>jvMXz4)|MkUQYq0@YJ_@B?-dyb%q2p5uD@n^?YT#aJpooGhp zWv!_WSv~p z5lUyu*){TeyXx6F;y9h+WWjH>ZbS9q(6AJjzT6Q6Jkibs^#cYBJ*0m8t}{v(op8hn z!Ele|A7$%~MQfzi$-up#;K_Z|vmf4n_L0?tizCl}5yz6USAH4D(9Z+kq8(3!!B^99 z$%wQ^zLO!wkQyuCRw3@4?moUA>6VmF(}jEO$qEwQxyTN;t4V76N5VDX5mCYW##cY6 zD<>k0v6X7Eho0%ECx^FAgFbac96q8NNLd(``Z}N#`Rhn*r0}<$L~P_q6S=TcyHKj# zh^woqJmi(x>hqOL8U|41>5F5~*h?{g9D;^zISVIH*Q39cT0R6w%|s8*gJ6v9ix@H0 zqsvnO0dzBWS{6##907I%(QUaTag}KQQdaPh0ynW3!(M-mVl%C)_=4<8?kTW&i&pyX9Yrp!EV3nK_aqp)@)CAd`@n8r9#A2jj+sy|jVn=9u?AXYbnA z`=Zaoj&-qiYS5Vt2WH&E`Wm$8o8eYcI()hnLgev)-jSKT%j-Tjr7tsd*jr>BCWr%Y zooL{1g1mG@MbXn};6fU&3MoME(Vt)JB{QcubgE1R?eX4TT&O|Ih<%@(E^P!4sP|Tl z08^H~ciuf-1vZ{o9Qh-Jz4)z4)v={mjJ2-np=031y|XJ?$}1 zVh0r&czNq3D?-7Ome(t_=P&(pTNpabf|gfzI#>Ju57`v~wnclLrPI$2N3s&EI&?F1^!31gtV~T`hKl%Z(_m$yYOuqP&J-BA z`d|b<$1gEp*O~Fx?{m?vt?oVo>F<#-PHx&7v;@={w|@sUI6J!sH9Vi3r2O^68ywF1 zO1nM+_;Po}rUwmU11` zuUMExs9l@?f9?D^Qh31GwyatYd%tYeDVUEKUtsrQn0&=EvNsgT-CtB5LSW{8y9Hiw zNO=Y42bV>YQkhpQ?L1o3C42*m6j5jsGu&I0LkHs@DEA-xl-=y?w$Sh5+!qN&snKy= zg9fl*eNV^pMo+CFOQB-1H1utO;++>g6Ua@S7`x4|@B?E*99~b1ZuF3Aub(^INR?{~ zZgx_YtePnXa?#(%TVk@?Y8$g793m9nFBo1$k4fTrRK_;?dQ!L*FGUY8Y;j>C9iw9( zBrqi@|8Ze=sJQ!gez-Br`(#w^Kv zr9O(=3K?mNcgqbdJfb#?7$3rxh%+$<5<)EG($z<){*fGYp)Xku{1C(*2AMr+3^Ude zjo-cWFHPd=w~Qa{Zq@GFbmzJE2ZFWKom|Xi?h{XcX<5F6<2Zlkh2RJ%MQO*e3}2vM z%1uJJ8)b6^oeam)sw+I5t2lARuv;o;opJQiu$2=Q#4@a-+=81;?eP;My=5qy2^#kH zU%28hUfv17x*c~t!ZYyUzZ<-U7ox7PJAt7p%g!D%El9s(D}2M+hR2r?pO{J(&Whk1<8b@0B%3B}f`+Zc1}XNJuh1=l&YCttVQ zvKkGvLHrUBm@?BloUofU@STM17nVs@?c2@G&dM)l=)UqAyJK!o1ne?c+?6)x9toDv1c(7cMTilT7 zY-}>CRHJ{>aCr9_{2}gxYT32~{6Rsp{@u#yp63HIwd>s;0zz;=yw*)5Aq9`HJN&pe zXMF$)G+|CRdfowT&zwdzJR3jDUIb^51c$BJ;)+ii4YB?|q`k^e2K|yoBnbA9L?V&o z%eHD1PMv%c&*OY8SA{28iq&W{p;5K@SM|~NLd*OTTbJi6Fl|7;qUejd!>-Lo#gBL} z?y2<5jM-43d}&NZj$Z;Wh}`J}mE{!I0;DzCsF>KB6;gW@)!uY8ksC5=ig$?#e8ZzR zB~eONC5Fm?lVP9Ic60lX$2dBIvl;zzDJ)@_xi2UJpc!v2Sol+!mcj>HN z@Mr15jZ@9P_jp~ns;~;odiq&|PjoSd4(2bGQS2t%-JU6Dr|Wq|9=n!}@biX;jW$CV*rT*F`g=kVDyZ>gX8p`ovqu-^8Y`Q^HA;O zP!i<^Od{c)4+m}K>nOLJ!KyxgJiD%3r=NKcVTT`JDXmwk$-Zxv=vYi+l)>$XYVPZ~ zDoV%>i1Px@_4%=sSpBf&-{t2m%a0T8M9JN^|Ac%djet8*x7r54lwXkvFtc189#fON zV(Zl?Llx?Ob#yz&SX-%7`N=07@OK~|5MaFs%k6S$lRvT(=uI`in~{?@W4eN^}7xvanbgKg~XaG@9*L z31xW)Jfb)Hlw+{0vekyw@zi+jcCXrHIiOzMQO!kif;yxHKXwQafjn72tWv6q@Oz6i z&4^!Jf1nN-u&C}VKWJtik)4)_Jo*bOuVOY8#GQN6)((0389mE1Ts28Nq|BrlI>qU1 zv0Kh9-P>rX^3F5%EPN*aP}=z3(=5p%Q}4hEYx0x0uZV>HIKPK+JLWN=!_QYs<^
1pwRcM@vBfdeiv9~M`;1uhKr^#uCYJwn=4Aajb%+qOm3#@E?+ou+sbUEUyoJ`rF-Mjff3A|cycei>>f{nYa%wrb6d$7^-eTxDKR9tCUFi= zIrW2dt1YZEezpeIyr6{z3Cg{~Lizzs)&63C20i^h?M>0)Se~NC{R2&eqh|qmxzaOG z1p^)kcN5R11Y${nd(OlRjD>1O3aiF?BHGk-u)i!IdgQy;)-QF63V+D zaK4Bd@d<7#%rrd~zaHo1KvkD{(9%!;u+K3Ox{^Q)k5^+?W#UbVPC6v}o)XSop=~FO z;CEIEQ-$TuEn;w1nY+aZ>9$c8mK9?gGsp56QQ#Kf0%}+rE?h5S^WGs~0u)kQ6`ozj z3T;r8-+H%CwfFa8O@6u@Yi%{a+20xG27UVZ2j6h+`;mF>89LAoszIDbcSv_RQ9nwe zbH1UV(ASUSP|JL&*<>M%il8f6bC8qgGD2NiCy>TBS<0K~;Q?Tv&26TO&&*k((^D34c%h6VI-iajnJd7gZl=MT)mpO^vCsGGhz*kSy+}?voUx5+%}ritj`<_PKNX^ zEs~99l{U3S5G9M2Q9^%MQs~gnZ{D({`)X09Rf>Fbj4H(#qsLp30J<|yGyb>iO$^vV z7O~^D@8!8ARcB{O+$?YID1j1v)`gwVf$G#qM!j!RDB(aGgk3F%o%T@3Y49dsKq73O zQ{>bcU=zO(i=WK=Cs8Uv*zOnm>Q7}9|G2T2)Dhfvh;d8CFAIh~&ibs$+j6;!HcrNG zf$zRw6&#AZ5=ZjD3cYC(f5*n$S{qnoMb8Ma&tBgiiRTk4{jU!l%vOzB#}E8mLW*R` z-mU(T;}FceYbg6d@nr8?_yoicpm&xBz1Yf1rJq7%+XLkMLRs=DleP~MF z)w6DXLF|p0HG?Ni-bxNQ$L*Mc4pM-kz#4ZC@~bzM5AEI(Q7a~p&8J_g17FY&&mYW& zFZ&S1F!Bt+V3>ln811T1g?;^JD`e?d2aKlgqz}uf6r_C}J zx%%!&0PYVw=RUl{se%?_)_Ve>>tn`DVGd|W+|H2yC@QP|ElD8l+&!p6AE=^V+xwH%A4FSXtpTY zkwJ8XW8J#u#fFIx($cN>Q2(`}BI50gz(s*YM5s2BKp(;Y~ zlFkzbd9PkQAdIXu>ZsypmGF1`<`zFm0dACd)K3BKz-1~Eu6%B;%~$Ue~G56WWtM5siZ^&Zy406p;-J!92rzXF7!?rJXF=^x^Ln(hl; zyLJm;NxXkc6`EG#bMRsi`2Q`_DnUOn$G}@en5-rs4$Yh)$rMUi5T-{RnI?e{=y#-J z^3!9?^Bj(rb?Wu4-L;)$27;uMXn^_bZ%xzl5fKfE#k5JJUQ{}iA~~1YS_Z|r!jx#3 z^mv^m9Cq>D*$|C?_rMO-vIt+uI4AEx2CK`_cvxG_X4T=u9^+LZB05_i3v=s?El|+X zLqwy|VXw#7+KAx+*@_fU7b-TpYO$+8u~g=`CS4p#O4tuSCxE1}3RI4EdpZMBW&_2Kr!#MF`j}4}dCD5PdV^Nf@r!_$h|fgL1`t;E^%EU#Op$5lQaiKBZI=L4?aVk+_>=Necf_fwNDgX`Z?C{_TZDWf5huBKl#5N6?rY;Ue zzO7&WT*6uB`=M-IoOI%Q_aL-dJZW}_3ze@VIU!LpJB~+Azv5-3#oPg`K=C|WI~%`h zN7Y2~+X3CEg$MPKwQy&H;c5;lF}E^8v{$9|v6zKJW3E8;K5hg2Y%oF*8XX)^Wh`~o zZcyDV()G^)U9AWBp85|yz!M^E#V7ciljFCHu8rNlHxgM2tZ70E^5|}oDW8gZ3umy! z+IYWNHKi$olidWGh+1J`jioT6tojUp@}?JW(BmVWQDEt@!R)O%LS%Fl$GUSNUQbfH zL%$U%W4kUxLx)s`lG6f<(AW$?89!(R&x6(`ky|fCIw;A{{HYa?T*E9}fpn|+)^0Gy z2{_b=3cYES9;Z+I#^>hKzN@^w8$=|O6_)nSjS<3jW{^Jpz;9z+WDqn{f1====cs6q zn%Scr@aXq48crFuthy~0su>0NazEZP6i6CQn6Y=ZVjeL~v({X>N<8e~i4I+SvPJnQ zT{{W^|3H2$G_iyC^{iLG;ZWLE%$i9XOj+YI)@*6W)7wAWlGW@~rV<=SoLKk{_D6IzSse zWC)4nP2%teNP43b9N?(FENDM>aZ=LeE<7r1o>d|j9)e8VzDww+{Di}Z9GFgTJ#LIm z{+fym9l~B-GIDuLC9*n}o23W>EITJT0}9yB6uS&Gqb#x^ayUGYY`om!K8 z!^e;u^7CPgahk)PWuly2QFePi-qThx>EpapN`7zgFhYsL5?HlaCtcC7)Qk~vT~+K2 zI0^97Zu**R2J0YGvmXTA?;mg<3g}e6g$c79AARsJB;@5W; zg)|vvl4MGO!wh4KJ`h@LD4!9Dw-Cpk0gu6$-(}@nBNcN@l`S3r;MUe1_(R{TI-twA zi}rWrfkTJfA87Vh=RYbS&x)6FcIoGR|0Hq}C@H%;s13p3CxdKI)91aXFyH%aKWwl7 z7n|AhwOmKDF;%MP2vMhIuwv*YI+>iVBe7KY8$g`v7OMujqIiIcva?a_CFyETuqaIW z_^K%6TIr#Y7id?Gosk$)^uD+@+Z|rg>=IN6?F%SF zQ~aVUx4CalM1#Yg>yn5C9ye>sZW&z^a)Fi?!JKSA+pa*}{ZQiYE?p6PH#F&a)nYP> z%S!38lGkCP^JPS8u7(xCfq({-h;&ksle+@oVyd2R?Hbxam`6xxESD(yqoBR{ zOW0;pn(%XVBVtIsq=g1%hO!K!y#%`?H1-UY$CYQ<0!&_j)i1WTV?nO`>Jd3Ek)tt- zZxXh*sKdTqM+XY#dB>^0$SP0NTzljVQ5n~L2sSr3ellF%LPD+5`l~}_Tklmz3S%9f zjwkaj@amx}?vFSn^Bmw@mYe!x*UI-jl7m|i!XkAVmU4cc(9*L7i_s#$ro&#el4SP~ zZ(|q3&n}LYH#>#n{F2lV(WLj0f7^a5*2KIcJ)edj896Q&Bpn)Ehg?d8CzDsR3S$^SvwnWP*>plr z6)w2B$uWq0Fydz}7DOcXRgx+Q3Tcz$d7!~yvX({#N9tHX3e8}CVkcdDe-Y=ai#ee; zY_!&vbGbjhfv%KPW@+eT5aLjbPo)3((z=|_l<!l(vBYjP{w+~bZBfyvk|OP`PvfWqPULB z&bu?lauK0xb`AFx2wOCef)nDw<95ahe}3SVNywaUu(9bM9Oxy_&le_HyCk9T;-dIf zYoBY_!$1A)P!mLXI#7X*U%W!+dSne)SUlbLU)b5!nnpn^l5qgeXlthwfeLyd!Y(-@s1O{pe#rgo1vPQWe*kNSC_*;M5`? zVM>(`kskqb$!7=vMnJj03^VM2B`FLkemO*;_6L78nOE9(8G|qQJV>!O85!KR&2%B- zjr-?GuUVQ()x1N)EV|X>BL0$ZNfT6oE*}Hwck}iH2*30GIC~ogZdh#Z1k9(RX_Q0x z-D9&19Be75VgLIS0Ifgv$Yw{uR_>>nGajgA%QbuuLBAjBU1>beZSvN|p(tq*m+N3h zqG}QmmwlyDW)Z1i6E%Whs_=@zvlCGYs>qjncd?i7DWjFgV(t~xPsO#RBv;tuurm;f zLAqL8zf#Hj6zUD$!2?n>lPpyXcgl6%G-y z#W*szjUqxyro~MefQBX@Z6$P8%vZv9aq1)4A!rMdsEW-gUh)GP<{| z&m$d!3lH>ZDtyG!ces-EaO|-;NJBaMBd91vrYp38*MiNbZ@al%gADuldZnt zD{BeOYpf9qiZ21XCYEVcig7X1Kst*0h%F?IXbKlA zp1n7wywqrcDr`apbs4UYYmIF9sN5y6}UfR3(^M5bh^maEEZdi@1-b4n(HrpUVtJaIYZnjon zmm)xUBjeCMo27Xo^k|PTz$<(3XpsA&F@(9Sj_sFHe$FHf7s4KGF#VrgBp-g0my)cW zF2JdC;jL*v)`PHmYh`do%M4rUC?Z5pV$+~HdXsj5gC2r(oMknI20jROSsa8aMpQ0@ z{kk&Un2vDiY6a)UC#|dV+>Y;Lv;q+BJ0v%c+~gL*E~_oJvm5z|rD?QgY-=6Pf$Vae z7jJ6xkKi^dwnfdoKcy0XBiT!j)!nbDv0>NQ^2UlZpZM8gMji(zrkuDvs8np}SJtVr z+U^$h8A*B5QwZxk*TVd8qA318$G z#?=mLgho(CS9nUY-9A9|0q7Q0XKvpCWbQG6O8egq9Ul!bLo!2>&%u+K5lYk$b*>w@ zhBu9Lt|=XeB$vfI4y0z#p@6u!cX*IgkHWN5EtLwl82EGM)7SiR(3$%PO{0KZF6l_< z%kgzOfG#K5;Sz`fh_XsHa{(_LiG4lK>e!v|(kR8pda~U$zgxJV?kvB*T__jzQHYJg z#!Wwh2pz=r?Jg8v*<0(~mk0-gc~Pl2s%O4*&~e(V@sZB3r^AnCchPIDLq1_jM_l`b)S!xxbx)g(#SB9tlSc zGi0fjeb7)A7t#$WFImjShJsz2x)theG{POtKDRY$k)~?oB0so3fp!o)mxnQ?KUHs2 zY(W~D6#CFAv-@-|Ew*9}Ysa=JqPAJIFBj^OCU9*0X%T|!j(xAVhRT1zM>(%fBEVM% zc4@AMiri-d)3GmncKsU;opxaApNeETG)*e&49q|#_nQ<77O1dty%|paaIU^t#!;buk8+aZ6YL;j?yH>8HzBHLi%WmsOHN;7eQC$Iy&S_C^A>|)Gmk9U zpsfE_m$@fQo&;Sc+VUF(W(UL0Z^pn1krM%Bv(+VN8m*FN@z|N1;75B}C=wzr5(bhf zgXtJT46wyyK;q-;`E^2zU8chOEPX+uqt^ZWLXvq|ua>uG)T!mL7pE%cDuNy%&+>ed z3#GGrng}VqcPFepfVvDTRFCfm0A*c}kN}}tG&b%vx#J&pB(ZIefceE-tj_;lN2v?# z@$hs*P_YkhmDQ;BZ(;Cqu7XCYk4qL3n2%R2z;%!!b85~G`f{%J7A$uGi2JWXcYjRt zD3O-8vjlSpb{0_)&Q{4yHnLbCG+PlYBQ0kYjP?^~JDRa3ta*UVJhcYC>nbFuD2?tf zS)>keRH+5y>|sH>*qjG~VQ`tY^i*J|F!cgLAa+54#;Lk)4nU~ZAU3m^VUI$2YgoWu z1|!otFswe3DcVZB6Q8KQ$P0UFX{&|tQ!!}(0DF)|sG|9kSvh+v<{!^QhtFq$Ya7vJ zPzQq`XuZ;9LcCRc0B!CCxBY1(F}1=6JJq+l!|4-%W=`PZ#&Nwm&#abymzQ3yvv?Fi zJ65%dcS>!|e;hFv2Y(jh179NFAt*?&;0M_AgkGk7o^TOpHDLvTPE_g+W> zp)&1agTA)jYN!+c4K$5o#flJm&u>gShDI?w%2x021R!#bREzc5(!TP@a&B^#lM2~? zlLDtqBVIN|DikpbmF%mlx$hcDaR1m?dxM}c36YMwiSRrm`!F#+@&%AW)tQJNI-RB^ z&MO&SW0@zC>rR_B7%x5Vf}cGfC$C)3Sz|U82W6n|+h-@&`jN{>bYKn6y)!=4;+N(Sfnj$);-=kz@L@zY zPsrC&1V*>o7uU_i8cRNFcoHDpllu^^5R-`_AtUH6@uu_LQvrDJ^apl*&T9iml~fm^ zLyADYSXRgT(S>KB2I&v$Odt;oEBh{Ioqj}k?NTel2 zT)5_GD^pRG!Wp?+6lF2+HCD}=<8rd_Vu*pS6{Y1oa58n3FYEvMQqjK1t$FLx(@$JR zdYKJ$;Xm!r^8pJ@^D|BeS%MQ(4-=L|&37XTT^LyJ7s~HPNdzlNBLc?sI0XFMfiFprQrDnCn?S?KcIA zBoZT@0+VgXlq0S%_;VQeZ>Kv*P`BmPYyC#gA|q&~m{Yw34wPH`7M>;hspbV=dOpTi z8I)`sHkVVBSV`!Wf-VHW?hI|ksfEv)_5Rc%pqX;sBoq|=1dflwNA6eZe35)PYntir zqu7$|>JTOOdQ*-1=&259Acb--uZ6^9pklADlK@vpb7~|Q?MF8f(jxI%`ZsU7cA7D- z;5yMP4)>^lW;rc21CC5&mNH_L3GGeVZci3nMSI`c~mTuArUp^0){=fb5#sMYb_7Yp4 z#?NLT2HCZkCMDYbIZurj1XTj{&mc`c#9(8Y7Swp)*#hK6V^OlY6^ywn&7KElP!Ys4p%xc2IE! zg*4bN*%OrbzVF5F0V!OsgawG)HMKBxw3k}Q#Z5W37(891YAcF_2w{{GbtT?#XrP;- zFwuddA$u1YrPZz=Nujm)Df#qzds4oIWQuH!o}|wC4kK=B^+%d;fT^j8Ff3U;|TezCP6ntC!w=?rT@ufr000H%#D@r za=$`*?ld)tl=iFwn<|#LnEc&LTC$ELf`q;r;6}TnIe=!Ujrj`C{B3XChwI;31X;L%7#E%3TPHeHXz-q z=801&)kXGv&}9M1#NkUY z(Lq=R0Cn6MHB`h8DrdsguN|3#KieX>-+*OWs0QXq%TaW(F6w1*T)qbGh=2nn=gpb2l&JB z_yj6l+m*VsslQw+E_Xym_zvZyv_r&0mBxS{itnBnYgS*QYMC;Bulpmr#hm7&4kHqS zjwgdg*n=mi!J=Ak^fcq+4vvouxXABZK(7_#<~Z1}eDqVZw9ycb4+CtD1|U^oV>Uzh zh4l>?A!k`dvo`|hCV;4wb4%k0Zr^=8+!%_Jeni>UFta1V-t1w z3s&O)AxqU`K(=zXkIWIx-MOWev|X@DSP@?4^)QtsuVPjiIfx=BgiN&J#d)lr;p)dl zxL|Tn1g=wJzem@X-Y&i&019V4Sczge(~AnYK;K*R>cwrFOWh5!)POC?;YCu^ed5yG zax8vNpf+lnvp3s#vm#%fJgPD^qXvZB3219KII6#Ed z^$Rx?|%cpjI9wk#%w=&-)H1g9uNNn9o3m#tkWN7p%{HA2!x0gH;^ zNUKX$ems@%&4*kg-sDmNk>r1HnLK1G7pLFTZ^&XcRn5xs>2e{=d350hn~z-JrUc3B zHnA>*W|MQFkqXzObWhPaW%8w*3q_&ooxH3U3riXKR?7(OB7Dnf9`kUX)Pu<_X=y7a zoC7%EoNL%dPIBk=mwbO~qm>V)j8c5mAjSyWaXkmH9lx+piTH(UE3ilZtlA6{pI!Qb z0E*(Ub)NYjm6Iw;?m4yZHa5t!drrww-@S`QK*F>gGyAvj{9 zePSwcEmWca7OS1lCp+n%-eP=I-44gam!+;sq(@7dVHMb;=6>j6Wy%JXHFZTZv2klI zwtOe!UU|g`Cz#+ednmB)Cl=IHyBr=9_pJ|$Q#qzY*j+VH^v^OQn>UJg;m^-8FazTA zAcBMi8W!Bvzz8R(AMA3l{FHW;kQc zHKeY}AsW5q*uw*~Vq$7z`7qJi#lhrIYnrAvfGxl%1Emg6oCr>h+Pz9U8kgB(g~g~F z$jO%4f!8(bW_N=jk5uF2AYBNu=~Z8-o`wH80G#RR!8e;l1Pf=&W5`OVA(vt)zK5u_ zI5@*2#1)AiQ{m<^=Zt0jImU@>aNv)$Sq+xAa0!swCQBd~FFq4KHJBrT!!|SI$DPMJ zb`G`mci|MLx6g9!Q^97)48G@lgVb4R;^2|Ey2ay>LU=A)k}mO}lMk<>n9?IqyY1DO zD60K^EaHDd4PhY=U7g50qPwZbZpVmvj=a4XIrKheGe=%})xw5)EpDth zn1d%m^^5_mzyF%NIF>?8;oJf!PVJeR;-U5G8c6@v$Oo4KZ^T>Fr4-XowUoXoN^~2) zKLr)SaZv3CkQpZ3ix+WW6u?DSlMSyx?nxcy?0RiY%cJR5*|=oSNj@HkhP+(U&})~K z-{u=Yz-Pnsu@MARuN$J27O7jzeI!O#HalF6(~%c}Wk>WD&7rV ztgj_LAr0HWO}CTUQ?x4B$&Yu}b->1Wd)gT34o|n<-lXFRA^??C|FcVAj3Gh{n{Zl)nqJW93B{9bHy z5^CoYFe3wnz|^bzhc=(GpY@X3nj2MsfV=Gs;Jr4CzBvs8Xlt`y(}MteH+jdR`Y1fM(_oR=WqMY>p zgAS1{jwwXh^W2Z#sd%JTVj9F;sn;=9vLSUd(AN0yCoL+W=9(TY&g@ZG*gu9T(`S=1 z7GAZd$^)ad^iR!IkCa~62)~9Gt`?FYkCeSe_#7}RP425h=#&92^a?9D{h40wyT(&s z?57+0q1S_6;DjME?hQBr$32S!1{HG}{`Wqg_`a;4Y8>~~hSPNuEl;wf5+6P; zjKD`;B?o_$GQyDdlns{4_eTpVwz{F&TETt8YZ#JPp;1`fc)Y7E*r ztTijC;S@J+5|h{z^DxCv0g*7B0tf&BO!J1Z9-g|x$hKPi=q{&>ZE^-Z==6_4yJzI% zZb#Y|oVtV_E)g9bn*Yw5uz^BYc0R+Y^G_;PJ%HA6T>An zuAfGXA}%`1B!`;MjNfHc0U^Xs{1l@MzG4N32bN2Z5HB(JcFn;>G!yK;^sA)rT{&2M zoiJgnW=ra+y%^Q`3V2TnCd-Vo$V|tCaPw!rxWrK-4ZFi{48UV_A^3FX*jR=QCPpVt z!J617#=K1wN?QTxo0JV(C>{i;%Nco{bFE;CSyz%kdwZ1IS&vs_gP{|!O-~!tJr!I5 z@WClD(QsbiIElS5%E4wwd;7JEA=Lsonji}rq6dCX$w!$3hpf7X#%f6-yU3Rkb2+zU zuRNUcWJ#YfmdafJ3Qo?A{x6r0VlL$Xkq%yKl9pqC2Z)WI^goJ}kSNL}_Ot;kDSo^a z0h;>1a&h)$&DOdi=8T`oIzM{@qOrp9pdxNa=<`u*|Mm|;PbEupQLx=o*-Q2#IYY+k zL35;w&91ikJSj%OO64+-wsVqZ$daTYUYibb$4yI=!Xqy85=W9R+2u7R%~~&}Pcg8t zbuKG9>J|aJFPL*esE9J*lSeK2MOQ2Yk&nPt*NR^TOvyA&NOcbdb!H6siQM0L?kZt5L8%|GT1ewGjp#o=J$s4$RvVzBzEJHiN*LBjHbC`1)XVijpJBW|xk78{5 z7vsTVO}|VfX1sUa(2Nyt^gXnMCwm9{(V^R>26ETsblzdCIm7RAH%)Ye@42bKzk43XLP;045yniHz%TPeaF!WAmy+p%6r=#oYp*-!yC5N9QnQ8Ev(G z{tV+_pJiNhvl^PK@EH_oY1ic*NQ`gtoBolUJ$q%+ZbP(<;3A3FI{Od#Qrv?n{c69T zo-0H_!gGdnH%SW8PB0+a_zD+@B7OIh$cb65M{O8LB$GHA3H(A=z#aqa3MIlR7FC-0 zAUyzgrY|u-&XFI5_Y&i*bpBm6=x?)N-g1QF7~35GO&<0Q-L01AkJ?fg>I@P8Gon|- zMRWBf=^Yg?Cw`;LuED#SG2ohlrY=!w_Z4hQcN=Kj#&%vi5VVQOA~P zRf=M0=rlw?LiA1xOM}@>n-YbdO7%x=j!iKO86)=eZAb`fHA3-&Ei85?#^nBDo>}qO zlBA>MsX=bXnU8WQc`e4wR_52~0+^agbpoK~k8&~#yVu7jPMP)!7*>?$?YY~RUDk$qVoDyL`0Sk@D<>Eu__zPt2g@REX z!eBIw3*hco99s>Oy4N24l?c?uLqok5Ta=mC-A;ypn~J@1t1 zlXt>cegD26A3mpWd^&-r@`5e9`i7!%(2!V&yAz*2%BZ0DMcrq~gr>xSAFo;t=^uu? zQOhb!9|hnaJUXxS0GjJc5Whh%h5kEdu;9?zEdg&Lp{j#FC#s;WR{slHnjkxzv1)JYfQM7D~3mt+zx zh|(I1E19l@81(l_#VjFdWh!P8PxQmBH~Zm0%Mnh6+%jVal(rk441g|NRSa<1EKW3_ zFRn;`(e9GfA2Q|t|Iy|QN`N*kLr9M3r;;sZ0$Ng{-ZZd^u)5(KDec_KAy5p-BF-yQ zZ%sC_=%u5t;te}PeH}w9^Is)fdmuFUfZH(|sRGx3Ik)Q)2huj;V1e_qAbM2g315fH zsb-Dbs-&B8=eIf_4m326&l}yg?`J zhen4-d$3}9nsNq13I5-bveEm`_thytzr0luBRNNgV4M-Vl`X%eE;k-4n&h#$r7UOQ z#D?Worvdl={SXOv7rJE##Wjub#qt8?KxvPMDOon?z#xi5$`U#1o|u^*qgkv;&T`C0 zs3WaWt8uAB36eTRZ{56RjF;P|8-TEBK5c)x#}}U+lYo5fZ`wp);^A40t}$O1G?coS zuh5`IUed6KTZJ{a-EdX!J8O|zk78BMft3Z+=cMurwQ0xB+KzF3(1tC|GAVy>6hs3!5jrtHoiH11ieazoY&MEN3O7~Oy_7}_i30iJ;dnx9(NZ2PN8Gk9bgB~ zHZegO)N!@MJ`M8wJJh4#$7S+i?F++T$|XkYOiAk8?c|^hs2#A&e4QWFKKa9O_G^Gb zzPJvE*K%Gwv~dbj_fKhia?!G9{!U?J@F?19HbN4PQlz=Ij8UAibbOWLff+Dv6|Ha+ z5nj=r`)^rsV1e5>UxlZ%BQ)Z#VBgp=N1j0N5<#gx=C@`BoqIP3Kqyt_w|o%nUV{yT zw%dNPRJn^vfpi|SA#XYz$FV&|+ez0qLrQvP5bFHyp49oP4%pa%`|HtPqsY`p9!8}@ zn}NB3dmJySf;O^ronLD0;+J*}_i6yfDup(b8(+d>6_aP#IglPUv@c}ykEtZYw4>W7M3LuW%<=E%a9XuosNk z|99)IF|HF#oJ2YdcTj-Wy@9N>o4cl~%6g${9=+}${1PB5qB?b);x@r}Xa$*kCXp2#cgYue8(W9diR=GlbQh5-}fL$^|Xt+o>+H12zt zk7&AJG`vW%PX{WB+5*HgHZzkq&4AsOTO^eKk zsZ+D)v`prtwtp0uz$C?G2C92`9q5Bjx4`r%L=eK%&O$3B`GKsJa~m5XA6uaZM^hL> zWaH2_*)ZjSzblhxgB);(x~!k4?j%*4wLl$;-k#J2n$6K${Syyw18F2@WvucN;ZUrJ z({?qE>Hi(&5KOGA3`HHmdrLqKiP^3W***nn1h21>4d#nY<`aRa zRjukdoz4Ev(w8jgsTY>u7LuWKtM+(uXEf|MSx7C>zIL#fTASl5kU=IDF4Kg3GNyNq ze%8H43RsA$)Yi46obMtoH8kTaWfwG} z_jx56%-FVQbezwt$C4Yh#VDKJB3&oKQy_Ka1ctF6yrtVX&+lxg?GT7`@?GM*GDERH zY(Lv^cbwXvV$2BT|83wBQqo)N(1R#LRlv>NoB&qs%r8k((hjW)=OF}9MuSOoZuu7O zutLdN)`}l#`UdgCd!}_!m+J5jWn;dxY=DD5_o>f5Iut03TxS7YCCv^ek|8V%Sz8VZ zRz5DqOnBL-wCgk8sAv=35>(ZzrHIrEhqC&C(?=hF7TAW~C8S}!HjTOnzE@3Df$FpX z!ovGU+(%;au`)Ez>rk|NIznAc3dqw>sd|!AgkwRbS@Z-@TH4(RXFk3tR-X6Rfhk3aKtxs_(x=Eo8rL?{;qZ=3H?S@N)O;;6#)EFzKkfKw zK@wH+J#`LWgOK#pNpW@A(Q( z$?Wr(72r$W!t154c~QO9RmE&V0&~uk#;a%^DW+c{CQZLx_@G=3^sehd%yH$f&t(a?N>Ewe$zolN>F7V+K(OB#Pa+#R=<9DaxjfC=*Z*E@)9S?q z(GeU&{79dKRWv6|@n9}s>4x9O?*7gdOV+*k|Kzc?QKC-=_opa@c|8d^ zRq-z^p;h03=W>VMpi#Ufkin1LMGzrCOM!-ue$=*%q3e1tg)q4Aeu3uZDKyQ9%lG>J zr=ARzkfFe1TTFUgd{_UPrs0`f`lDS;4?7OYG+#nzTp}Xlvtv*V_8#~}54&(JiXWL& zHoB%#y$1Ll`fbq;HKLe8Va|rK^f>vf{|0^tf^Yy+x?f4jGkG{Dk-@KKtbOI??Zp^j zGARF=sUhFD* z;;Ll|OBf~CCS~-fxApxQpx|z|XcHk5Wi?+elMb_>HX>0QQLo1#5v?SKMyQ1WSZ#K` z;O`dPf)Voekl)HvU)*JfCsJ0mWx%r9B4H6PP@o|jm@;;&O~=8su#0_bx8?W+EJXs{ z)?tt89~--Y5tJReg(e1JVw6B8Icxofm{omI?DEv+G<5J)*JbQC-XVr>qwx#D46ptiF>(h zD_}f3TnpB)pC(Qqgy8Vxe+b=`&1eMkN#FePMIkQ|1UdDJQxT7)^XV}FtLvk}6rLd) z*XkaN`8zF(KCG2N-#u9<;(O=~E5m*vf#;v^{s55on@p*9{0zrv7i^^26I2-UQBQ#W zNtWW9i{By_?}DV@hz7dk)aPJin7p6DO z08CMQ@ceqm)srJzTG-+ z?M8$pi&}QQMQ0S0e_++C9~{=m8nMeY?)PY1v-iPPXlfQ!)4un&Z1tR8!l1SXmRrs7 z#>5{_!p{}4ejBk$E6y-KVp%r$g}~a4$yrxf+!|bx$69*(i!M|e=igS`0fJ=alZQ&y zvuH+=nT6fXtpIRqYQu;!6hN{6YgDrvwyq<6oI1{VZon~~_8Y{as;#-F@|Nzl-A-KY zgT>nWU?KE2>c8llq+ltcNt)G((++7RTX+7ArDsZnj8k}Spg-)u&5mj!J5Jo`lz z^LGP2z!rTmOy<6=%llwrda%*_p`vQgH&mwr)2AY-!149E6mGI zow{#!w$%-#UtS95BxXq;z1_>g%AFv3T$%fxvH92v zecVdp!IFi9DDH@2L2&Ltutf(GKu=3gLf z{XpL4!C|wxpoS50U9rDXM7GzVcvVq50X@fsw(^<}H#Fh|lbVZCD5^*u&zf zgONs!Kul;g-MI4_1qjew=$-Jn;e(;H*rmT1AKtzJGPVK^eLmq3%i(pL*CVetz**jv z7alc%bJjd64uFR`>|QV+L)$fabvoO~UIHwBV=T)AS2|W5lNa1J8;O1-DGPzddqkwt zB9ZVya}h8lq$>Z6YK*{*N_WlKOX#Go(V05yxac}Hc*ovo=wb{Slg#s{@nvzboqz(1aUw^R%c;R=g=L7=+zO$!`F+?loAG43o<|X6$9HH^CuY zErT*0sn+QDOWt~*1u}sZ)J&5mkpDnR!v5}aQLuJ4K3L(&VxcWgLmbGekn@_{wx_xx zt;+7B+R1*54=}P?4O<}T8nK_9RyFce3#pf|1(UYFtQDhjw^$B4(lrpRnj5SiWlsU#=kxS_L_kIO zaRV}WIHtYme-M*I2&$W3-)kYuCgeR!0+a%r3W&zEh#U3yf00rIxtrJF`MqT;^s#x) znpv+zd;OW-fGbAMRQ|;qt3rOqZq**7B_-e61&hWR$J;G6Drjp-Nm)h6kZByW#i4iZ zGOMvYx0OYWb;9c)dv1-?-_~J_X<3s)6qBt}_V?74t>}sf4r> zreZT_C$M!oy3tD6uA{2)-7~ME+6L6xre2V|o9N^PZujvrLhpfAco;Nvpmdl6&>L0pe}?82-@9ZF@XtLJ+G|q(<5k$+|Vb7pXbJ z)`M6aaNFh|U5Bo?k-qWatyO^>tI#v}-DH3?GRB3lby=FJM$V#`M?ZTCj*lCzc6O|J z)eUX-vl#Sd@Xkhfls%_h##7fcHuJzMxy6;z`-05092#Z+LinFvc>{ix`+7cdV(54bXn9DRu z@I=kwq?Ao!$TiX+krOh@&!@OocR5UlpknHx<;=DD#H93m$o7G(KkZT7TiOUXW^+is zc*q~W5irvY!h9W;(JnHDfdac1XXU;1WHd~Jm#~EO?nd9w*?+HSjZq?XS5qCvz(s~MWg%=zdE!I1UUq{dHPvB}Ac z^98M=FNHtO9B0PAU#V)@aRJtt!2nSLh5C_=(uZ)yII1+yjzP;2(HtNphr)p_SFvac zMbB`|cWZk=v59^eQbp17vq!K{_UDyxS`rUf)`q@SIP#OWcF@B(LWgikrGofkgsl9_ zrcjFK9`pk7W+Ps2{!O17DePcgDP7-p;dttlL20^>c7RKM762h$7Q7u%mL%wl!BO!1G&c6{S7>S=Y5!3D4Tc#F;WkIZ#>ps~?v8LZ(J)n_eOI0jr{>vxbI z`~+gJA%bH%B)dq!&k#jri|&NEk=) zsfOtlqSte*Q?<}Hw^^gHLZHR&`*=%U?Q260zI(=aS^_Mo;ajsXK=YfqHIt7<#K8`{ zj0~Suy7Mx9$N%t8wF0!Zn|@l!Gd^A%C-uE0QxTn#N2?+?!!0<{r?wshc2o6_RFRy* z2?JvLW%R;dd|w^p2#r!4<}`-CFmP7p=v9rd{#3 zf9TqwJ^L9J9X`w8i`QBUjlm! z$N5CUM<`fVp=vOs$)nVb9Bv{jpBf!%3PW8Dgrpi?{Y2hM=@_mE?njLwuj66V+kB9~!L);D*Y z3WPwIl+18-!PRPD&fO1=pZj0239x6DYH*I{ItQfOgL%@8cQ+|X0I-5>fZpLlJJpn` zLsKEY7V-s>>sLkxBA;AAB3sKUpAG4uD(4l}G=~DV6RI~j&dO&N?iOIVi$K7%9u$Hh&Tz(43YA_qDcr9j>DFc$4$!z)0i$I!Xt6q5)I;rrio`X+N*~AucN;+Dt^1yO5tIP%PH!MT|ArKxXwj(q9&LfFJ}nie$${@c z%dKU-KMy=pUSxxBX2&2^Q#U`k;B;Kr+fpLedWE-|Pml;C)->;!4dIEd0{en?1BV5}}gAM_&H+w0lF zdEM^^3P?H?H%hUlv$r8r+Ic=FqC5#MOBA3B@2AXbhqtqC1lzR#UyKZOy%~%G0|!ki(=l1?P1K8yIGTcgjUNA4t3B@clCqJg`Jl8IHHG$2S@TCTiIGHQREn{% zQlG$9#-4cAp#o{|kv1+l&bp^&vmoyzgZ)@)RFGaBeNQa*9U=vP*Y-4?Djvq~V|ik- zlEhu^aa6;S^Cd1K&e{FIpIItc4Dv z7l~XC16Bvlxw3Krz*NS;=u)J!J71(O`)}swt9yqcsYU+FD99-mn79s}l(tJJ<#e1b z#NQff=sseU?ro#X^s5Z*YXe4~Ky0~#@%nxoc7Nsl*lbHoGDk*qLM9)>lX?xY>-RW& zjl?JXxsfBo3qWPmrP&>D5}TRD7|e(U2%E&V;^Bxb0EWFWq7HFPJWb6H(xZPoa2YM( zxjy7+9>?jz+!FI7E~CmPK`UM&F<(IuMnQ9FjoAUF&beBkb~`op(6JI;8ntB_9`5W* zp9p?0l&=Cu40{s&s*PXu&sl<`r4C}~nq?kK@49qanXVn3L92^tw^=1MNjytqk@17L zn9#_Y->J}aGaZu%HMcy)0^L`TcGX^rujfTIy7AF>^e?z(_jUm=-uVTz8L5v#feELN zADr!Eow}Xm_Bpz^IfY{4 zF@0e^p-%B@V|s+0l|aJ8dh4fZB;+8Y>PeA5-S7;v>{+FfrU$YZwU0Vh{H#bkNRFz| zJw6CHe-hFz2-*<(2-lRXo!L*rbS>8Yh?i?d!=F6?+KDP~lTllVD_jabtrKHBd^pJeWZ~3mYmoYA5vS8^#Gy^_N zI_dPAT?6Hzi`7HBbP;16G6&DyT=%IBe!&Fpzgrn(l_>_rjIg-VT$30DYt9z_1i+)D zJ-zPfIx@Al{#z92oJB3em6*U=!bqC2>+meW2BEz55DHG?(|<@);{ll7H{BaJ=Ou{; z6jecz#aeGm7+Np#?`W1UTe5(j6w;1xLzB2!=%(#?YW+YVBhv@WpDNBp&+v`Vvlj^` zR^XShr&-A&y@P+ROCc{@5qNOk19IJ24<&`3xzs#y{wM+^alm~%IH4U!=EG0YV_Ag} zj!5k~X6QO4A^)u*b6!1l=B=O?kX%6}S84HBqlh^Q3!R3(`1#Au`>~!p>^Ci8udk_1 zU1QhmobIv*kYqRGxI`@Ct(0WejM(d;S2_RbB2)n?FCBuFwU3jAk@~e#s@n4TGp0w# z^g_su!MKGr%I)8f%{s^M=Iw+t=1MG#Ho+j!YDS4+K6XzQZJbj&#VT__w@c@OxBU%a z{DrEuucnZ@5PqWZq~vil{N%s)P?IS`wO}OFaVL4{nLW={{x0J{S1dooi%%0t=J+r9 z;{#!Xr&8I5BGycI8h|c=#tx9p-L5i3!Gd({D&B)U-P2EP&P&H?!J#?uln*9gr) z^1>u=z{TaIwzT@Jp{wyOK)K22e=}a{IrKc34fHcR;uJJ}W{9_Zf;jexMAjPKru%?J z;pCywr|%)9Ka9~no9qyeVQ_9w121i?G470i_ptK!^Y`K+V58m@T8G!P|ep zxqA#q%@S>P6k(&lGgVJdMR@~oO^|pT3>^R4?F;r96$wA4%$t`HM8=OWH)Y)zjlr}I zI@ySy8}`x#)f=bkFMpU_qQKekr+MN?>q|ez9y^l0R2*@8xDd`K2Uou$Z{qRI9WiKs zu>_eivZN!s-=QqW%Q4L_!a4-kXt(;Bvqg2Za3L=-ZJz`s;Jg z3WQ8tWriceUY)qi2+$BXbQ8U+Sl!r;$!ErZz_AXR>T-vGs;rjIuev0$(hLIdW@seFiEh+jci%hVz@x=nY`g6Lb7bB^h>W1RBr zFc@tBjY6&jPWgyb<*ta|ap5g!zNx@jG$<9HktHBY{yO-WN_(*=zf4rPx%tM^C~BjAa_*PKJN^0$r0vzycQV^F0z>qy%p=I;W+Gqz{NxF zNn(&3!y*PTd<#Jq!-AIKGy!^82qvtkGzQW@Jt_1#0AX)RLfXN*ZUuct1%O}(%vj?) zkyTltJet1A19w^_+R$Wq-D`L@gcW695{Fy(3~Uq6^yFJdVsM%rOBWtk4r58IK6SA~ zov;!(DC_s3F224L2b~_R?*SS}nHCy!sKX^Nk<0O&VnB#XhsF9&1Lv4ZuarA?$9F`4 zaOTEC0!} zF$-0cz<42zeKU8soci?_94cFhVFeW`gY?0QB;F{~iX%sU1?s~CBlet;H2Ey!A0wJX zMh{U2(Dr0gpTV@{mh(Zq3G*!?=?3l9maZy=jJiY1xeU`1b3g<=5$(f0+`Mht2!Kr? z9QCUC43cByR*<|cIDBM_3ME)CE-BIltdQHR7X5U-`mEy5#iG-c-whg3{TNk`hnLcXPe$v$oOmwZ^2~u*Kz7~fW z8ff|@q4C+;{9d;Yn*-mc7OsVbwuIWMA^JkB4=i@T%N=XHg-?`OvgO^)y_wk!uZymlLnT zM0sZYk&!A7Z1iz7IQuCa@_Ujw6JAhBRg(BJrrQHZkNieV;*`e0J?BxPVGuhN!^@Ze#%k4Eq??A_|;LLwiM3Bw|ci1^$p1rmLBMG~FH3CHYC927>BnnKy9`KC|(H>78 z^Yi(a^1v~Gfk7*OHmo+;Syk5OpZS)pIRk)i%}Set3=FG&NvDKR`+s1OfV@q^ENF4ovrzh+mkP^K zPtvD=FMl=ImF;Jv#P=wEugxc#ns$3*WKjB(!A#pxL=?DCH1$gY_w#+#PT~1Ye%>lP z$l3XZy>DsTqOTor>T4W#b$Ubvv$q$@)HWwXNZESj|6H#+!Qy#h@1lSqs9?x98Eu*{hWezBxI#{*v;>0N_*?%ZMzAN=w+ zO7mX^XzyXpQ*}&Oiw@w_=jlH}8MTw!1?+zjousJqv`n zfC53XJ8N8}L2ot`4PXPUp11%&FUEnXhvNU^-}q#M^(VJ58_R?XAH`qbmi42M76bZn zJj~8TCkoQ;fLIC4_D$+^45hmS@$Ye#Lzq8Vq|nW7M;Pt{>vivUBX-045cNPx2Wa@B zr@HR&jvIcw39-w)ErFN3*saxTxMH}mOeNz* zpZ%f|wniaa=ys@5v6ggZl1Q73;ae5cY?xa#%fvC#K$JeMA(SDrCKu`p%E^|{P03|D ztE((84Xxy-;qgb&&tXLVxMAho)p@~Mw4OLIW&hCsMB@J3r{k9iwJ%@j?uGj#lrm=F z07$av+W6D$vWhp?{4mZWxp6ilDao0d#JwH>va{?gJP5_!(*Z#@Xsii7cYrV)`;MrJ zD_pPL`fYn;7+>{RodTiF05N4AbR)&$dtb8WBX3A>ij4`V`z8XC8^}l+sPpN$kq$E50gm!%_zCa)#;Q zR##cN7VztOvKX>>N_z#Ac4ps%k@WTvDBH{=7~SJP5X04fv@5>yNE^>&2*+BL2Nm8T zc6kbZkz5%{3+>ccNH{5%8sP0vflG|){D5n z8Y6&V&@w{W0{&WN>?Z?d8FP`h-g$IO?w{zIZ zERKhrfp+QYzlyJ0*C9KxcI6p|gZ)_p!6TN6Jek}Npdw4)6P&Hf>>ELU0nfGqRP!bE z<(1IS8M#S_+?B!6Lq=0fJS8PORf_m2bv!E4w+3IUKJbqN4nE$@INTY82?+^nh$lm* zbT9;C@JG-r5O~2+FuvTd=Oij38poiL3NRm(htK5Q>*5_|H_IMY*yM?a40zcyRGnE% z7{=R5&bs>Dv(UwR1Rxt@hG_#H4_G!YYEC+M3Y4 zXPGdM#Zd!#v63=o6@|s9(272o0p^UAZ$yegm{A#P7QQ}qqk{tjoJa~9{6h+GN=<|u z36>iBc19yhSzH_iy#$S^$D^UXm2ko?WEY33jKu*y&T`-$#pHs8KQL9T+QJp zFE%n)<~tzH<4^~%+|0k$T9nT2${$d+X7sS}WE*asfW!t}Wqxar)Q1feVy|(@;h8Ab zhm48AGw?f?#zm~afXOw=J5Rb&EO^fF@G5KMH;K2q=M-HVB|ptguAH(yz%q_ILdHJz z@3LmBYh2;WWS36ZnUU>YQ8MU)lZJmFF(fwKE6B z5lJxE6q#t1D`~CIQSA^XdB++q1UHENvO2OY-nE=?{4b*r`c7Pz+kS~v)3Zx+$_+!;1HG#vqqb2QmVI% z)M0cC2oL=^xb3UZ&tVM)HbE9*!yS6q-HGQY7uZ^f{Q+~Gs!;podIyB#PsEQC{o}L= znME|oo=b3Gm~#jPh5Kehpk`sRy^*ixtC-sb>TlINiu30CYZXXzR=hhU0^H{uFi^(m zx0hPTD~~oP7rjV?#s2JlM2W-WoASS2Y%%_8Sm@^(_b#g!J-cRPO8(n17ya7juXgf^ z%>9Im)8-WfLE`rjzW;;paY&M@zu)bt$%A1ZM?VpLwO3%%x{$<~OjuT~>=;IS#Qb*f z32N51T9eM|#7lJwkCD0IYIA)(w(oW5{a;x~(eSY$^Bt+jqFH_@-12(Ha;&||76Btg zFk?Al*vJs>Z4BJ1S4R@rj-@fou6Mup5Sm*nr+}d?ISF8Pk_pa|RX@d`9llp!OAKQ3 zT)m&lhJ^RSl+A%Stu~ht-{S>?5qQ4xh}N5c7s3kO-T^nj)BHskcZgPIf#~Q(1wdw) z<^aJc3!Ik)7qv(f2)Yv1>&P%U8}eR?^TJr&zp#by!3l1HY@y2akB8VHW?gXVydySt z)z!~GD+BF65U`Y}e)hvU!9iCx28=-Z*_I5i;!TJ`>N;jGk&G5te!_khe~H-oWAFtJ zCsLeJeLv41flmZuLvkb!;6;dG=Q{fxn}G)uI#v4>9euWMgKH$`XXdZFjIveSWi+&H zs<2k*ha(-?`Iava3X2)175MYxfk7wpou5u+?3yUA;^<2C^bc?fZqM5o0}j0e+0DZL5Uo!LzEgz`emV zrZ#thZfuug&rS=Hdt71H%}J#c0Q=&tZbmS+02-65Ne%(+2yh{TJ}2K)2s)@y;(2x` z!Thf()$1x}Pwq)FfnFbcCCxn2C*n$|O+(s*(5I8jq7WdZ!+nkm|y7>i@6Ijt!avK=@}pxWICj@LHQN> zo^`^quuKESQOZ_+^EdT5-N#Xk63|ILgJ2qs&3|lF$33n0Fk@~O-}CAT!8YozHONp+ zd&J&Ui->L*NQS~P5c%*oOcZqQH?!um+s?!zJiCB0#&j-&%5E6rJtf8+_rtXTdq8=& zMiR1WQvEoL?lLzJPW0oNpc5_5-D#&dB83O|d0-hnIZqdyFq%l8eyekq*mB_F4 zpCUg*Si_ud_vkZS>d9G*oiI2p)-3}Og!7(s^1ML?{s8v3FrJ%>5W!KUO1(ZpUw=N+{@1F3Hh1OB)Txc=_yhm09 zuLh*z3`cPpy@Uyj55l$mUCj&CQ^+v}VXH%G)k9gbQQ(H!qN9FO$rPOI3B?Z!1UE5V zab7YW7goaKBc~?kvhUUmh7KRwC7MnqkaCPyqcm8)&?PY;l9~m+y07c}%LX&zAPYnu zda9CX%hy&}q&@^)kTk`V^5{PR!{rsBMaKtx0kO=1b0Ow83bmB5cxsnzwg=Jth}q&5|vdO$=QW-=udGP@U+1$eaK%UgKrnvl`7vxOC2o{;0}zR9dh25< zOs^rS!;&cJmie%zk)wBvZ?*$v1w<&Y#s1GOS z^22Y74PpI7*Ab5yjM(YvIR54T{ksM$^%>=?;)WH&b*bIeSKHDXM|9^HYFDXo7vRY3 z50stG+k!%W*!J*d&hMKa1@~G!&*spn#(dYeeH5>^9a-HNs%rkiun+#hrXKs-GX#nT zePusFd!wtHQLGiPOw6Cf?*#1sm$+XC`2Ih~BI8OQ9iCyqdG@s0N$s&Zpj^niD-l^Z ze7^VnI>m-chaU?O86~)eR85%l*}PvHxHbSr zE$dY|6gut>AHc@r3%dV!mVNyght3S6KLD?mVIo|r_u7~cAdlpIlYINVHV#+6@)}Tn_9qEx;-JZFfrGfk$w?Q{%#p^i1oPRvPgFUKv0+P>X~V z8gn5MRSU~YxIb0j0NoJ8J(J*`Pvx`~<9IXIVYQWZILw8(5#3AzZM`pO*VQZet1XYh z?RjVBD!dW1oeGm`kf^eXuaJ3^$o$?PKy_$jv>`jakff+ZhFAGcfKh{+#G&@g*8(w( z4-#^BLWgAfeWE1AQi9H?^rDdn=Ydco)t>-%`GFRmQ4a?9)c(d(BA;u|UzuKBf|03C z;y(kfYIywikUTH0Eq3F*svFVG(AO|8y7CZf{tc+&QNVt8)k!D@ z;Gpe<`PN(4@gbfW$B`g9afnhf9|la{h5d7fA+5-hj>f0(6NJ~-0t=-sZ*vb`RvqS zAfc*$4!=xsF&JKL-L(%Scj4Y5oRwThpgN~=n5+GVbfJAhRP4xh19#a1IJLd+gWWYk zb3wiOD9}o`e4y9M=!zL6_}p;4(8GHuLIw_sAnYI*cL&3LxsC<<+r*GglPqfTS)bVL zN&dcd8oz`|S|$(2u@Si&A6UOr5nST!0XjydfX_ZYSt{zNmMFH--hy|VFtMla?!u{9 z3dZG20DCG~MEq!QMBsq(P?M|iIcta3?#MyG= zZMS%ek9Xxl*Qk@=MjGo~(6<3uOmfis-d*}GH1rUxVJ8i@SqvaXW;@Zj+Rci7trDYH zikSvNZH3D8*G*|Kd_HeIE}QR91~<3PcDr&rbOM8eT;bVy{55D4=sSv>r<%}oTSS&n zK!Cs<7N5?ug!8C;JWWwm6-0>J;*4Q=X27_gJHtFZYxK+#Hw?ATEtutPaNV`w64E`K z{~Nj65(TI4!qkCxOkMdKLP<`>}u;^2i24eXQ+D+C1d}1;Q(vy<%w6@2wilH;>q2jTy2RJ z%UC`RNE7{awm_5F;LPE${U^aQPb5$i|Hg(dvu@-e<^HH<5tqp$2g|+jUh|oS;hnuq z)Gi-V>Z$}f%7pkE{+4`KT@{IO*crl7aWzZw_J+x$i{&a)=O4Oo_qp5cxn&n*t|TKO zxN~lU`R&Suw=o}z znBX&;TyffA^QV6)jPsGS?n?xh4@2o7QP#D7!14Is^8dY1*eK7{(a;;?3J*{OUlndSP_U`4MqWKQk@u{m3Z9{3)nw001hITFfoy5 zi6d91kZHc#VYMp7Mcw#SAa~jb{HoCx!V7THpiV6A^`JsGS{-ZIRg=pMbsM(pguvUZD#$)Rf$$QCe)L9^zw2bo)D< zna5{v*XxDTmhcY|G8shfAI|=QfE(4D<&abiZxZlb8yc)qKd;3)88j;JUC4|M>tOb8 z@4ZvdQ5k7J|C1;01MH0>xb8J$t@(-KI<@YsOnerX03&8MlMb!fGTq-fg*BahBV zFT?6~%u$eu^SxUNkp{^@s01OZ!kSU8#;e4&%Uo&82jKyRpY4o(b|z1j+mP26^3*{2 zyV3OofjH>^3GZzJ*Gwx_Z%-B>mO$E8tQM5Khx2(`bU7Vqowo^_!RT?kGETKKA|Dmn-w>ZsBa0CIQs z9t>r*ZHVnbOlT7$9_g>a|Mbyu0+-Y%DeOKMMH8o+D{wbO`5!nUyhR*=cuscI+u5E# zuUH2Qv3^FcoeLs}w^E6MskjQY?yizvRj+@E%ytg`B=o71dftp>S$iR}@PlI6OE&yW zFJj#&!I%1d?$K*_h9DoLL&r#b#N+d)!4KbJP&nQw5}LgZn;4 z@LHSe4`ec{y|Bb(0hkyF+4G+7SqIcf`}3B&@FjNFbS_@htFRRY5AK0jKJmDE@m~fu z!iU1LaLvt}cuKn*<-1~kY0z$6DeRymgPFD2Bz0^sQM0$(CA+S9x8C;aWb|8v9^n)qEptaFCbbhKcPNT zf5bNYKLL3m0O>Kxp;L~A1)1W+3O)h-@ht>_$YA!nt%Z|8ZhF{!Xc2#;zS(%lP$rPK z@I#emOwsY1cr~1(T2xpS5+F-@h!9p+s2}@j$RnH9aD}o&qrg(;1Il<_UR%Ae(!ZN* zn|$(zTWIECyDt;=WZzKsOE7|vLeMCtJbU?|{HnGmybZ#kMq0`>AEWE&U;R1X@X>gH z6%c4Ai7f{X@xydrw^*5$A5XtEP=4S5oYCVnMhFGMdd=(h{N@0vZz0?A=LhQflU5|b z31yp%sdSS5M~)pKUgjZrZJ>+GLON?0HEL-)E#M~9@Yw^gYL~OSqpsq)%j`w@8>Kf% z;%*+9)pj6+Xv%g{V4f!r6&AoMU#nxqcn7WZ!5N6y?xkF>y2lU+oLA-(U^--K`$v(~ zCDxz&c=#CKGquxi|8MDQI)q-*C>|J(4eqA+Ge$uixGgT{(+2TZnMk?SWTRJ5lwuoD zNue_ug+sbS5TzCDw&RNb26nJ96EadfBh*PB+D-KkVrjQq)hh_dtG1e$ z{#yfRpdjteSe&UR?yAzG;x7J?S*NF;(e82LY6hZ zSbdt!%ST;f2Jl4^fPkOUzKojEGxmoi+Oh`!H&=0$uq(PqpDBk&7b8 z_CHmyw~Lb9+$?1V8t7Rqu*&&mq{XAsFTOt}Y ziLG)x+^YnDqrj)`e^wGcvL#P2-+q1_ev%BXW(!s{Sj^6muIx5wA&7ElWuMP^lNCl- zHe_Cn$EM{?I3E0aK!Eg@6Zg2@FE{~#PzJ69b5EhWCy*`+hU-mQX>)rB=eWaLdf6Dq z7+F^M`hnj5m>{gEu`QbmdP7pBG-T_xq&CP1%R9;nBhJ~nqS*H~eq^--jq_+nfaB?) zj~xZJjP4$}Q;YovI8XN|Ikdjf!iXXCtX8D9?Onysn{eqJmgr!FFy(=@s11$xTQ4t; zY-YYSmdHK;2#(_z%5pJ#Y-wxz&SV06qZPfio(#($r~1ULCjA(_OCp$W&+8W9FrZ$c}7&kcHf`~2KKQEOtKIBB5cgtjd$oghxL}%A1Rxggk$|J z!Ej(uJxttQN)Obi7P{7+`4gW zlCk^3(AoJh`U;M&(jDSpzvs&4-^yK6D3aM(hiX$>8NkE5We#{I_oY}Y=tgPg>YUz$ zq~8+1I~Sy6IQ&RPF!E)I%ou__zVqSQ17JlU&b%8`b@pe)(CG}Yu#YO2JW#*G@j<#e zoZgF7G7~bZ6zg$8KiFQbt^@x_wA5N7MCBo8E&G2jbM5*OoZe=KYQq`J1qM#C8-jR3 zkB<_AUEn0Q3W@z=I8rw$3!NYy=lzecxeFb*t#w~kbRp6z)0QLqh-NZo45)1K$31^8 zV4QZ)Idj(4*%k|iuzaKnT-`)qLN^pIvL|!i4;^WXw)3>+YOym?wv?)(*DFi>J&C_7Wm<`F;RE(I6&^yoS_KALD)Dcl zinTE$S$Eq+cz_Go4?<=2m2OIClv&Lo2^q0t6vduF_DvK7%UqYZ0fx~2;S%9_-I#PZ zYn_{h9LaHd>x!~+o|9hR^+MuuKpwqiMXHB?Y6K^8*KA9ag6@j~h#U$_b|T*hC4hnwld1-Ti&SLFOTQL_4XG-kFI$Nb zmH(40gLl!rV&K|x88A>&^+sixvH_rAw-8+LDmbjQ0#~$zCDdAek~YhoA=NDE(y8u6 zH#z^(;Rp_*X%+>2&!jSTprdh9Z2y9{f>b8js<-bMT=uNrynGo|lW)r5{1q3(z6tZ; z$dH5l48i+4B!409LOaY$4Y}Pd_7ih0c=@vEJ&*@aK3jmj9>)TeFm2wRCb1~(wV=FUeCJl!InA~| zp(=0?1zBHfkp(PoZUNj^*Ko{5$BemPQDQ>qIeJI=)W&8l6OWY_z}p+JC*n2C&SVN- z?+(Hun`QgDaoES%93ItLozlyU+OFc^&ue0^-t)))RWKAH7u{_~Z$;UVmZ=-D^6v)* zse|KC2J}Zf2Vc0H9FPVoTRC$gG^!vt@u2v4AyJvpH!91Z6BXiP5cG(5a#=Q_xOp8s zacvWi1!gGIct1T};Ck#}0D^$jH3#Y%yL(=3IQ+9p+C@_m_aW5Afw<1m2?|Fl*si!b zP(`Br$B5(Cbs=x>)WkTcQAM#e_snSpWiIqjFVt0I||P*CkmRUo}!nHFGeKNe>VH9(WIJ7%m6qkQh)+n{Rk0uq9Vxc{$803xV}26 zob?1yLKPl1y~pZh_m)c&@V(!EfGm(Pkw0Ee|NZ;;Yxh=6Ytn3)usf|@V*4kMc?xb| zZT$aVQj94EtfM}R-Xadu<{)R6%=+ti%r$2KWVMlWX0gzqqdHkSG#KO$eQTBWq2+Kx zwW)>f*SUL%x^pD@R}K6!^|QmGU*PBsfiP_8JrA0X43S?piujdzdSYb5R+Fv8@LW# zoggn{6uP??pcVg2=sdlv5naNg!{HZ>i7wFDNBZV}1kjrPHBDR?EoYsQZ@DYBaIJ;y zTTV>%pViT=n(0T3Ak6rM~-7x3&v2e}$u+{P;b|(Dt*J16kwUThKAZ6nqnC%|UnZ zQR(DW`aq|wBy=V(`%(YbPZ4!MRrA63YL}@*WY|qnucV$*yas3dDwoef7+5nOWVIUB z;S2iz>XUKyXIEbG2$dV);%cdpS<0!TfvgY%VDFKgVe(wT)qY7)q~2=(38cNeraMn^ zZFJ#0KF+1~8jNydb{P%+WBO1%H(3IZR(V{*{zpI+G}rgTQ*oiJlkqwUGtCj`*(A$V z>|9;r3*3$m@QRKoMz|^I>ver}4B`j4p%;poF}tWeY~x_|mRfI?B3k*3y;ELh=dh60 z^n{%y!qAx!CQ#W;Wqa}o-?NG0iYFDu<{RBs!d9taI}dCV68qyLS#xMI>@Y=EtI1&_ zEFfDXY*rjdAsmDu;qAeP{Z7n&P{*>^z4-=`^WJj_X0>PF5u3HBDSO!#`02feU5<`W zw@<95K@|TYJs^~P_5|34F&bd~zj^gW$CX6qKOLZgW$lPc1Qc!44(j@Wub`;eiEXikZ}bDx43wua$m*zsZ?uam+n}& z{ZAN(xkG+@POzMlM|Ztrv?i4|c%J!fudyYrS+VXU`D8y*A;Py;O6|rh9KxobJIu7F zgT9f=*~E9A6#O%yydeCMuVnhA>0+Xe=KCW)a$SEkg$mb%AjWwo%#*oZ9DQ6&@nca7 zR!LjfDzt4khzx6>d$S^)Pf@;i|Gvo?Tj_a6s`php_FKa4m}?xt0`3sav(c)Fi^1~D zyJPxO1JZsKDE;t0%rnr(dW9f={B*966^0gmYB?bft#3lw%faEfzPBw*BS&3xwbJJ)<|nfb>v z054F+a`DNZ#p?Z??H+>nrb~zyR0fdmt!VOR+zFO&$hV?F5E+K_5`1f35Re4mRw**` za^;c!Mli~DAUXnq3$X9e$Al`0a-JD~2dq`2Bf%6i^NQL!n^Y)p~h3A=X4bZ0s z2?p*BK4(WsbAt^}cC3KGq`+Ua5kJMK@LPZXQ9Id~?xT&cD<$cHmIPqBB2bt-F2 zp*gm4W}6js3xow6{}`SCpQ)XaXzvJ`F+7%w!6c2{eg)BwM!%_k>z@Yxo&3BvK@Ri_ z8YYU*kk>{{y>9DNs}&49BRyWhM!`Lq#jqM@9(q7BV|8wAojS(z|nF&tWrT zQyfSo@(Y$>xAer7)3o_Hlg4~;8r@8>zVjsX(Obr>QCttG3@1RCDXP-tPS^x3e~<0| z8rZzvhsPY6qfe4AOY>^a$EkJ{?~a3O0I}0qK44U=#Weg(SFaouoenPLtKp?OWhphl zw?wN(H;Jzzl&X&`rx@1BGLU6TyNjKf|Yx^^?1saGbc%FgZlsgr#L|8{+D9$Y;D zvqp6n%b|?VJ?xTT?K5@bA>S;LZ+ReI>jY3Qnhf4IdUMw^RXCCy4{7njdOT$9+*FFN zgJZYwd>K{B&|uOYq5iT*Rch;jY)SCJ*m1yM;9lzTQ~ecGzr30lNBosk$lB`MawJF$p)F^pLqYHml0-Pv*X(~6%-RT~oie4*o(v*g)1p+#|K>NtjkR}1 z(+vdz=f>K?x6>J%k`ri3e>pT7dta`~^_a!V^+!nU_@vQaWf*Tb7}wayb!x3fX-mdG;yt zNa67Z56;8S#>&XVU@Ch|S;7N^e!T6NLwU~&1vhv@qTWPL zLOC41qG#&qmg)=|4?p+&xyUlh58kLO?OH0!O11`$3L9YK4S#LS7ksnhbiOQi~JU zX4rXN%v8}zd!pyibRi+jT&hqfOtW9nA zmVhh%6F4K@?!vS<=I*pbrmQ!18+vU3oMC_Dl?U}s5VaZcM-m29*<3vi^l(XuxRI5* z|F~&5QNF#1Dddw1x)nUF|J{g88j14PEO!FCoo$~AT>^R2_?o(4-H5aKlYV+VKfR;M z2;P`vj}csFp`U|wb`Gj9qOHfEQ^?v$$XQiPwA58C}WY-6<;^sZLs#Y_; zG|P5&QJ)YV+eM$f-J4!(Y0p%(122eZ_e}~;z^RtEa$0IyUb#%8||c%T%Te4P-wEx z_2ch}aB|QdG|7P(nq-CL&2&_Q57`eGcD*dq4uz8i+~Wg0D-Z#tRs%PUvV{@#dvT({w!XM%c*_;}L#xzj7l@CP zrxzMg{Yb2+MOw5zr=3ctUPZFdRhO5*PM7p!8Z4`@ACB&+Iag=!17GK~#O-_*JI}+7at2s4+v>)P4HtHeo@Mm3)< z7SSMTZHm@50;lV?jPOCB@PVw^*~kHW)nY%g8p%WNvbD;{LLF;gJ3I9iFuf`?mAeiE zpJ8;q=2NTcC@(9rnkX_gd;DRo98C?uot&}~*h%hq12~UMgxEsI?c+i&P&hcBo=5cxi5##QB7N=WQ@M9aZ zYJh=2sgj4r_uf$G(BjChh?Io!y2_?7-fH(A0?y<5W?U2&2(?35?uoja5c?6P`tX#k ze|$a>8*BjXz>XR52`>mbLcWnc^269vxDy%!uyWN4W$rh$K8VXU0y6v&*L-^6Sd~X@ z#QH&JCs<25y{%!vrIP69JiHz2K2tdkn7O0;57N_fu|g(|QhQus)*b^&P*|>;dKPcv z4c1s*ROFX)#p?XMjO1`*Z;W3%o1-Sq0-D8XM(WtF;N7Lj%MwU_D9-G*(+6?pB&VK} zK1`*jHB}F!$u;&`(V&ju@K{iMSU}W>ZWL*4DkD=#&6qbF+y5I>-%%Gq>jxZ-=sRC( zdE=b!<60iko-Ec4=^k>Dlpii6!$${t)k$Z(>I+;{c*tuW;VSSUSNQ2}8Csuk%Ii=z z*#Zrl=F2Kg8i^Le>+IfmW)DfY!JW?Sp|*y>r0EVIF-WEjuhdF%_b;9zji>KY5D? zL;?SPdyYaCe}8`tk$v31URA6N-E|CAC_S3U=ilOHmN0AEis_5zUt{6Q`8*aafBCQ% zJk;stIto{(d<1`yr$3U$L234x-O73UnncL8s?2XpZs4GGMRJH%2o!=cYNcpwu$s9( zJl+6}=md~r{vo#*pd9}4jn6WwclXJ5e6O<>t&9eju>_=7Ozsu=Gd}T!g1k>(T!NDI z$u<8YD>t+HhquQrITl{H)f^}sfFiUNuPph-E0#!s?f905p=gzLVR!;zV;Z6nCVXME zrscx?B_Ms7$%L^f<7hCx2aXM?q}Z7gZ7=pjq@YSt=&c*fUst?>&dU3)nwYo_5%Dy9 z3H8PKA~PPuG>jK=2S^rCiqy1t-=-lPYWcq{o2_xkNdnd=t%nM&ZxIEusCQ=xm-(EU7Givk-^XQcvjjt~eO-2(#>? zF2C4i6c)|R^O{uFo@7$pX3B!_Xl;bnvOC0Pnk{u-gTpPCzUO=(ln7iqie;sO*OSw=~X~Ne&mqnRk*IXEYfNYAufF>8y{@W+$25V$D7CDoPAtD zf2NHR1~8jpYb>)Gd3UALa%cKrPa8Wg9TGPSC)giNuI&~PZ+ov)jbpXtXCfY%Yd;AF|&urf+fLRjyA8X#2D=2en2G;rKvn0;=Oo;?R`-|F*@gMuxbt z(I;x#D+>n6A^jDHE($O}&&e{b|4x`;2MquEVl4)X4Fj}&Ega8-8(?0d421K40T!Uq zBIHlyT^94EpN(u?2gVL<7#V~ECATI`D^~oP)rVmP(SeD7>5pWVZ2ib5KQ~_t{8OOZ z3wZ^MOm|-LwWG=*-{JyM&P*pr8D|!V54cl0u$Bzg<3Yt7Ub}VIMH~m58*Hl~-)(6=TV8Iomym~XRxS&F^y_wlF~8@{(x(!|MjCpX_?!(X5FWSzs8ao9 zrSKR+Hbi`p_ATVX7wfuIX!}NtT@BiYQkk#2>7$AR{Su)MDt+Q5FUMnQ#DW4r;mcfD z!sn7Rt0=FAi^Sot$m~$!D4AHzMeG|yoTDnE@$a9E&p$b!^cF&y9a}db9$h#1 zr=TB62E0;kin*UpTl}xBCul(?AlViKX02>YMTiyo@vFWFU@5GMMQLBmG^+Bdl-M5f z3XV6xMkU$l87%NcAws)&aburlk}#9pa*gWI!z$QHU?FfOLhn_Wn1{|BUn0ceA)dDM zNqjH!NLA4syEDR#n@CzEO=Ej7D+j?99&T)EhM?7yLRRWad?T>X1L73FVBmgFDf^1t zUa%_nRANL-;F-0C^E)t-u0e=js3@n-?9}biNws%pQCb>U4rhC8R5l_FT|5H;lNwQ} zPr5 zAJCWUnzJs{r0oOJLa{1ba+l&Aw$!u992X{J3%mi3iW`^N{8s|JI41lF^?4tmq``Ti1&1l?;=q5p%sBSDIFe@q=lfYTq^X@k@39%R5wSvCQDii?Z z;S9{9rChO4{y=8m753CD_oate&0^C#AZBceq6UVUOWU-eoZe#E3$OUUtE4F$NpuXOQuT~7=YF9H=7)*xSYR45;4x;KZ;#cZUN{y3$WG;E6_gPLx~ zeF>Z1#f6@odhGU|Y_D18Sm|ZyKbYSUf3H*{zzBU5 z*VGJ@n{C2}N1~vbBUa&51eX1_X9+L>vm95awBrNAaBgCKeyJ&7rbR5=C?V8QcC<9R}G>nT}!YIKgSbIiA_zmpIhqvvquAjhB zoio;R8Zlbd?V2USwBgk_>@SgxesIRnLEN+sw9yy7s#K%;4arOXeuGK8w27Y-k)k@9!*VfkwkM!A%+jVv5*W!+b~d6bco9uMO&e#|A z5E&(f3(V>CS7kOlm-~q~P@Rr*NGA}8x{?;=_vdF?VMzNB7fcBQNAbFFCV+};r;1p9 za`{g$(@k!kyP4afNy7O+oN5tSXizc8aUj;@2|&eFet^R1Zj`YRs|G0$^qjV*g(V7L z5p~%R{lghT-%egDu6ECBWFCYiLOZ#{3va?U+k0GMw;w*fdm09zKjc|puaUK?gFjyM z;7Gxxvtk7@6xauS$WfRXMv$RHL8N0~;_kZ@hScLU5Yn>*@rcZDe#>(`c8P^3uo0oFR-yE^c+Fp`jQP;YOpi2xPxj?QhV2kHj4flb&^?5i zZB4wwD{KB;qMG2QJO2k=j*%4J+`Uc$i+D==wBYh-E{N3J^ z0;XhMWN834-rBX?W(#ciC>3^`7<&HsXZtuGHjO4UPT~7b4xVtxJ&|F}DXSN@`+o?vSu86MU&HG)UKPF`#^pkh2-Oa+q`Q6Es5No3uLi*KaqxVRznwS4((Eio~So0^q;Xd zKveM5N6>)8BZtoT=o*CkX{LmD)zW;=VI;I#uWDjr)Cw#c`mgL z)_WT+ar4e8K32gl#9^4wXmjN^3ZbL+Ji<)XsXW11uMojH;JC+Jct20Oq;O-X)&y2Kp>wR$TIc*M->X>sE8SyB*mE z^(1`AclUO_`-ZYf!2hG< zWb4YZ;DoktxbH`GkXX9bXmO?| zg6C1&lqj?%&xAImU693__8*QGizKAK zFJ`kKR%uE6!NlQt(lIO&d3~f%7YU0vd`=UpYq-p5OSQ)JX6fUYd~($vKpXrDJZ*R*9@NA$erJSm*en|2_Dt5ZpE;9Pl#T83nV!U`%reHp$*y6hKyK*sS-OY zj48JkG-MVljO~~mr=qv6jrX`d<9u{Q;c1)}9le?d|LQP*A-2kGqOE5UvKnJIP~CTc zb{~|z6Qcey4NU^G-$KvHb!*-y=kF{@;pLo71^^DrcDB^vS+7uJVFF-3$u)q)dM4%I zR)lR`3(u2^KUUd?@pnM+LpvbL7><~+=m1}dkWsa<%OwWMcPj8e>tx=rS&5HI&PUoMC3=aH{Da+l*fJP7MgOmdE09e0t5|Z(iDgCyYxtI?B@nE$ zZHs=v-#1M4YJDr}(bWhwLKY9Cd?qHm7zK|p9fT3r@?%mPt)2Mp+mzk2v-523_tJ|x z{CqiUzJ2hfsZmxs?|Bw7D;7eYLbZYfG>h#sLBfPOE_H&ErtRzQClWhr@P*HuZjjJmfV}REz%32t zf2yLfnA?iYdaIT^ndRz(0538qDHiv~U}$8Se!6mWz*DC3)iw4aY#~SS9+`hnBx2lc zd1=>Q-nQh2&g6@isR4JW+vUUrJiwz4_+lK$jX5I zVnCTiZ9@bpd6i#BQNfl^A=XICm5Qf7W+JtCX3} z9DPlA2saKc=R^gPx5~gR5S_EE!-&)s*VFP{gNnyJ)2x8qQBMmp7{Su>GOcW&q&Gno zg3cv{-(`;GXKQJ^6Z&W-Vj2@#J*9ykL!OY8T>?{ogZDVzVMiJ*LL+MDzDGrjp#SjxTh0=TQNImvp}97Y^BYw{@_g@+E9o7k4KZ$Z zXa{`lXl6NfR3hLixa|;JK)Ki!{Ldg64jaBL9@?YQae&A>Geb7fvn%eblme6aMGGgd z!HP1h?3xPa9Lz1@;{6B+^BpWFt_r^-{X#9S7^I8&%$=&vDF5dLfF=yLXuXz}ws%58 z8_T~0a2P`HSB8jeL|zQu2Tv2J>-=1&weAu3M224FC`R$?F>X}-a09u0X)F9C&}h_u z!8iTr_~vs#SIolx9BXoM{V1l@#22>$O)Ulji_iv?!7NN|%lAH-Mh^|P^mJq-6XX`l z`l|kN?sM8k>4!EtlJCdr+yLpf>Q5o9$zppFe0e^;2_x=`f##dz@Daeh!M)gL+b=Tr zEPHn@S+^@97MK2eW;E3Yq^nhqJ@-mc|mDKeZ{!bz_r!uxhEg+H>kgo_|&Uddtd^kfbu zpMj3?jjO)!e_folAM>zC&lxl%(W6Xe4jT{s0Yb-WQnJyOe8l``lpsa;U#4j&q(v&x zg$DElzX`N&4K`$^we(kxRjwvXQ6?FH@_jWT%54dAIVVKyK3PMorGRR5w0~iLl(#? zs5i>2S`}3dpehPpwfCno6+sCt1}dkuu^`KAYh_36)&AI!(5!^Qj+{lGrE>Nz8UJV$ z*J5N>k{o^-!x4rYtJXP)z~r^=vH!sa=k64x?s6jl8SA~Y#3!Bq4oi~nx7CHIk_W94 zwESK4%1*w#ydgVOiIYQU^57z!>~;Nfx`VO8u!{h>BvX2^V;r9Fpg`b}{lnvw-y@kd z7LYnxg=Z;W7|3v3f?|*Y9jdv*D zID%9RByb#;44-^IT!Rto?a7fcCs=9;nt+0msinq#F-6d9>e9LI@)LbrFAjWLy3~ zLo?`8YdCL|fSGW^VrxV(CHi1HrquJ!?vh}lZV#KQP_>U&UiZ?EJKCaeVAs!80jA6v zkdtsO$#nX+j}A;S&Nv&O->^^ILuwIc{csJ<5|UFi)*}e+LnBTJZP)nSW{OyE@cn^p zcG)BSH&k@ipwVbw10fR=RN}`TyCne=@Kw7Qlg?Us4O(D9exm<&d#j4`M zE;GCA3~q|_PC~Y=KwXva?|~?v^IM9|hXFv2Lp=y!MYfYWj{Pso(49APIUgXW7K^rD zrCSQylK=MvKWx7aFVHv#)4WP@a6*St(4_pq_T59T5^G%Ey|qgk`Nx{}TYB{R1V5k% zK42lISZQ;_{csh7#At8NCm+M3t!Prv<0in~QArg^wGNhFpub$;0bL7Ghbq=0n|Nv(T{$&TM#$VXlY)36Z=T9G&CoE_^3Kvg)%QD}o7A)m zb7rrr60Y|#$Gq!2>DdkBwAS6E>vABqVa?N0cyk0T&63nxYC!WZXWn#Pm|cA_>5dQn zF7wrJeVEzMJj7<|E^{55kMJq`chn<2L@Zs^lb>uSib|sreLFk)sygeFKd(=6A-0^k zM<`k;GeOm4;xDj!IBFA;iF{i9sR?ZCBZ~s9VBv9$jK5(3IiIR|e)I!c z7+&9(76wDYDR4g)U02R4?m^+%1)fKswp}tfL5mG4AfpO;smytVKR zbH3Y*ZvgXCq~HG91sL@687OYcyURC%OIw>ohrtU#cS4xMsRI)A4jjdWKlLm_!b4P;G$&Rokn#UQZe(gVQ2NrG&-zZ)hy};q=2zY zzzbS-m)K*D+_NGmo}B432wrni zd&!6#jqQbx8nR01MUKT}hJ6D^zA@&avS0OkV-p9ed2#dKF2gmJXdFV_zkW*zy4wbb zqE|&%a*jIMh@;j+CqKjmv(ah_U;L|#{DD;R{W<1&BAUwRc~DfgK*$>0Wk z)#>L{1kuE4oS=Uyf-EO2zfivOK}${97Z~;sa{N z{MxWx{MmcTf}(>$#laOs8WBOOZbvDT>Mu);fOzQVl)twwPf0QK1JL56iEWAbrBodh z^DxQ^{IaohZ)F_;jE9l@Yr^ArAeqjlU=zADG`I-pF~YzP~6A1n0KmC|$1lvIrWR6n;L#+60L$r)mO1 z1q!B$de$x2qpjy<^_f=p&V2*R2{`>eo=_#}|31PA9E*wxu&6W|UwHdG3#O;`I1mr> z;GI~8#Ht6vKC7xv<7`zYRkgeL1#Z?scvv#HpoA+&UQ15`aiiNJrUIz5Q?|Vp2bzmI z3}Q=B=JZd9rQb#`KfXM)(Z9%E+8v*c{gKHBVKo43!<7D0uZXge?Sure&e@S?h={43 zn4THbQgI);)`s%n=2%bEo3B2U354kZaI8p?sz%2(q95?alD+so{SRR|oV-=H!5s=`9s1F1Zj*+={sOBOh`-P+d$YgInPS(ZG#<%2g4QYy}|JtLfJg~H~QvPje4c=mqMpGgX?{y`MdctN~ zmK!ym{^K|Z)g+MitQq@5wSbCAM{U(dWI(XW3or~T3shAJ22XhYY^A@gr9JP_Qn)5h z)!q-5P~pO_dzksCP-a@`mJEW}hFn_p-Kw^mGUHlvoF4bd6m3 zY3f9Rour|mJ~}OQCQ=GcrW6vvbf?~go|6O@TPpE@;2UBedd~?Qg(G^5FMT@9liN4G z(MxU?OBIzcv9LLy5I1yUo1g~Gl0)~Nqx-QSjNwrYkiSSo!8i#jR^I@|ZkS4riZ+oG zje$tQSeuqP35!t1&aWp|I2Sdukl~Yu#i`?|+ z>gHBHc3P%6xbtt2gVD2{uS%fv^eezD4z_QpCbg6EaF;2IA{9Di$lsP)&8> zox0#CX*m1VzUxzxBTLt76jlwv%}?`ESH?Yvr_hfQ@&h-h883b6HT5qj0EW}sa^!rZ z!$kMK7A+k5wl9f7Cj*;JDo_!tY5nK+<+dGBlOJE;w*5vD2jxIkm*4DzkC=0cka=(N zt|*8?%B$D*zvI2lTRtun6%=_9JX+5C|zXr7K!tBWd4$+MvZv5!d5D@tJ)Sp+T| z?%^PEcb|oYM`L9+5yGxZWH=#DH^m4pv*S9_=F&$mg~UhkaqL$^RjQsD2JLq}?xP2J zQKw~5X7D$s?^yp&mY*r=Y<0ZLdLOSx)&0$-t3h#^MqZ(m+j&z9yK66paP9rGdr1O& z+8PWtbnM1nmNxp?8#lP&tVf(ZGbo;#CSQk?&mmL1pX;s8oV6aJqDaxV<&9DGx+%wa zHk&xfgy8|qhD7?KW^Hk&CdUJgfT+e77K=M|*0XS_upx*v=4R2S-#*nDhWrjiBFXzE zVVs;#tiJq^!FRbCQNv=oP%w~DW(vMi`-gH0&paU*_O$d#*L_}h6a1QxsN>X1 ztDq~s`E9U(NoDVSE#BT-?iS6?;C#-f3MvOy@t&3Kg_vCv%Ld4|SS070*_{^iTPZC#y?H zn`7UjHS0u4Lmk+eM$`_3*j7b(!5?%56XlEZiaS5tn*Oi1&jSu9KnD@v#o!6Qp#x{o zT5!1SlYH)LN?nlx9|+ISTG?D)+1?=xl9pyoNQ}!Yjq7~a6c<_6FB2HK65)w0d~qfV zrY25g7*c|Yo}`3cF#H`%l?x0_zKSyveCrLzja#&qP71PVcd$-Mwbs96=`s)=IGelp zDlp7Cn=P6>(uD}DwGJ(lg9~Dz#Vw6AGN9+PsRVJ0^df(nI$GT-V-ofj(UP@dez-l1 z@g}p%F%^kpOfZ-x2&Jv|q)aBo>2i%d`8ydH#+6>thdMI?_ckaW>zr*gpfxHX6}e~Y zV&m^vmC9GlWzdwj;&-1}nboWT5y>#)-06~xZUF6{hK3=bgGq}5Q#uZ9~qbbIKt+N0pS*U%%j4h>Y7&O7i_ExP?BCz=RaiFf;B~^Y`~4tfLm7@ zaTXL8Ltp}DWtYl@+JPIbV*W;UMjA|LjiklmMuCB0#mUTxux)a(o$yk`rQDm!#w#yC ziE_xTCDX7rI__x#TZZ5&ChW;90XcAM$zIgSi=4 zUN_N1Ap@+!wW{PAL8JvW?7ZdtU3j;rC6Q{?VM(Gp!4Q=IHJja(Rw0<}ttH;=jX^D8 z{O#rT!|!C@R?#M&c_Qu=Xblj5*>tO{W!p!`D!!r|XQ&#F|IJu|6}!SmJjWBmq2qQ+Br4 zJVicF#Hk@zpZ}R1>qu59Wh;(*4k*pM+hYUn+@@P_DvU8T3BR-ME+(+qwy<96&v||6 zTTkW?R6cT@JDIk5*J&@AU*4v@2LFm}!r z>Kx~wU0T~e%5Xt-eILY285EapMjb&jDDU)HBD8{9!eGRvHBtbZZUlruX^S5RkR(P* zE&Tdqt^fI|P>zn@(YaWpNU-IS@53E17_@*hQcSKeICWgv9*BzdDTjUT`D-|u>Y=z> z$J*f7mR7(6l5az=5#L~KZJh8ZDY96aEl}je1SX5#mk8Lfd<}Rk6_zQVI*G)5d4&z2 zs=Su!jH@17Xsh>{Vk*MO(gbo%OiYYEU!_}v)3GpqSNhve&k#ETbL3o69-wR?vq}Gy z+&tJy^&s&cEc!_Y#d3UD!nZdZ(~gZ{%KEe+*sR^p=G?-P>=EZ~UUH2)yy7f~>6INd zifnut;VhF4PuVzBUX+lZyhL1{ELpX%*MnZ-Kfe_q=gHoxzC+dM-~KtyU{nqGM`8!b zvW0R;zui1{@{)~+_F49)&O{Z7E|4Im^E|`ojm3hYUM1bi_TP`_rhOce@x`ap(@C}c z>}nd956BX8&s(PZ>6;5U(Y)8v>M+3ys6q_)eINnwn_%G={(j7<3(wJn2u= z`9j@g9(K_$qVauPw`CfSdDC>W&~Wmq<`zIa2+0Dnn4ZfwxJ73iWW7`}U%JSy_;Sfq zUYKLmu%oEd1tkcS=a<+)-hr+}OHp36D=MMP@)&zT9UFT6Lj%h^xjkgpe(348pxKzU z)blF_U@!h0kzE>ZuB5`GKYhUnXOjdpT&7D)YbvE;)iE%tt6%A|Y*{%eFl~vCJa_ZrXjD5)l+39IF2-Yl|Z*CdL zmM4fa!|`m^OM6B4xCn1Oa1_MvZj1p8(-~w@^$bC|qA`{V;ACeEmHV!LBcPz?ZsUMI z@3bbBU6AF0J=bv8q|K6R(k8|yqjPvbPEM=GG61^G=!+*VN%0$ zaY!l?L>|Gju|lsDS6;1_uh5wztDA-lBSX|Mg(Vta%!oOa8@RR!jN1{BHPz`iTmh*Q z{&2=rL&O$u-Rn!x4nS;h%3OXg3Ly}5HmFH&z$pMcZ?M*!#xWTCc6jkg2GG^U*4*2(v94u-Do2U7^6Rw&!s4S838C^F)fcJ*+L7p6aO;f_LZ)1jH=g6bHr8uM|m z{(aywPQ>py7oJPpxC1y0_0o&_9nktDkZ?zWpS#m@bc|7IUo>kU{V&+LT`zD-wV zsE^mH3@Rf3GNT|kq?1~F;F*pGV_nu^0R1#??JCm-huIT=@+sj?Dgo=|n_@{u$~Hlb znV3Oo>yROx9Jf*TR3vwNwy`x;eJY)8g6e|K>3Ny$>#uz3=Uk{5 zGc7ZxT=sY6+`SOu(@1kf0hV+aOQzd7V{*;c5+sU$ebhSkeFVpoE`46}B{$+FyR?Z& z<3bR`ztB}&;5Pi9$iC#XXY3)x1vpu+!qdX#0imi~!+IUWN}Hr^Ny_+zqB<9yYaNGOkYrS|2mnCvlDYwV8Z&9!Be zd~GJRGS*qnp=x^FD4FU3;j%$g`abo4qM{vFv{GW~M_VX*_SsAIuZfVYT0^_Wvm>yQ z8hp|W7afr+A@d4M!%Jho-k8W7IyB<-9hjlR1kai=vBDDHFGtB)Id^VzvyVMXlU;~m zyJ~F^5t{T*mB@d^NPwbGNdPU1K!!gytQ&^&?kP%l9vX@N!H3V&Uic`_P;H1pGFh56 z1t4z^(;A5w5ZoPI3B`4Nx#07lih3fbe;NySGz;)J6k`V;UcDtXAeJv;^r)5Hj`5js zpnM}R%lE_{Cr+EU!BpzJXL0XCRCL<1iOb(beDj%QgJ(2&ZYeA7s>z5| z-ZtW^o&$EJTrthV$ov1dIu#EUB=cEiW65^177#sdX;)a1CLU%>yd%K4^I{f(x0l%4 z5a$tKt{JKkp)&Qw za!VtiGz%YSIFZAds}7xo<~%-xDIR193>(XPleX!&!d1p3L+mnsL#~P{-j!;Op#4mO zka~n;Xt5Kn44{hD`C7^so=11m)J9@_>J4G+p=+&sB+UquE30G7h6~_^oZy((soSa} zj?&#tZNa+2M*6XVHsHa(YHcq9D?^X9_;ruIKMy6WmWaUT%*eo8m|6_BOZ1xc26#E(t&dZp*9<_ zxJySW_Nr87gQ|})bx*2%U;$cGWS*~zS35*+;{^0 zBfw4fiG5}Z2`|pluTU#MC!FJyrCMgTOs}<_U;RRo%RF_inB;1Cu7I z4ViQs)1k|n_Io)xy1tY%yN0mAKUs_C4V-#4;c9#3RfJrhN88`f{%T6!ehu@7^{`#F zt%PMvc`Epy6`NVDvHAeQ#~b)L9&SG25hh_2;}AORrkr^v4pWAVsPtbt z&Yh{tjP)TI8`|hQLGbvmUpUJ6ooXk;*|*+_ixpxw%GWubvXMi*!fJZZZg8vwn~v%;6&$d&E2vxT+WXbbftd2y*PPvZ5y}IKnMh zE4!Jr!prDL2U0a1t0>Ksl)R)b$Fa8gA{H>g6C%2G*)f_|DplU0FSo+j0I&kekJQ-> zk~c9NyJEuA^sCy)c2s-56~jtPFmdsr)Wawf2fOX-JgnE!u6Wi|=`6%)k>whNy-D4? zU83m*r#@p=wBQAMdl}ya#q28@^z57=-IYgZwIO5$p{H(7B8F}w!Ed;6k}p~qb(z_m zK+F?_>392{@KH-^2eXajw)on)wABP7AeE@*jR!=kZUN6Yk9p8{JFHa=&f1^oV%=w1ttH_j^ z!3B%rBgqcCF)v4?j`zz`Z+N4;y3#J zs-EB@nwHew4mThRWZ=2z%wLsbzJkMInRgcrusjX#&r3|aHfZ{CL$ZWD7dkN<(sc;3 zNiuk)AeN(e>57!ydQd;S2Dl~Q4lUK3xmPN-4Fuuahwh@H4iL;RqhA0xGu|#tN;_@Z zdtY*#Ry$HkCu_6oXtb|(d}fpuyiC`2ObjUo#2cgl7jY<2KQ_rRY6)xwWl0a@LmAQz zqj9Ou=dz|clL}G`U2I_5z!1fe0RFhD6yx>C{)453J*{l9V&#PBNhqzzOht}2*YvMI zYC+5q^gpiRtCM_7bf}TW-{6@Fk3kTo&imwp_hBi6J$jV*78e)AlyB974KFj?4Z~_F z@UB?E;ezD^C7_5EdA4ne&Bt= zcsKrn3<7kBuQ08_wt_SnE^yq*SrrS+Up8IY{&^JlOn12RO5-P#4mtr&8T>bhXM5Rb z*VUK83J9h3~^f7Wm%C~Ar zyfPj(`6R-+fM`y~O&0>I^?AD`(WS;D!8LId{yKLPH8KTFdiXY=TN%2Ud{X^R!X zvwSYYwjlJ(_f0W|GqPa>z#ZL*e{q@8)F@gV*iKRh7<*6ORp9eSPqY@j_~<4xtP;x% z?q-H1b1$J6IGJQ}}DU1dW62iesZFkgDtD0vOXRV}ak(SGV zU`RZ<>9Y8Ln+R`G#z4;wdP>PDBY?b6WembG2Gh%j!#rB5O?J^lFHl{kyQ^ZsBS^xs zyaGSL9kf_4=zKGdevSzAXeLmBcS%~JGAs9=CZGkKwRE>ox6_}AIUceDDX}29N1O=R zk4@8xML)Z3aGMmaE%9R4_xt>gNSUKXE-@tPe-v=SNA-o_=mct?@!$n6aql#9$qPU4 zuD{@SG&q!=M8M;C{+n2uYez7BqzR;8REMX+%oAf~I59a}u2j^4p*=&TP>Vdgi|cyH z_WLj-()dzQji|gGcTWT-v?EH6w_1zMRBv1<5@AawDq=>mVe=x|DdUd0FGv&sBU_7; zlk^9upA0JbY)tv_+?@UU_plgCiH>(cpfFsoPTrX1G%3?l3S|*y-|@ba&IOD~&#X%R zOfQwN+;+b;JI@Fiv+2^pO3X||`Qj1n`5ARjL>MXdPL(>X71S!bykd+X2Lu<6nUn!D~T~^rQ6)B9e|4sBEEvk6nGBf#Vb!8->r87Y3H2IUho0E!|tPtzQ_u zU}64Ekh^kpD$0mrxgRiJlX=#moM{T{h-#FC6j(Ai`|M4J>THvb}rtyqxuPtq81RI5^0*rErF&CdW(2O~vot$mAJH~^iDzZDsHbP4+@nIBj#>k0kA1%{#k2 z?i8J4y$E#wv6>$@mb}~D)nFZWaN!kCd8iD|5wSaQ*bd&)$b2uHRM;qONgI!-z9;`} zf*mzQ%y9VukG$cIdz))IT?@Jj2bJxkGFE4?j*Mz67NoJ$t#iu~vG|;+>X7Kr%zaV#hj4Kk)?Gi+28q^~45)mSb~&@01mg%-HM^2H0MTBdZyuwCqM&#|?I?VJ z`nwXi#J7bYE3hW-Am!s+``9>is6voDwq4Jn?7@bS$&(W`?@b>w{4M}KlkJy+Dm&Y( z?C`PoPl1qOh6S390VZ)!EcA*|g}Nf&m>^{C(b(KM9O8J1tA*Cu+ zV;11?ji_9iUZD@pijxaPJqhsYwd1o*)Cd##dG7BjT>O@j=72>h#+}I!C+CKA+QgO- z`IrVwxVn+@S4IzL>(!$+e%X8>q|2fuSHVb%%(?i^8NBmx2Kh40~zO`Y;JI$GkG=?m}11IX-TlmZ1-XlQ^Z7GHSsaZ^wlcg z`x_ILszYu}kx#6brPB2QEV~?pNo7Ng1jHt@ft@+o)9}X=bN0+>&=}7(Co8nnH!aB4 z|7$Lt>Bs6txJxz(`M_f&dE6FOxNwf!AvDa75qZfD>kbm8bjOO*z6O%2D?#9~u963k z*7Hw*;p|G>96r7~4ftXz2$<(dbYGzAppxjd$p*MgiVoCL#sa-U2O5o*cJhY}uaePi zc*L~+e}x)!6WCxzFsD`PrO)^tpL^SWuQ4NM-H1*=RBU=o#LJS#v_D5kJ{hz+Os|*y zLXo|5oZC4gqiQjgbi&s`5$6zP?QFn=FAJ1N1*WDAjVnre#Xnm zI-BZ=%|#lA1pKhn?V0^> zyc}T2s!@i%ZcTHK#}OMtgAEc@qJK64Cwr}m4MtxLk9Y#G3ZEu}!|mVRTELKVMcIt8 zvluk3(^egk{$9HN1CN8g8-(xoU13*2NuXV-Ab_7o zH90_ey;G@j*Y!UZ{K}x2L#-!|6?M1a#;LuS)AWhn0e|`#LNvCK77rUP2oJ#i(2xW} zQZ-obj3VN(tE-XTR}!#bktiW{F<2FOGXsn2xsD2zFT2kxJ}n9u(Uri(%*i-{`3~kA zG?hgSfCVvUqpk#L9+5zs;4rS|Olzj)J>^7=BO#I7dV#?V78*;HMOzs}hYxD91Jb}U zaub~O!8fT^O+e^E%F&RYT8mV)e>X@@F^J@ptNFSRjHbHXT^9o>Djntwan5RBf6=HG zH>O^tLK)lO0xBm&9txJJlellqS{k~`_+TKJB!QsGQo zX{vFHFN838Y(ebhqwZt?skS!$=&pXEOI{WMjFnLeESJU8T-RvcE3fG93U;%1quyhE??Vy_~E2&5BEGdwxUZasX4^VSP5&-8M;$FUMu+-Y`*+!Suxx z9Obyc^2N}vOsB^e*XGUn?EljvkQ=_}|-kr~41b)?R*Xf8{N zqTy})bQ+)ike&O9EdD>75F{Zeu=lQ6i8+zgEy(|tWLSQR>_3K3!?hsOQ<2U}7D*vt z+G)FkE~6^O-Shx4;J?HLn0(1X)K8Xj%`dP-w>QQOnC=b(TWQfwA^6!Q7ttYzc8m8! z*q_usKJMEJ91rQ18u+qGwZyco=~!|N>C0MFm20Tu4ckFi2Eo_ry&2yP_?|=@DjMm5 zl+j@fr*w@v_!lJ#dMAALpS+S;8NC3?f20iJ+_hHxHk+ijh_5dqZ#Fzyl%$&G6+mwC zmr3kTyf1NA#{J9mNc|CI{}a1(Ce~eHE?Iw5%FM%LW%tFe1mZS&_MH3C57AAPvfqDL@Grie4T7H81f> z>0j%yXbAi05>Jklz_I!b_j`f}q@4e=F++guc)Oo4R8Z4)(|xL&1GxrUAP4%qZ{Z1= zDLKv%ni3RgXeYn#;TA3Cw4`?adJt_@)&qn=PncTha!_-AiHliK(#A!u*z3LS>ZTRG zpSth2nxpYctjHYCmVy@_Mk*gAU|q?W?8>n=?Hau8DuXb9`ql?mn4^&LE!}un>qLEW z6h4+Z>#ZG^d$vrM$4e&mWzmMg=g68QWlI&5W%IBnj+7B?J(6D^2T1fNdq=^%CrAOY zR6249amR-~CAYMa)-9SO$2W5VpXz0?uo62dHgUw|1aXWS(J?0ihE`fMJ^uQ<^jFCR z-ckjcu4)ly5~QU=d)rfvhwu6kwhh}#qrAsC4ZIZlLqfM2yfU zgL^0J8IJu^M{dqiHZfg#{aBEI>Nqa%tbS43`s2>b0qRs{!L7e&PPOj@cFah|GCO%6 z*4q_~aMNJxBNa0IQT3L8|M1*W3Bh=CGy5Bw4pq?V|eQk28(RFFqkV zhrtK~D%l^j3To8*3g{NY#^NGLzakEQCA-cVgNMC9n6nt9o!S)!*m_ zdm<76eg4@T=PrdMAY3D>mYbajV3NDSzqpjV2Fi_idPQ?#J3|Z5WuEfCRBKJR-}%Oe ze?>VeZJ1HtI9&*Nj`64RmelUmF~V+qkg^!nbGfU6BPXEDFZ81L%F66JF;gn4R6|kO zE4GhEFTc;#)Sa)y=;brHT8N~cpz%nQNo5)dyD|$Txm_#6Ha3Z+^3n@55aFnSYhU$Sy zYKYpjWuG=n))?B4d_KZ+Q|eN6aYDQs8N^C{gN^{1qOR>m_^`pZXNgICK^O9gHp9%=d7otUE(k2Y?`6f!{0U!+q{`C2QXrfN9SIAd z{HC?taM&2zZT-UQIzhMJs^Ot_I!c^hjc|IqICOHF>48o2$of59)mFdq4%z)4`PGMt zZ5Ij)(bSRXVP&YZ{_dU$5aQGq-95>Cxl&;0@%!Rnn9oPTA}l6F`yb$AxGFaQLqNR0 z7-Bw5Qdtj3yygRC9+>Tk>>DH}T6N^Q`(%HT*s&lqP!<|>_9)x_i(g8p&CQ?sJlE`b zvR(2EAFtYwzQ(=@6MSTtrv$K(mgz#(T&oY+E|t-~iSEqH+TiV+>O4ZkoQlZX3^=}N zG@#>)DE4EcN;%q=*~2K|^-w;H+4{Ds=(g$jC$55p1KGBi`JE_sydQzPU!tBCGp&Q( z06rg8ycQFeaVu8EJ76!eqZ&58hZ?%y?J_im^#AJFU19CHxbN@S>2k7pkD8PHhJEHk zqVPiBKt`U^Y`-m$ejmnC=qO}Eq{J!IYuayY5qFs?M1oRajHQZd~gs73N)qa&pCU(}pGq$fr@UA#mmeyf}6u zh%ZAFl$9Z)mc_VA=1xFXSDobTDC58~rbX0%>XsAooE1uE`m+_RIO-44MFW=RQQK6s z%kx1vT$*nuCMrN~|fsk|rVF^QeZ8a*4meHd) z(RCXVDo9{SVU6nG@@ONsUU_^|U0g#!Uu(7E$4bGHoAcVhk8eIV4<2chC#BtI5{IGyw-NEW_E&lM^l@K*p8!-oZAWJQ$-@qYLj$7Um7i z>G{;SC%90XIvk4Rp>Dk;*slrFuG)^)xO1DNtqVxD42G%MF|paNc3)+a`um3zM>9$P zZ|TBF7Wyt-!U(N zKaz^~sa;ImRZiz!NW)OS^VA}QG(e&_s|H{q*)Tn6M7#1c&m`C3|F)6rHS8uVFKQEn z&L`Dqh=iI2PTej+%Z>^a7TyMsq{f;XD&q_Wg-);=-eKqadqQ$zi#Hz*vT8RN=gE|^hqf2I?ydznK5LaM*=zP8FZRH8_)|gJHZZz7n8cTcuJ}YobwCPY zNs`7)yh_C1NaKuZ!8Ctfli38Cpsm{Q3ezs61vH4hC0~|n3K}?Nu$7NDQ#u+_;ZYR0 zk!^8tTGHtMUWrzWJ$XI)QIom+_kGAck_LJNYhtKP{5Bo&QGsbCXx4@g(4Lo3rjiie zO|-bj=ul|JdN*mBrDSog5prlH%~~pHGCcxN&bCBq*n?qf$1Ec@By4M5Vx=UXG#ilT!(qCAR z`VN%AK1BXM0oX(r^ZWZD)8OHPOv}k#EJ*IZ}`bk!}-<~);9Y4r;o9et}%1Z&K0GS*@)8b1RS#z zvYsY(Ab!@{2VY=D7vAu+`GW;ShO#9gr44nV(weDmP>HEkW(n50)mWaF%r1%DnvTG~ z00WBHLhzhtNRGnfSiU8|+){TUqkS_d)tEof+!&&ynjy;M{$d!b;+03J{Z*Y-dBRMi z_`3~oJyGTcb0_bE-0U)up`uQ%T626oBPB$k)>V%erCyh(ye@qU@mWeS8`e#uKN>G;n zvu&At{E2ms)NEBSnmd~|YhV=-jQ*N{yVU9g4C_^QsZX8`OvXQWCni42J??p zNnx<$o)sRQeyA)U#6;6sih(5pv27r8YL;v`M^wq`ZUXP=5pVt629c=HOV1ttOUe!L^>#9vQmTq3 zSnZik8XswVgdpQ56xv(cA!F1P_2P(X^4SUGT^xSAo4(;|xb4O4I%L<7dhlGvTs$(< zuL_2Unc=f9AWh8Ju2LG!U>5R|w5&&rF*m{9ikxM50SYt@P`w?*L=|)|fZd z%9>6QsL?o;)Jt^lCcYG%x=`k zitms6+G4l(ewPg4h(m8XdAw=9jguplE-ZaXKXqk(%|T9f}7#mE(He~hjcK%%s6b1L;s{fk0Xehul;lJIv537%(D zKJG6yO9SBA-0BFjx2tyZ(?F>VQc?ii#P;)e6QnaMj!)rsZxRM6v3ir3v6+ z18yGE&~~{mZCi;RV`s93jQ*2E#NN&#QWkqzSHk3k)W{8lf{dJ&27b;yE~zoYGR(*1 zNw&k%O@t~Le4xIX=B(fMVNmwVNl&{adGs5)bK});)}!2(aY+)6V6E4eRJS}H@_`@K z7|8h|h$EPiHpUwzLFaC=EVkh-SG`i|CFrjpHcb~Y_n(?EsC&jR@f|`Y%(vtJ1lz=3 zoybPQEQyBf^AJ!bX{)#dBB>|9wEN~XIx^0GionV;u{zr}V8dln)Qux89p12kv6V=d zv`%V}^tZ7#{{|SAw))w}>OxIcm0biESC9j*D_+`jEVKJJ|DSzj3GxLY%QXObI@5%Y>+ocjyvx)#o|fMKuEQh-?;iH^l| zQ7HWLdD%Ctgz-}qdl-+Pw$#M%_yoblATy%VYtOGs^p=W2wh*&9G@zTtPu?(_lCe#N zdkp6y6oQf1-~+o7DIw_CkgJf>u)DD6$h1N60q3bC@pY#}MiN1vv%oHScbcyXPO&fz zF4!8JQpdKGyf$h*mP6Z)$OiBF-+0CkjC*r0_d7Ac# z+cwA)#~#7TYZ|V7;TeHku;a@6p{;XeUF^{DT+4rlnAT5*T?oK?h>vg|{tmKX>-;JM z7S{pFLuX%(^)M>#4!i5n4j!zctIvDj7k$N0N&)S|5i=y`BS+P&(6VF5%k5hA@DyEHs z=KVB!Tw0TakSwcrv zp0M8e8b2POJhocU(;&qazACEe(u_*ojA6f$CHr{qki~Cl2GG4zV3Pv)>V(>RtLX9s zdM8Sq&2r2thVXLK79=VC_$};v6Rjs|TB62*&EVr(o9p&Uu(z{Oqr5I_S~S=g9U73w zfytXXs>1;aTird&j{vtN8p5wsL=&N9t&#=GRe*wd`qx`Xk;{lWM{YkgYMA%*hG`kn z7!&28575&TN7~WJ#Tw#=OA~nvfS-xK`vFN;g2CY}euJ>Wlteq}FejEUKD!p6p!6W& zn^eDBHHne^&))tlA-=X*ncBlIQ4jhT2S#s$w?-j}K+q1-XN6`4U~c4LmKCG3Q_!z_cxd<=0 zPY+xw=E0K2dUpbo(K;h6)EJ`Q>9QHEF}`APbSD8gfI|%jNw_&jaaMU-UmF~O`){(L zz?9ldOi9=6IsRM^wCA5jOB1ld2q;OKzIV9Qe;>77r+KV}!Q&`pm`hrOs?NvKKdrP2 zyS^p&54J#juY@lY#JOLA)Z(ltdh{cU0nSJg5~yzU#&JQCFOQJ0nn?Fhc0lX^2Z}u2 zaz_Z9?cVu|diahIT}*?P&34-anN~~F)6V(cEumG()Q!K@*xtvrmNgStgKo+;KI;l^ zcZ4LsrrfmCLobXy8E>B*rEZ;ScA+%v?`k`#SE(e!X4smNW6ry7q`jUT2NwM;j9j%) zs*c8O`+vUxkEeT#bDqr=4XKEQtl~&n5Vl0e&6u8^&!|!n*KDgugHT{F2 zM5c}RWXyQe;RUyyN{-jJHb6k)8CP7a-%TMQvy(_WB-8{aeNXvz9t3=-QA3~INJav8 zGL7RX)}P4GiTAN_n#ae#x@!>;{)%TcG+GKIU6OC#EUn66#4L@z zDHplLBU~ZXvco%^vaU4R!6_cNq9bF%r-b`)a`BS(^9Z;fmPS#f_ub5)k^W*5{Ic=POG+gQW6-R?`Rj_-FS98r47vP|Q3zZWAf=IM6%72y&7zZS^uy}5|SZK1lgv6vuYhcJNTsI?RD zd7$P_F)Ev=;xqOs7(W>6?MZ(@J7^64!&Y?OKzI`fOvb4D1z4-;r>H1IU$3CRk&bz% zbDhj;E#IJDAK6L_*D-y>XQ6vnZ<^k&wC{H*chUv$hc;&zRRm3eD`XC}-ZeQ?6^r(# z01s991`!kuD?+eBph`w8J;B%C-kYwA*P)q)o&GkWfsN-C)lL>!e|Aem62wSKH;3Um@{fP;;|O-NxF z`FS1`q{sFT59(w&DDw?&UR|F6y1w5JEO4-Bn7DKPs|+}K(8s1zy=?Us8=JbFL=Mo9 z0RKzJMS1b34p3g3{#WJJye;b`^_Ycq%d6nP2@ZDa) zt1W=Ws>h-X(v+j!vIDwD7w73Q%1O^X+<^=`N1Rae0~AF^B%i#M+O`_qfF z_<+{xiblV=N2!Fbv_VKm$FKT1ECN@qS#sjpn^ynss}rD&t3ruq4~tgiQg4LW40E_f z{dm{zGrE&A;V!(I(PgxS(NX3=?-7})6w2*D4u7Rilc|>%%SJoIDWNNn^z+;kQz}V>Sftu^PbD&x5exvaged*@wh;+F`9%)WaWmE(z zJ^FS(rHmjyFS>)fK|Ty?ec${t#)U`pL{V_O1A)cN)qItpWSGf&{acC699XVJXqQD1`pg3wZlPr<$Tl zGgU8{w%Jn+37W%)NVPdA$lvDIkm&~QE%UbuxY#(ncXr$tsq)C;sr4~mf;3h4hBnEQ z87v_sqy!hm^SC89>bOE11?qMz@lYs)-G}Ow39l^g4HSsZ%D}CYM7YsD4CohBkL&^8 zyXig};RH!U{-+6Et;Wn0W{R{KFSesU> zFU*&y$mz@o;t`6ponL)HNAF%;=TlBvr6PGZ!F(RN+h{>cjKUtsTZ$MSmvOqBDXDd_ zI5&6SX!#v#gKx$onBA#P=_b+e$X*Kl*N#xECKUW5So$lPRp7R;IR0mfO3_AnA2Jed zzG79bs!{mCJq*s)^A$T)WXz?WS)kPGZ;zj@=KsZa-L48-7p9OQ{PTTTj|&WQP22lT zW11OT5mhpuL#?^{>O;brnaIXb-f*KU7B$riBf6)&b)*$-!sK*esPq7w+%j$F9b_t? zy+2qY_^SByrDsV#2P}Jm`bD{~T~K_Kok!y;KN*_`AXB`wn?05Nr*WJspblvdw69du zZw+|NW!(4KJGx-}Cw4%CX27|${zLh>@d+kB1QZKR*2gF;sd1IY2Vg<79wc3u$?p{h>r;1%HXr>-z?A2u7_eC%t2GU_}z+t-Qv7=-|Zr4=-|7SjM<8PRvgI0PUBiB|J|I{EeaY<}1$nk$u;agvN~mKS|!8 zD*4_Gdt3pwTtwmRWg;rKp`pa(j-t)rTp>f4cT*7*&lK_w$v|m0XVz`y`m;Sp=Yle< z8pInlVOr!c_O}w368c{}5j#8uPn2ZlDI}fiLE2Y3twU9wUUHl|5uoiVpYj5I{tZ>U z4Rmpm=_$jv-}+fQF~oEPAw}NP+hN}pNKJsEE!xT`fAs-m_c`3^JEVVVIBwz7b0Y-v z7YlIj#Dah7cs*~}C(_v#KMNeh?O1DD%BB=BX1UXU7YQOL>_Drff40C>#HDJDo#e5lHB9`xx`Sq&OT80iyW zr?uO%Br@7TxuFs! z%FNui7KVa*l?)I_v^p)8_@T4n#~Vg=Ix0y#YKsfwahUGQNaXOynVY&@<1w=!NG^vO zA&?s*fK)E0O4F~SJ9o^)|G7AqBD<{sr(_$_gZgOsCcLa0l|^9Nwe*rDz}>JIDH=nQ zes~m5jx;w!M&Lme@=d>KpO>c`DBnj(%HBLiT#64@yaPQ9>VPs_jX%Z1 z65t2U_pmVn!)TW!nNC=_pL(JpNFH)CsR_*HwStIdP7P9uZDLS0x@xCKCuf(=sAmFbPJ2AG73Ey}Yu;*rEJXzx_7D8;34l?roZC-M? zsl|bN3gH*$xsE=i{N~N_SX|z|iGJnQhC{S14O;4N!NssMs=N;5!&hoziU6J-@3n6H z->He3B8qIzg3Om%5BnzT^69b*nY+2r(ajr0dbZN}_l$mwt3pkDQoi!uN7L`cdT5A@nMk3^fS8KMY_ z=Rfd5=uzC(ZM^7#m5JuY9_9cr$wh^{z8e1tKJMyK^vrJ#tLS|Nz*n%yt$62Tb+0;H zNA+BgT5(kh_`Y42{$CP^4Qj?=NaAL<&&|1~9{qhQ!iDX2y#TdvuKYGvP8=ryjkD!h z?!<$Ym11eOwKH^ztYp2rhovM3OdZbO47*&eI0#-?p}DjoLEP%-Kitwo<$WabAi@v& ze#nDY1*xIl>AG1?ly);?TEQqeo&m{<7Z}pKDhfO*xCS`d!_KgSayP1nZ%rE*8Vfs8 zc`m=dguAF`fSWvNl!m{d1T0P5^VMozPzsMGpN)|HLkRE~7Zu~QiY~x_7=JNKGU_+L zH$y$cQRM>S+b}}nZ(~+xwv=%d9WOVm&zs8vUZ!@#lGTE<(B`E`@e%(ETg0v>?G$JG zB~(kq#X0c}QL9j!MG6B}k#qqnHlxg87OL2N;-toikj8^duRQe(A>0W82>ghk$pz?l znK(gQPfr7*l}$t1b&|YnM0#}dRKQ(D4%aTy(rp62pwDWXt_+!GRJR66PAHxlNtDM} zE4@`;gyp&PIoFg`ENcZ&<0VO?RnK=fbU~_Q5Y>X!FwOgqiNdm0?9ECMU)|-noVo^6)fg zySLwH(cXB9<=aq`B7FPb7>OD%BrGFF2}CHV+lP=UTZXBa~^C)oqc z?`gbBUm>caithyC##4N@IREIz8I*zJFaEJF?GzNbi|^saVk63*?ySUM3dB<5`2x1U zYQqqUufefqWWr~T>ydw2v5k2BJ`LP?$y>-zNTT^2*Rtg%RKcBz!_}8+GP5kzyu#44 zmQ@LvTcpwt>be@gK`!44T2O9GO;Ig*vVjE1a!!Wt!3s<6c{pvM=WG8bH7kLIs+4AH zLHrZqn&#GwI6_Nn+iXkPn1OM{n?=<`vRIKAtVNq!}=m$gu|R znDO64U8_XWkF8_JumNb$B@z&rA$w5!e()Z4KOA%aV&1KHhV#|Ck#FRchdN3f*g4u9 z%&JqC+kH}(5Bs9yCMEaoZ~ri-R7axDC|8X*qv~yeIZd`*1rR}JP?yW>~l67hmuz-&`Oqwl-xD5j& zs>Ic0KlxseN_^PXq?xAu(p90U?qtCeIKM<~VW~ZnikF^M(w6UUdW!F#ztF{hSxSS#x^UmfB4g)zXPy1_-tFMcAePu(2 z5ENgBG4P0RYb*P(T)$0~^exA9ZNABV@;9b&v_FUHfgHwuH`bbEZAx}gDKx>D`5njz z#M0Q0hOG?S;pgCE>8m3I>11__USsH4n$l8wGf^N*d{%UrdAX1ul4gWQ$MRFdffHOC zkdwX;+df~28m8Z%NwFykZ8(yl8XW_CYa0~Yq2^GyZo8gWBHO`d$nm9k*fU0#4)d1p z3^1j^F+44^EEJ5di)s+14#c+RW56&Rn<2_I1qm@eNF9dH(;mb7LHWKa9~F!PZ#Viu z=f=Y^wpvPT;|aK_-3ZS=zXl9ZeGGgksr(I@+a$%ISQrI#c2?ZJ9LoWw243P85w~#_ z)%dRs3F+^fU!|Fd_kN?;!!D}Tt|x+LzIcB&OXvPlVR>zVCl#PTCKN!@el$aLv*;u( zrfP18LPvayo=}C>Yk`?uGKZCHj;@!*d zZOu=7QFoE8R|4o7}ulNZQgec5aWd_81rC$>TV>4@w|JIx9Kn}*wdC~3H ziabA5$pzvOE~}@fvq7BgQ-h@AMqY&Vpx^iM`@6M#|Iwa6tkHYJTAnwxVrhrTPp68c z*qdep;iIroz}UsmU#@4H>{W%vT%pejkZ9c0SwzAeMh02Q|OSIr*G1MuDNm3}M@? zJ+EE|N)xYC>0l*!3Ob_{W-u>U6Cpg=SX)mPg)lDjqu}q`5g-!b; zFsl4MWzLOYG2ZUPN9|G^>DXrr6Sm;3lY6>G$~+7Zj&uomLa;0xw3wl-RFPZ=Bc8JDpCBL-B1Y=a5qLi{Ko^u zSuv#{6mEL$>4kbcws&?Shgr@~7p}cv{TKwhDpb3UPQ^`GW#@CZvQeAgOuGxSnZ9cR4V&zWt*_UB$jpCK7zDB& zI+}z<-UV~Ak$bAubH7nsNm1g6V#eK5TsnJi61_i(95IFHPSGMI+ecsHTCem#{DicJ z@D_$(>O6tDdB_$bN>dt9ABa|2ku!UhUNk<$ALeJWpM^8>0m9C<`m{=g=QdceRd)gW z=XlX5Q>6%1n9N?b^}=xwhw04CA%q>QQkJ&}0#a7}n$dhd8ubsdJb&L%r1cXbbVDJ| zy4Qc86Dv{ROi09fjLuO93M2)RdolMfEWWU2l3e11-X{^(6qS%yeyL9sXA~?@TQipR zw?J*ff}tiz64*#zxR;rjKHCpA`p)@W#zJPEfTyK%4o42gR4-J56AU8^aXe!e@{8;} z_fWwfV(u%Wn>L47pZRWv)#+ez)*hl8Hyfycirj|Xepxq?;*?pWd7_jcX-)(lIVMaRQyUD`Z+^sUO?^)ZUXi=q7^1U=qZzzM@TRN85Vw-D!8<`@jIq zus$iu*cfA4`o~;lY_x`_$1t!6W}!4cOeLF_04T=z%6K=m0(S{{W}46!NN}>8w(bX} zyo;NY2-G_~{NH7?x6dwXxE9)cLaGia&I9b27>;c%bTk6vT**};)3chr8id=J!wn#C z!a8YoG3Ho+5N0BmwWU@VU_GySV^_ppJ5x_fj?IJunoL(qg z`1z-^S!!7M#lg@BZ19?e+O$I^9jWe7R9oWyaSZ08tBnNnc0>^7!Ve|yAPw#8Yax`# z&o(K9O_idBH%Et6vndv*`f@QMwLpg0wsQLq-f?c;06jd7?|%kwkts?~e?bUkcOwMz zF#B4L?G~5@Z^%5&Pn)_?xVX0L>me|>Htte6u1WsgK42lmgzBPlTT?l}EMHNJC{^Pi zlD5e6{2|VFu0eO8zT=9)s)a_7`TAm<i}_p(e}*^gRwrlE zI+DcW;U8D14(a`9jwcFo|I`+aZ18G&o=W3r0t%r~?M8BXFZR*)_7G6KvW(NYA^W;m zG*BB)v(NR6SPlN(*2qINju>VUnf(TK_vFxH8--xzFyYsiydk4zNOgg7&jB;%rVPS( z6n53WLw+mO8-vD;`Vkng(MewcrXAJnvJ^uv`f!Vlk#mxUm0YRHo357HEhBmXHDm>` zl#h%sbU{yc>cFiRcLdBmyY@h(7)i-TVuw{}s?tSzOD(?HV;?TjkGk|9M^X?SyQ9T> zX*u=-3pMC~LAo4-O)vPCqum}t?s|>Ah33jM-y=uCgT9z)VThb3@r{{x72xx2tkb7O zvB)>bP{gS6?gJ((F)1Tm)IhC#^C+O4&`c$(z!j^l%IJFa4p}GCm^!1hHidR^s}df% z2#W%vO|68nSh~`}0JkM5b_FCp^aF_#m=QBP8QgR!C%`ER2l`!FgQhJ!+gOU+a8tun zORar#`Gzeazdi?wWTa2z4KBSiTRjEFa3~K1CYfwPf~QLR?oy4dNMVP8XH^~T#na3= z8GHagN|nA@Rj_YjvCMT_?kUY-rmY^+D9B_5QOgWItrmK6>Ao6fA*XM1C?Wq|ob!S( zSTFo3!@q6Q_fPtZ6@O;Q(nn@0Z}*pFCa&RS=d)a?xg?v~rZAdc!6d)@f!(F#FM>2_ z4?Ed_q1Q)ylWRiv!e=ZEyH;;f*ZC4H!rgUN7?EC515osWl)A*z&j*jmqevCiVr4Yi z^_{f%#^ zWECouj`cKa48hN_&?CN??=04uaG?vYCE7Xzapko>BhP;t);1DW0=daL{guXs1t#sj zx0AUO?ScZdHctQgZcOn_`iA5Zx{xrLx5s(@lzC+INVFLlS2SJJg3#$~M@;XW!;?xp zK4}rywvlNVv08!ed?6e(vu{4WP-A2?*l^z$)D{~@)H`wyCX|ld3s}De4!Fk>mgqM1 zL~K7*z3bC$)%-S|FHmhlHNB&576aIAY{SHtdhzTezJ0y%dLYprWv-;Z8QeGGx>TNT z!?3G}7->GJ^cR7McUUB6IVexcWy>XJh^$9H4}{m%I^L`#B#$l;a7Yd9bzmn?ANN*L zW&Cuxk3gIMMeaNLWtM+(oSt^R?#v=(1k9pes?sI2qzZGOB&n*^dYAl119`qOUvcG# zHBKXJ!PH0+4L${Xd*mu#p z#TpX=HC}(5vNiMuA~CN?FVQBs zCpUoS22xfee6w9L=yQpEb0TwS@J|7(K%6l_w0=L14kwW#bE`-m`5FY7Zp_v^r!ryh z8}mYcnuW&|t!2Dj@vCqhZqhZ$Z4VcZj~Y|Yr_CN9HEoyGY&ZUz#gX1S@Bmr*kMp|T zyfsba$B4F4{8#}uu=8|c=b}3mrDbqD8m^|?CXBf6+}#La4B{UvOxxJ*!$K7shcu+% zOV0>bM~T(#g+YB9CJ9u@J)FtUkQi7d?=OAa(->#=U%h5b7)oC*BNVD-p2NE5>^8`>*Y+b@%j9reP1yiV?E!Mfv&u8sM5M3ktOyNbov!~SghN;_x z*(r|e%?-l);ushPOpKyTvH0`OUkB`JcX){(AwTDh^-gY*Ifk7ULn1bZ)R_CMBXtNiSU=s!&NDZg0(lmejQj zSi^his~*!HcN7_l>E=&xKu;%>biJ!ssfcsji{TNxW+!$fU%YEOOi*TqUo31F@QY-G z1bxXQS$3@gkl9<=pUBhnIl_mLJ6#$srfvo!=}Bf5$n-!dSItJj=K5&KrYK`Y&VUkf z6sft)B8!mJ4DgDspgWFLbV$~fQa?D)a`u)%ERSj8WXjeT~+Yq}=qsFYf zx#4@yrJCShQZ9sQS0OZ*sdF`-fNQ5EP8+#}I}|H&i#O(MmMyGn&VY<@M*mT*$LnJ2 z@zyn_VXSun-rf@Do^G0;)jx2C)fxSx`UHhQU%c<+rCpdV$Vmm{D~Hag7!{K<6Axeg zBHCNp;DK^|ML)u-7=BuL*|s!rvNtj40DKSrP(L2%5&=bH<8^|im~B(N5EHL1jx8VQ zdy1$GA#&p>!|1ssAa7bngm^xBrv9?epA%WcdVx@=MpIZ|9ZS6F(!^M^oLD5*OS1xJ z!MyL~YpdZ}tM*R|eljL;kE?lUrbKGdwbGk-M9gG@wmVYX1KMf>Px@(02M=u}4ai4i z!y;Cm_$>uYUsae%#^VF}-V1M{UgkG;+6)N-8h0fhg@)BB@w2yo&uuLPRkW2BC}Wv% zr2H76!@EOCFL-8$8Nwsk!tp=3dR=-3+*hLc8Osa+ne(j2yCQ#V>AV4c?BUeQlI7KM5 z_F&o%k?;LKxk{EMnb)A977C@51VRmQq?dLb9}y@R29%wvGWm}B_VdJDcW2pqSiERJ zXZQtdt1ESP!0v|Az$ZqBs+6Op(>U)#wI$T4tTL_tmdWq(<*_QN%JZK-QwOF)_vKfU zl2}%>60M__47|)p^GF2U7cfusj*+(MgJB31E&NUyY4guiQF(KemgWLlLC_jXTy6T4 zz9XRq+p@>F2QozUnl3WDpX==071-b=@8CL0B65lCQi zfCiQR&CR4ZluOK+CI||u?YbL*1IyA25$w)pTfk9j_h zhY|t8^8Bb__-L$<*|O$-UB(UB9W=#k9)kjg1HhX$6Yx7K2w@bM5lkxz>iM)*L%O?Y z>oL!v?K{1{h?uw(*g(84g=Y=HCHq>vP90ce5i#CRjJk%*7vaX!5*_YKoyn=Y#*z-VR&x7JeOP$6@Dh_ zG6Xzub#MT4rD!$k6zawl}PddD_-0Fos_dS_OM{}pTQMbz8CTqz}gBII+@2e{&Oaa zC!8fHw>Blq@>avhB}Aqm{8eDJ%LEi6Wi!hpAJWQ2PEA}{%=v_9k)7VZ{TgcGP)Hi= zbmtyChN?nEhGJ9Ba~NYH%ePe39u!6n(k4=snsbi)AFBnB_ZBw`HSp zhDGCS>o$b`0D$&qo+8TtkWQyx%;`$&}N!~t&gkA@J{@ipq8nz+u7 zrA^sL+C*8O7aVQU#wce_fadhDw!z`L*T^ZiFciink{qU0Se*jQY=(M7fRfrBD3}fv zar?S7Uu+F3a*sB2#3W_~ub}c|Ly(B`Fl#gTY7x_Hc%oaXo74mBexT`Zn5C|WEn<41 zH07WO_CWIdS{em5Nv!?bu>k|xH58V*2eV1MOY`7I;vbmT34%TfwrZb9dU`$eW<9LY z%k(msrL3g&x^m8yf>I2~BT^}|Ee1dd`(;2SjmFwVft$05EipNE?4W|Ui6Il3X;nOr zVVO&2Cc|3Eho*>kViwnY`qTP}Hx{5O!A|ZI`>S}WF=ea BvI1=U(Dwt#O$r}UvM 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.*)" "$HISO_DEFAULT_IMAGE"; then + set default="$hisoDefault" + if [ -z "$HISO_MENU_TIMEOUT" ]; then + set timeout=0 + else + set timeout=$HISO_MENU_TIMEOUT + fi + export timeout + export default + + vt_fn_mutex_lock 1 + + if [ "$hisoHotkey" = "F2" ]; then + unset timeout + vt_browser_disk + elif [ "$hisoHotkey" = "F4" ]; then + hiperiso_localboot + elif [ "$hisoHotkey" = "F5" ]; then + hiperiso_diagnosis + elif [ "$hisoHotkey" = "F6" ]; then + hiperiso_ext_menu + fi + + vt_fn_mutex_lock 0 + + unset timeout + unset default + fi +fi diff --git a/src/grub2/grub/help/ar_AR.txt b/src/grub2/grub/help/ar_AR.txt new file mode 100644 index 0000000..e7b07b3 --- /dev/null +++ b/src/grub2/grub/help/ar_AR.txt @@ -0,0 +1,18 @@ + L - اختيار اللغة +F1 - عرض معلومات المساعدة +F2 - استعراض وتشغيل الملفات في القرص المحلي +F3 - تبديل وضع القائمة بين Treeview <-> ListView +F4 - تشغيل ويندوز / لينكس على القرص المحلي +F5 - الأدوات المساعده +F6 - تحميل قائمة Grub2 المخصصة +F7 - التبديل بين وضع الواجهة الرسومية <-> وضع النص + +m / Ctrl + m - تحقق من صحة الملفات الصور (md5 / sha1 / sha256 / sha512) +d / Ctrl + d - وضع Memdisk (فقط للصغير WinPE / LiveCD ISO / IMG) +w / Ctrl + w - وضع WIMBOOT (فقط للويندوز القياسي ISO) +r / Ctrl + r - وضع Grub2 (يدعم بعض توزيعات لينكس) +i / Ctrl + i - وضع متوافق (فقط للتدقيق) +u / Ctrl + u - تحميل برنامج التشغيل EFI ISO (فقط للتدقيق، غير مستخدم رسمي) + + +اضغط على ESC للعودة ...... diff --git a/src/grub2/grub/help/bn_BN.txt b/src/grub2/grub/help/bn_BN.txt new file mode 100644 index 0000000..b9faa3d --- /dev/null +++ b/src/grub2/grub/help/bn_BN.txt @@ -0,0 +1,19 @@ + L - ভাষা নির্বাচন করুন +F1 - এই সাহায্য তথ্য প্রদর্শন করুন +F2 - স্থানীয় ডিস্কে ফাইলটি browse করুন এবং boot করুন +F3 - Treeview <-> ListView এর মধ্যে মেনু মোড পরিবর্তন করুন +F4 - স্থানীয় ডিস্কে Windows/Linux boot করুন +F5 - ইউটিলিটিস +F6 - কাস্টম Grub2 মেনু লোড করুন +F7 - GUI মোড <-> TEXT মোডের মধ্যে স্যুইচ করুন + +m/Ctrl+m - চেকসাম ইমেজ ফাইল (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk মোড (শুধুমাত্র ছোট WinPE/LiveCD ISO/IMG জন্য) +w/Ctrl+w - WIMBOOT মোড (শুধুমাত্র Windows/WinPE ISO জন্য) +r/Ctrl+r - Grub2 মোড (শুধুমাত্র কিছু Linux distro জন্য) +i/Ctrl+i - Compatible মোড (শুধুমাত্র debug জন্য) +u/Ctrl+u - ISO efi ড্রাইভার লোড করুন (শুধুমাত্র debug জন্য, সরকারীভাবে ব্যবহার করা যাবে না) + + + +ফিরে আসতে ESC টিপুন ...... diff --git a/src/grub2/grub/help/cs_CZ.txt b/src/grub2/grub/help/cs_CZ.txt new file mode 100644 index 0000000..53a5f0c --- /dev/null +++ b/src/grub2/grub/help/cs_CZ.txt @@ -0,0 +1,19 @@ + L - Výběr jazyka +F1 - Zobrazení nápovědy +F2 - Procházet spouštět soubory na disku +F3 - Přepínat mezi zobrazením stromu a seznamu +F4 - Spustit Windows/Linux na disku +F5 - Nástroje +F6 - Nahrát vlastní Grub2 nabídku +F7 - Přepínat mezi grafickým a textovým režimem + +m/Ctrl+m - Kontrolní součky obrazů (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk režim (pouze pro malé WinPE/LiveCD ISO/IMG) +w/Ctrl+w - WIMBOOT režim (pouze pro Windows/WinPE ISO soubory) +r/Ctrl+r - Grub2 režim (pouze pro některé linuxové distribuce) +i/Ctrl+i - Režim kompatibility (pouze pro ladění) +u/Ctrl+u - Nahrát ISO EFI ovladač (pouze pro ladění, oficiálně nejde použít) + + + +Stiskněte ESC pro návrat ...... diff --git a/src/grub2/grub/help/de_DE.txt b/src/grub2/grub/help/de_DE.txt new file mode 100644 index 0000000..8c4c328 --- /dev/null +++ b/src/grub2/grub/help/de_DE.txt @@ -0,0 +1,19 @@ + L - Sprache auswählen +F1 - Zeigt dieses Hilfemenü +F2 - Durchsuchen und starten von Dateien auf lokalem Datenträger +F3 - Wechsel zwischen Baum-/Listenansicht +F4 - Windows/Linux von lokalem Datenträger starten +F5 - Werkzeuge +F6 - Benutzerdefiniertes Grub2-Menü laden +F7 - Wechseln zwischen Grafik-/Text-Modus + +m/Strg+m - Prüfsumme von Abbilddatei prüfen (md5/sha1/sha256/sha512) +d/Strg+d - Memdisk-Modus (Nur für kleine WinPE/LiveCD ISO/IMG) +w/Strg+w - WIMBOOT-Modus (Nur für Windows/WinPE ISO) +r/Strg+r - Grub2-Modus (Nur für einige Linux-Distributionen) +i/Strg+i - Kompatibilitäts-Modus (Nur für Fehleranalyse) +u/Strg+u - ISO EFI-Treiber laden (Nur für Fehleranalyse, darf offiziell nicht benutzt werden) + + + +ESC für Zurück drücken...... diff --git a/src/grub2/grub/help/el_GR.txt b/src/grub2/grub/help/el_GR.txt new file mode 100644 index 0000000..3cc35e9 --- /dev/null +++ b/src/grub2/grub/help/el_GR.txt @@ -0,0 +1,19 @@ + L - Επιλογή Γλώσσας +F1 - Εμφάνιση πληροφοριών βοήθειας +F2 - Περιήγηση και εκκίνηση αρχείων στον τοπικό δίσκο +F3 - Εναλλαγή λειτουργίας μενού μεταξύ Προβολής Δένδρου <-> Προβολή Λίστας +F4 - Εκκίνηση Windows/Linux στον τοπικό δίσκο +F5 - Εργαλεία +F6 - Φόρτωση προσαρμοσμένου μενού Grub2 +F7 - Εναλλαγή μεταξύ Λειτουργίας GUI <-> Λειτουργίας ΚΕΙΜΕΝΟΥ + +m/Ctrl+m - Αρχεία εικόνας Checksum (md5/sha1/sha256/sha512) +d/Ctrl+d - Λειτουργία Memdisk (Μόνο για μικρά WinPE/LiveCD ISO/IMG) +w/Ctrl+w - Λειτουργία WIMBOOT (Μόνο για αρχεία ISO Windows/WinPE) +r/Ctrl+r - Λειτουργία Grub2 (Μόνο για ορισμένες διανομές Linux) +i/Ctrl+i - Λειτουργία Συμβατότητας (Μόνο για εντοπισμό σφαλμάτων - debugging) +u/Ctrl+u - Φόρτωση προγράμματος οδήγησης ISO EFI (Μόνο για εντοπισμό σφαλμάτων - debugging, δεν μπορεί να χρησιμοποιηθεί επίσημα) + + + +Πατήστε ESC για επιστροφή ...... \ No newline at end of file diff --git a/src/grub2/grub/help/en_US.txt b/src/grub2/grub/help/en_US.txt new file mode 100644 index 0000000..a065f70 --- /dev/null +++ b/src/grub2/grub/help/en_US.txt @@ -0,0 +1,19 @@ + L - Language Select +F1 - Display help information +F2 - Browse and boot files in the local disk +F3 - Switch menu mode between Treeview <-> ListView +F4 - Boot Windows/Linux on the local disk +F5 - Utilities +F6 - Load Custom Grub2 Menu +F7 - Switch between GUI Mode <-> TEXT Mode + +m/Ctrl+m - Checksum image files (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk Mode (Only for small WinPE/LiveCD ISO/IMG) +w/Ctrl+w - WIMBOOT Mode (Only for Windows/WinPE ISO files) +r/Ctrl+r - Grub2 Mode (Only for some Linux distros) +i/Ctrl+i - Compatible Mode (Only for debugging) +u/Ctrl+u - Load ISO EFI driver (Only for debugging, cannot be used officially) + + + +Press ESC to return ...... diff --git a/src/grub2/grub/help/es_ES.txt b/src/grub2/grub/help/es_ES.txt new file mode 100644 index 0000000..11e144d --- /dev/null +++ b/src/grub2/grub/help/es_ES.txt @@ -0,0 +1,19 @@ + L - Seleccionar idioma +F1 - Mostrar información de ayuda +F2 - Navegar y arrancar archivos en el disco local +F3 - Cambiar modo de menú entre Vista de árbol <-> Vista de lista +F4 - Arrancar Windows/Linux en el disco local +F5 - Utilidades +F6 - Cargar menú de Grub2 personalizado +F7 - Cambiar entre Modo GUI <-> Modo texto + +m/Ctrl+m - Suma de comprobación de archivos de imagen (md5/sha1/sha256/sha512) +d/Ctrl+d - Modo Memdisk (Sólo para WinPE/LiveCD ISO/IMG pequeños) +w/Ctrl+w - Modo WIMBOOT (Sólo para archivos Windows/WinPE ISO) +r/Ctrl+r - Modo Grub2 (Sólo para algunas distros de Linux) +i/Ctrl+i - Modo compatible (Sólo para depuración) +u/Ctrl+u - Cargar controlador ISO EFI (Sólo para depuración, uso no oficial) + + + +Presiona ESC para regresar ...... diff --git a/src/grub2/grub/help/fa_IR.txt b/src/grub2/grub/help/fa_IR.txt new file mode 100644 index 0000000..5d1e8a9 --- /dev/null +++ b/src/grub2/grub/help/fa_IR.txt @@ -0,0 +1,19 @@ + L - انتخاب زبان +F1 - نمایش راهنما +F2 - مرور و بوت کردن فایل‌ها در دیسک محلی +F3 - تغییر حالت منو بین درختی <-> لیستی +F4 - بوت کردن ویندوز/لینوکس روی دیسک محلی +F5 - ابزار های کمکی +F6 - بارگیری منوی سفارشی Grub2 +F7 - تغییر حالت بین حالت GUI <-> حالت TEXT + +m/Ctrl+m - اعتبارسنجی فایل ایمیج (md5/sha1/sha256/sha512) +d/Ctrl+d - حالت Memdisk (فقط برای ایمیج های کوچک WinPE/LiveCD ISO/IMG) +w/Ctrl+w - حالت WIMBOOT (فقط برای فایل های ایزو Windows/WinPE) +r/Ctrl+r - حالت Grub2 (فقط برای برخی از توزیع های لینوکس) +i/Ctrl+i - حالت سازگار (فقط برای مشکل زدایی) +u/Ctrl+u - بارگیری درایور ISO EFI (تنها برای مشکل زدایی، نمیتوان به صورت رسمی استفاده کرد) + + + +جهت بازگشت دکمه ESC را کلیک کنید ...... diff --git a/src/grub2/grub/help/fr_FR.txt b/src/grub2/grub/help/fr_FR.txt new file mode 100644 index 0000000..1c8fa18 --- /dev/null +++ b/src/grub2/grub/help/fr_FR.txt @@ -0,0 +1,19 @@ + L - Sélection de la langue +F1 - Afficher l’aide +F2 - Démarrer à partir d’un disque local +F3 - Basculer l’affichage Vue en arbre <-> Vue en liste +F4 - Démarrer un système Windows ou Linux local +F5 - Utilitaires +F6 - Charger le menu GRUB 2 personnalisé +F7 - Basculer entre le mode graphique <-> mode texte + +m/Ctrl+m - Somme de contrôle des images (md5/sha1/sha256/sha512) +d/Ctrl+d - Mode Memdisk (pour WinPE/LiveCD ISO/IMG uniquement) +w/Ctrl+w - Mode WIMBOOT (pour images Windows/WinPE uniquement) +r/Ctrl+r - Mode GRUB 2 (pour quelques distributions Linux uniquement) +i/Ctrl+i - Mode Compatible (pour débug uniquement) +u/Ctrl+u - Charger l’ISO d’un pilote EFI (pour débug uniquement) + + + +Appuyer sur Echap pour sortir… diff --git a/src/grub2/grub/help/hi_HI.txt b/src/grub2/grub/help/hi_HI.txt new file mode 100644 index 0000000..fb1ed99 --- /dev/null +++ b/src/grub2/grub/help/hi_HI.txt @@ -0,0 +1,19 @@ + L - भाषा का चयन +F1 - इस सहायता जानकारी को प्रदर्शित करें +F2 - स्थानीय डिस्क में फ़ाइलें ब्राउज़ करें और बूट करें +F3 - TreeView <-> ListView के बीच मेन्यू मोड स्विच करें +F4 - स्थानीय डिस्क में Windows/Linux बूट करें +F5 - यूटिलिटीज +F6 - कस्टम Grub2 मेनू लोड करें +F7 - GUI मोड <-> Text मोड के बीच स्विच करें + +m/Ctrl+m - चेकसम इमेज फाइल्स (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk मोड (केवल small WinPE/LiveCD ISO/IMG के लिए) +w/Ctrl+w - WIMBOOT मोड (केवल Windows/WinPE ISO के लिए) +r/Ctrl+r - Grub2 मोड (केवल कुछ Linux distros के लिए) +i/Ctrl+i - Compatible मोड (केवल डिबग के लिए) +u/Ctrl+u - ISO efi ड्राइवर लोड करें (केवल debug के लिए, आधिकारिक तौर पर इस्तेमाल नहीं किया जा सकता) + + + +वापस जाने के लिए ESC दबाएं ...... diff --git a/src/grub2/grub/help/hr_HR.txt b/src/grub2/grub/help/hr_HR.txt new file mode 100644 index 0000000..cb2c60d --- /dev/null +++ b/src/grub2/grub/help/hr_HR.txt @@ -0,0 +1,19 @@ + L - Izaberite jezik +F1 - Prikazuje ove informacije +F2 - Pokreće imidž fajlove na lokalnom disku +F3 - Mijenja meni između TreeView <-> ListView +F4 - Pokreće Windows/Linux na lokalnom disku +F5 - Alati +F6 - Učitava prilagođen GRUB2 meni +F7 - Mijenja između GUI <-> TEXT načina rada + +m/Ctrl+m - Generira heš odabranog imidž fajla (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk način rada (samo za male WinPE/LiveCD imidž fajlove) +w/Ctrl+w - WIMBOOT način rada (samo za Windows/WinPE imidž fajlove) +r/Ctrl+r - GRUB2 način rada (samo za neke Linux distribucije) +i/Ctrl+i - Kompatibilni način rada (samo za testiranje) +u/Ctrl+u - Učitava EFI drajver za imidž fajlove (samo za testiranje) + + + +Pritisnite ESC za povratak ...... diff --git a/src/grub2/grub/help/hu_HU.txt b/src/grub2/grub/help/hu_HU.txt new file mode 100644 index 0000000..a57e406 --- /dev/null +++ b/src/grub2/grub/help/hu_HU.txt @@ -0,0 +1,19 @@ + L - Nyelv kiválasztása +F1 - Súgóinformációk megjelenítése +F2 - Helyi lemezen lévő fájlok tallózása és indítása +F3 - Menü mód váltása fanézet <-> listanézet között +F4 - Windows/Linux indítása a helyi lemezről +F5 - Segédprogramok +F6 - Egyéni Grub2 menü betöltése +F7 - Váltás grafikus mód <-> szöveges mód között + +m/Ctrl+m - Lemezképfájlok ellenőrzőösszege (md5/sha1/sha256/sha512) +d/Ctrl+d - Memórialemez mód (csak kis WinPE/LiveCD ISO/IMG esetén) +w/Ctrl+w - WIMBOOT mód (csak Windows/WinPE ISO esetén) +r/Ctrl+r - Grub2 mód (csak néhány Linux disztribúció esetén) +i/Ctrl+i - Kompatibilis mód (csak hibakereséshez) +u/Ctrl+u - ISO EFI illesztőprogram betöltés (csak hibakereséshez, hivatalosan nem használható) + + + +Nyomja meg az ESC billentyűt a visszalépéshez ...... \ No newline at end of file diff --git a/src/grub2/grub/help/id_ID.txt b/src/grub2/grub/help/id_ID.txt new file mode 100644 index 0000000..2d96f24 --- /dev/null +++ b/src/grub2/grub/help/id_ID.txt @@ -0,0 +1,19 @@ + L - Pilih Bahasa +F1 - Tampilkan bantuan informasi ini +F2 - Jelajah dan jalankan boot berkas pada disk lokal +F3 - Beralih mode menu antara Treeview <-> ListView +F4 - Jalankan boot ke Windows/Linux pada disk lokal +F5 - Alat Utilitas +F6 - Memuat ubah suai Grub2 Menu +F7 - Beralih antara mode GUI <-> Mode TEXT + +m/Ctrl+m - Periksa berkas files (md5/sha1/sha256/sha512) +d/Ctrl+d - Mode Memdisk (Hanya untuk ukuran WinPE/LiveCD ISO/IMG yang kecil) +w/Ctrl+w - Mode WIMBOOT (Hanya untuk berkas ISO Windows/WinPE) +r/Ctrl+r - Mode Grub2 (Hanya untuk distro Linux tertentu) +i/Ctrl+i - Mode Kompatibel/Compatible (Hanya untuk debug saja) +u/Ctrl+u - Memuat ISO efi driver (Hanya untuk debug saja, tidak dapat dipakai secara umum) + + + +Tekan ESC untuk kembali ...... diff --git a/src/grub2/grub/help/it_IT.txt b/src/grub2/grub/help/it_IT.txt new file mode 100644 index 0000000..1b14118 --- /dev/null +++ b/src/grub2/grub/help/it_IT.txt @@ -0,0 +1,19 @@ + L - Selezione lingua interfaccia +F1 - Visualizza informazioni Aiuto (questa guida) +F2 - Sfoglia e avvia file nel disco locale +F3 - Cambia modalità menu tra VistaStruttura <-> VistaElenco +F4 - Avvia Windows/Linux dal disco locale +F5 - Utilità +F6 - Carica il menu Grub2 personalizzato +F7 - Cambia modalità GUI <-> modalità TESTO + +m/Ctrl+m - Checksum file immagine (md5/sha1/sha256/sha512) +d/Ctrl+d - Modalità Memdisk (solo per i file ISO/IMG WinPE/LiveCD piccoli) +w/Ctrl+w - Modalità WIMBOOT (solo per i file ISO Windows/WinPE) +r/Ctrl+r - Modalità Grub2 (solo per alcune distro Linux) +i/Ctrl+i - Modalità Compatibile (solo per debugging) +u/Ctrl+u - Carica driver EFI ISO (solo per debugging, non usato ufficialmente) + + + +Premi 'ESC' per continuare... diff --git a/src/grub2/grub/help/ja_JP.txt b/src/grub2/grub/help/ja_JP.txt new file mode 100644 index 0000000..edfa5c5 --- /dev/null +++ b/src/grub2/grub/help/ja_JP.txt @@ -0,0 +1,19 @@ + L - 言語を選択 +F1 - この画面を表示する +F2 - 手元の記憶装置にある起動ファイルを選択して実行する +F3 - 表示形式を切り替える(一覧 ↔ 階層) +F4 - 手元の記憶装置にあるWindowsまたはLinuxを起動する +F5 - 諸機能 +F6 - Grub2の構成を読み込む +F7 - 操作形式を切り替える(GUI ↔ CUI) + +m/Ctrl+m - イメージの検査合計を計算する (md5/sha1/sha256/sha512) +d/Ctrl+d - 主記憶装置上に記憶域を作成する(容量の小さなWinPE・LiveCD専用) +w/Ctrl+w - WIMBOOTモード(Windows/WinPE ISO専用) +r/Ctrl+r - Grub2モード(一部のLinuxディストリビューション専用) +i/Ctrl+i - 互換モード(開発用) +u/Ctrl+u - ISO efiドライバーを読み取る(開発用,非公式) + + + +この画面を閉じるにはESCを押してください ...... diff --git a/src/grub2/grub/help/ka_GE.txt b/src/grub2/grub/help/ka_GE.txt new file mode 100644 index 0000000..6fc55dc --- /dev/null +++ b/src/grub2/grub/help/ka_GE.txt @@ -0,0 +1,19 @@ + L - ინტერფეისის ენის არჩევა +F1 - დამხმარე ინფორმაციის ჩვენება +F2 - ლოკალური დისკის ფაილების დათვალიერება და ჩატვირთვა +F3 - ჩვენების რეჟიმებს შორის გადართვა 'ხის ხედი' <-> 'სიის ხედი' +F4 - ლოკალური დისკიდან Windows/Linux-ის ჩატვირთვა +F5 - ხელსაწყოები +F6 - მომხმარებლის მიერ შექმნილი Grub2 მენიუს ჩატვირთვა +F7 - ჩვენების რეჟიმის გადართვა 'გრაფიკული' <-> 'ტექსტური' + +m/Ctrl+m - ფაილის საკონტროლო ჯამის შემოწმება (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk რეჟიმი (განკუთვნილია მხოლოდ პატარა ზომის WinPE/LiveCD ISO/IMG დისტრიბუტივებისთვის) +w/Ctrl+w - WIMBOOT რეჟიმი (განკუთვნილია მხოლოდ სტანდარტული Windows/WinPE ISO დისტრიბუტივებისთვის) +r/Ctrl+r - Grub2 რეჟიმი (განკუთვნილია მხოლოდ ზოგიერთი Linux დისტრიბუტივებისთვის) +i/Ctrl+i - თავსებადი რეჟიმი (განკუთვნილია მხოლოდ გამართვისთვის) +u/Ctrl+u - ISO EFI დრაივერის ჩატვირთვა (განკუთვნილია მხოლოდ გამართვისთვის, დაუშვებელია ოფიციალური გამოყენება) + + + +დააჭირეთ ESC დაბრუნებისთვის ...... diff --git a/src/grub2/grub/help/ko_KR.txt b/src/grub2/grub/help/ko_KR.txt new file mode 100644 index 0000000..d221eed --- /dev/null +++ b/src/grub2/grub/help/ko_KR.txt @@ -0,0 +1,19 @@ + L - 언어 선택 +F1 - 이 도움말 정보 표시 +F2 - 로컬 디스크에서 파일 찾아보기 및 부팅 +F3 - 트리보기 <-> 목록보기 간에 메뉴 모드 전환 +F4 - 로컬 디스크에서 Windows/Linux 부팅 +F5 - 유틸리티 +F6 - 사용자 지정 Grub2 메뉴 불러오기 +F7 - 그래픽 모드 <-> 텍스트 모드 간에 전환 + +m/Ctrl+m - 이미지 파일 체크섬 (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk 모드 (작은 WinPE/LiveCD ISO/IMG에만 해당) +w/Ctrl+w - WIMBOOT 모드 (표준 Windows/WinPE ISO에만 해당) +r/Ctrl+r - Grub2 모드 (일반 Linux 배포판에만 해당) +i/Ctrl+i - 호환 모드 (디버그 전용, 공식적으로 사용할 수 없음) +u/Ctrl+u - ISO EFI 드라이버 불러오기 (디버그 전용, 공식적으로 사용할 수 없음) + + + +돌아가려면 ESC를 누르십시오 ...... diff --git a/src/grub2/grub/help/lg_UG.txt b/src/grub2/grub/help/lg_UG.txt new file mode 100644 index 0000000..8cee84e --- /dev/null +++ b/src/grub2/grub/help/lg_UG.txt @@ -0,0 +1,19 @@ +L - Londako Olulimi +F1 - Laga obuyambi +F2 - Nnoonya era kozesa Fayiro eziri ku Disk +F3 - Kyusa endabika ya Menu wakati wa Masaasana (Treeview) ne y'olukalala (ListView) +F4 - Ttandika Windows/Linux ku disk erimu +F5 - Ebikozesebwa ebirala +F6 - Kozesa Grub2 menu gyewerobozza +F7 - Okukyuusa okuva mu Bifaananyi (GUI Mode) <-> Bigambo (TEXT Mode) + +m/Ctrl+m - Okukebera Checksum image files (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk Mode (Ya WinPE/LiveCD ISO/IMG entono zokka) +w/Ctrl+w - WIMBOOT Mode (Ya Windows/WinPE ISO zokka) +r/Ctrl+r - Grub2 Mode (Ya nkola za Linux ezimu) +i/Ctrl+i - Compatible Mode (Ya kutereeza kwokka (debugging)) +u/Ctrl+u - Kozesa ISO EFI driver (Ya kutereeza kwokka (debugging), tesobola kukozesebwa mu butongole) + + + +nyiga ESC to okudda emabega ...... diff --git a/src/grub2/grub/help/pl_PL.txt b/src/grub2/grub/help/pl_PL.txt new file mode 100644 index 0000000..590dad1 --- /dev/null +++ b/src/grub2/grub/help/pl_PL.txt @@ -0,0 +1,19 @@ +L - Wybierz język +F1 — Wyświetl informacje pomocy +F2 — przeglądanie i uruchamianie plików na dysku lokalnym +F3 — Przełącz tryb menu pomiędzy Treeview <-> ListView +F4 — Uruchom system Windows/Linux na dysku lokalnym +F5 — Narzędzia +F6 — Załaduj niestandardowe menu Grub2 +F7 - Przełączanie między trybem GUI <-> trybem TEKST + +m/Ctrl+m — Pliki obrazów z sumą kontrolną (md5/sha1/sha256/sha512) +d/Ctrl+d — Tryb Memdisk (tylko dla małych WinPE/LiveCD ISO/IMG) +w/Ctrl+w — tryb WIMBOOT (tylko dla standardowego systemu Windows/WinPE ISO) +r/Ctrl+r — tryb Grub2 (tylko dla niektórych dystrybucji Linuksa) +i/Ctrl+i — tryb zgodności (tylko do debugowania) +u/Ctrl+u — Załaduj sterownik ISO EFI (tylko do debugowania, nie można go oficjalnie używać) + + + +Naciśnij ESC, aby wrócić... \ No newline at end of file diff --git a/src/grub2/grub/help/pt_BR.txt b/src/grub2/grub/help/pt_BR.txt new file mode 100644 index 0000000..b6d29c5 --- /dev/null +++ b/src/grub2/grub/help/pt_BR.txt @@ -0,0 +1,19 @@ + L - Seleção de Idiomas +F1 - Exibir informações de ajuda +F2 - Explorar e inicializar os arquivos no disco local +F3 - Trocar o modo do menu entre Visualização em Árvore <-> Visualização em Lista +F4 - Inicializar o Windows/Linux no disco local +F5 - Utilitários +F6 - Carregar o Menu Personalizado do Grub2 +F7 - Trocar entre o Modo GUI <-> Modo TEXTO + +m/Ctrl+m - Checksum dos arquivos de imagem (md5/sha1/sha256/sha512) +d/Ctrl+d - Modo Memdisk (Só pros pequenos WinPE/LiveCD ISO/IMG) +w/Ctrl+w - Modo WIMBOOT (Só pra arquivos ISO do Windows/WinPE) +r/Ctrl+r - Modo Grub2 (Só pra algumas distros do Linux) +i/Ctrl+i - Modo Compatível (Só pra debugging) +u/Ctrl+u - Carregar o driver EFI da ISO (Só pra debugging, não pode ser usado oficialmente) + + + +Pressione ESC pra retornar... diff --git a/src/grub2/grub/help/pt_PT.txt b/src/grub2/grub/help/pt_PT.txt new file mode 100644 index 0000000..efc5fd0 --- /dev/null +++ b/src/grub2/grub/help/pt_PT.txt @@ -0,0 +1,18 @@ + L - Selecionar idioma +F1 - Mostra esta informação de ajuda +F2 - Navegar e arrancar ficheiros em disco local +F3 - Alternar o modo menu entre Vista de árvore <-> Vista de lista +F4 - Arrancar o Windows/Linux em disco local +F5 - Utilitários +F6 - Carregar menu Grub2 personalizado +F7 - Alternar entre Modo GUI <-> Modo TEXTO + +m/Ctrl+m - Checksum ficheiros de imagem (md5/sha1/sha256/sha512) +d/Ctrl+d - Modo Memdisk (Apenas para pequenos WinPE/LiveCD ISO/IMG) +w/Ctrl+w - Modo WIMBOOT (Apenas para Windows/WinPE ISO padrão) +r/Ctrl+r - Modo Grub2 (Apenas para algumas distros Linux) +i/Ctrl+i - Modo Compatível (Apenas para depuração) +u/Ctrl+u - Carregar o controlador ISO efi (Apenas para depuração, não pode ser utilizado oficialmente) + + +Prima ESC para voltar ...... diff --git a/src/grub2/grub/help/ru_RU.txt b/src/grub2/grub/help/ru_RU.txt new file mode 100644 index 0000000..03d49f1 --- /dev/null +++ b/src/grub2/grub/help/ru_RU.txt @@ -0,0 +1,19 @@ +L - Выбор языка +F1 - Показать эти справочные сведения +F2 - Просмотр и загрузка файлов на локальном диске +F3 - Переключить режим меню между «Вид древом» <-> «Вид списком» +F4 - Загрузка Windows/Linux с локального диска +F5 - Утилиты +F6 - Загрузить пользовательское меню Grub2 +F7 - Переключиться между графическим режимом <-> текстовым режимом + +m/Ctrl+m - Проверить контрольную сумму файлов образа диска (md5/sha1/sha256/sha512) +d/Ctrl+d - Режим Memdisk (только для небольших WinPE/LiveCD ISO/IMG) +w/Ctrl+w - Режим WIMBOOT (только для Windows/WinPE ISO) +r/Ctrl+r - Режим Grub2 (только для некоторых дистрибутивов Linux) +i/Ctrl+i - Совместимый режим (только для отладки) +u/Ctrl+u - Загрузить драйвер ISO EFI (только для отладки, нельзя использовать официально) + + + +Нажмите «ESC», чтобы вернуться ...... diff --git a/src/grub2/grub/help/sl_SI.txt b/src/grub2/grub/help/sl_SI.txt new file mode 100644 index 0000000..cd1b49e --- /dev/null +++ b/src/grub2/grub/help/sl_SI.txt @@ -0,0 +1,19 @@ + L - Izbira jezika +F1 - Prikaz informacij o pomoči +F2 - Brskanje in zagon datotek na lokalnem disku +F3 - Preklop med načinom menija Treeview <-> ListView +F4 - Zagon Windows/Linux na lokalnem disku +F5 - Pripomočki +F6 - Naložitev prilagojenega menija Grub2 +F7 - Preklop med načinom GUI <-> načinom TEXT + +m/Ctrl+m - Preveri kontrolno vsoto slikovnih datotek (md5/sha1/sha256/sha512) +d/Ctrl+d - Način Memdisk (samo za majhne WinPE/LiveCD ISO/IMG) +w/Ctrl+w - Način WIMBOOT (samo za datoteke Windows/WinPE ISO) +r/Ctrl+r – Način Grub2 (samo za nekatere distribucije Linux) +i/Ctrl+i – Združljiv način (samo za odpravljanje napak) +u/Ctrl+u – Naloži ISO EFI gonilnik (samo za odpravljanje napak, uradno se ne more uporabljati) + + + +Pritisnite ESC za vrnitev ...... diff --git a/src/grub2/grub/help/sr_RS.txt b/src/grub2/grub/help/sr_RS.txt new file mode 100644 index 0000000..f00ee59 --- /dev/null +++ b/src/grub2/grub/help/sr_RS.txt @@ -0,0 +1,19 @@ + L - Изаберите језик +F1 - Приказује ове информације +F2 - Покреће имиџ фајлове на локалном диску +F3 - Мења мени између TreeView <-> ListView +F4 - Покреће Windows/Linux на локалном диску +F5 - Алати +F6 - Учитава прилагођен GRUB2 мени +F7 - Мења између GUI <-> TEXT начина рада + +m/Ctrl+m - Генерира хеш одабраног имиџ фајла (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk начин рада (само за мале WinPE/LiveCD имиџ фајлове) +w/Ctrl+w - WIMBOOT начин рада (само за стандардне Windows/WinPE имиџ фајлове) +r/Ctrl+r - GRUB2 начин рада (само за неке Linux дистрибуције) +i/Ctrl+i - Компатибилни начин рада (само за тестирање) +u/Ctrl+u - Учитава EFI драјвер за имиџ фајлове (само за тестирање) + + + +Притисните ESC за повратак ...... diff --git a/src/grub2/grub/help/ta_IN.txt b/src/grub2/grub/help/ta_IN.txt new file mode 100644 index 0000000..3404a35 --- /dev/null +++ b/src/grub2/grub/help/ta_IN.txt @@ -0,0 +1,19 @@ + L - மொழி தேர்வு +F1 - இந்த உதவித் தகவலைக் காட்டு +F2 - உள்ளூர் வட்டில் கோப்புகளை உலாவவும் துவக்கவும் +F3 - Treeview (மரப்பார்வை) <-> ListView (பட்டியல்பார்வை) இடையே மெனு பயன்முறையை மாற்றவும் +F4 - விண்டோஸ்/லினக்ஸை உள்ளூர் வட்டில் துவக்கவும் +F5 - பயன்பாடுகள் +F6 - தனிப்பயன் Grub2 மெனுவை ஏற்றவும் +F7 - GUI பயன்முறை <-> TEXT பயன்முறைக்கு இடையில் மாறவும் + +m/Ctrl+m - செக்சம் படக் கோப்புகள் (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk பயன்முறை (சிறிய WinPE/LiveCD ISO/IMGக்கு மட்டும்) +w/Ctrl+w - WIMBOOT பயன்முறை (நிலையான Windows/WinPE ISO க்கு மட்டும்) +r/Ctrl+r - Grub2 பயன்முறை (சில லினக்ஸ் டிஸ்ட்ரோக்களுக்கு மட்டும்) +i/Ctrl+i - இணக்கமான பயன்முறை (பிழைத்திருத்தத்திற்கு மட்டும்) +u/Ctrl+u - ISO efi இயக்கியை ஏற்றவும் (பிழைத்திருத்தத்திற்கு மட்டும், அதிகாரப்பூர்வமாக பயன்படுத்த முடியாது) + + + +திரும்புவதற்கு ESC ஐ அழுத்தவும் ...... diff --git a/src/grub2/grub/help/tr_TR.txt b/src/grub2/grub/help/tr_TR.txt new file mode 100644 index 0000000..1ebe1e8 --- /dev/null +++ b/src/grub2/grub/help/tr_TR.txt @@ -0,0 +1,19 @@ + L - Dil Seçimi +F1 - Yardım bilgilerini göster +F2 - Yerel diskteki önyükleme dosyalarına göz at ve önyükleme yap +F3 - Menü modunu Ağaç Görünümü <-> Liste Görünümü arasında değiştir +F4 - Windows & Linux'u yerel diskten önyükle +F5 - Hiperiso araçlar menüsü +F6 - Özelleştirilmiş Grub2 menüsünü yükle +F7 - Grafik(GUI) <--> Metin(Text) modları arasında geçiş yap + +m/Ctrl+m - Görüntü dosyalarının sağlama toplamını al (md5/sha1/sha256/sha512) +d/Ctrl+d - Memdisk Modunu başlat(Yalnızca küçük WinPE/LiveCD ISO/IMG'ler için) +w/Ctrl+w - WIMBOOT Modunu başlat(Yalnızca normal Windows/WinPE ISO'ları için) +r/Ctrl+r - Grub2 Modunu başlat (Yalnızca bazı Linux dağıtımları için) +i/Ctrl+i - Uyumluluk Modu (Yalnızca hata ayıklama için) +u/Ctrl+u - ISO EFI sürücüsünü yükle (Sadece hata ayıklama için, resmi olarak kullanılamaz) + + + +Geri dönmek için ESC tuşuna basınız ...... diff --git a/src/grub2/grub/help/uk_UA.txt b/src/grub2/grub/help/uk_UA.txt new file mode 100644 index 0000000..44acc2e --- /dev/null +++ b/src/grub2/grub/help/uk_UA.txt @@ -0,0 +1,19 @@ +L - Обрати мову +F1 - Показати довідку +F2 - Переглянути та завантажити файли з локального диску +F3 - Переключитись між видами деревом <-> списком +F4 - Завантажити Windows/Linux з локального диску +F5 - Інструменти +F6 - Завантажити Custom Grub2 меню +F7 - Переключитись між графічним інтерфейсом <-> текстовим інтерфейсом + +m/Ctrl + m - Контрольна сума образу диску (md5/sha1/sha256/sha512) +d/Ctrl + d - Режим Memdisk (Тільки для невеликих образів WinPE/LiveCD ISO/IMG) +w/Ctrl + w - Режим WIMBOOT (Тільки для ISO-файлів Windows/WinPE) +r/Ctrl + r - Режим Grub2 (Тільки для деяких дистрибутивів Linux) +i/Ctrl + i - Сумісний режим (Тільки для зневадження) +u/Ctrl + u - Завантажити драйвер ISO EFI (Тільки для зневадження, не офіційно) + + + +Натисність ESC для того, щоб повернутися ...... diff --git a/src/grub2/grub/help/vi_VN.txt b/src/grub2/grub/help/vi_VN.txt new file mode 100644 index 0000000..304d5cc --- /dev/null +++ b/src/grub2/grub/help/vi_VN.txt @@ -0,0 +1,19 @@ + L - Lựa chọn ngôn ngữ +F1 - Hiển thị thông tin trợ giúp +F2 - Duyệt tìm và khởi động tệp từ ổ đĩa trên máy +F3 - Chuyển đổi chế độ bảng chọn giữa dạng cây <-> dạng danh sách. +F4 - Khởi động Windows hoặc GNU/Linux trên đĩa cục bộ +F5 - Các tiện ích +F6 - Tải menu GRUB2 tuỳ chọn +F7 - Chuyển giữa giao diện đồ hoạ <-> giao diện văn bản + +m/Ctrl+m - Checksum các tệp ảnh đĩa (md5/sha1/sha256/sha512) +d/Ctrl+d - Chế độ Memdisk (Chỉ dùng cho các tệp ISO/IMG WinPE/LiveCD có kích thước nhỏ) +w/Ctrl+w - Chế độ WIMBOOT (Chỉ dùng cho các tệp ISO Windows/WinPE) +r/Ctrl+r - Chế độ Grub2 (Chỉ dùng cho một vài bản phân phối của GNU/Linux) +i/Ctrl+i - Chế độ tương thích (Chỉ dùng cho việc sửa lỗi) +u/Ctrl+u - Tải ISO của một driver EFI (Chỉ dùng cho việc sửa lỗi, không thể dùng chính thức) + + + +Nhấn ESC để quay lại ...... diff --git a/src/grub2/grub/help/zh_CN.txt b/src/grub2/grub/help/zh_CN.txt new file mode 100644 index 0000000..932a4f2 --- /dev/null +++ b/src/grub2/grub/help/zh_CN.txt @@ -0,0 +1,18 @@ + L - 选择语言 +F1 - 显示本帮助信息 +F2 - 浏览并启动本地硬盘中的镜像文件 +F3 - 菜单显示模式切换。可在列表模式和目录模式之间自由切换。 +F4 - 启动本地硬盘上的 Windows/Linux 等系统。 +F5 - 各类工具 +F6 - 加载自定义 GRUB2 菜单。 +F7 - 界面在文本模式和图形模式之间切换。 + +m/Ctrl+m - 计算文件校验值(md5/sha1/sha256/sha512) +d/Ctrl+d - MEMDISK 模式,把文件加载到内存启动(只适用于文件很小的 WinPE/LiveCD等) +w/Ctrl+w - WIMBOOT 模式 (只适用于 Windows/WinPE 的ISO文件) +r/Ctrl+r - Grub2 模式 (只适用于常见的一些 Linux 系统ISO文件) +i/Ctrl+i - 兼容模式 (只用作调试目的,不能正式使用) +u/Ctrl+u - 加载 ISO efi 驱动(只用作调试目的,不能正式使用) + + +按 ESC 键返回 ...... diff --git a/src/grub2/grub/help/zh_TW.txt b/src/grub2/grub/help/zh_TW.txt new file mode 100644 index 0000000..bbe4dd2 --- /dev/null +++ b/src/grub2/grub/help/zh_TW.txt @@ -0,0 +1,18 @@ +L - 選擇語言 +F1 - 顯示本説明資訊 +F2 - 瀏覽並啟動本地硬碟中的映像檔 +F3 - 功能表顯示模式切換。可在清單模式和目錄模式之間自由切換。 +F4 - 啟動本地硬碟上的 Windows/Linux 等系統。 +F5 - 各類工具 +F6 - 載入自訂 GRUB2 選單。 +F7 - 介面在文字模式和圖形模式之間切換。 + +m/Ctrl+m - 計算檔案校驗值(md5/sha1/sha256/sha512) +d/Ctrl+d - MEMDISK 模式,把檔載入到記憶體啟動(只適用於檔很小的 WinPE/LiveCD等) +w/Ctrl+w - WIMBOOT 模式 (只適用於 Windows/WinPE ISO檔) +r/Ctrl+r - Grub2 模式 (只適用於常見的一些 Linux 系統ISO檔) +i/Ctrl+i - 相容模式 (只用作調試目的,不能正式使用) +u/Ctrl+u - 載入 ISO efi 驅動(只用作調試目的,不能正式使用) + + +按 ESC 鍵返回 ...... diff --git a/src/grub2/grub/hwinfo.cfg b/src/grub2/grub/hwinfo.cfg new file mode 100644 index 0000000..4bb3057 --- /dev/null +++ b/src/grub2/grub/hwinfo.cfg @@ -0,0 +1,64 @@ +menuentry "$VTLANG_HWINFO" --class=debug_hwinfo --class=F5tool { + smbios -t 4 -s 0x10 --set=cpu_brand + + set system_vendor="-"; + smbios -t 1 -s 0x04 --set=system_vendor; + set system_product="-"; + smbios -t 1 -s 0x05 --set=system_product; + set system_version="-"; + smbios -t 1 -s 0x06 --set=system_version; + + set board_vendor="-"; + smbios -t 2 -s 0x04 --set=board_vendor; + set board_product="-"; + smbios -t 2 -s 0x05 --set=board_product; + set board_version="-"; + smbios -t 2 -s 0x06 --set=board_version; + + set bios_vendor="-"; + smbios -t 0 -s 0x04 --set=bios_vendor; + set bios_version="-"; + smbios -t 0 -s 0x05 --set=bios_ver; + set bios_date="-"; + smbios -t 0 -s 0x08 --set=bios_date; + set bios_size="-"; + smbios -t 0 -b 0x09 --set=bios_size; + + + echo "Platform $grub_cpu-$grub_platform" + if [ "$grub_platform" != "pc" ]; then + echo "UEFI Version $grub_uefi_version" + echo "PI Version $grub_pi_version" + if vt_check_secureboot_var; then + echo "Secure Boot Enabled" + else + echo "Secure Boot Disabled" + fi + + vt_sbinfo + fi + + echo "" + echo "CPU Model $cpu_brand" + echo "Physical RAM $grub_total_ram MB" + + echo "" + echo "Manufacturer $system_vendor" + echo "Product Name $system_product" + echo "Version $system_version" + + echo "" + echo "Board Manufacturer $board_vendor" + echo "Board Name $board_product" + echo "Board Version $board_version" + + echo "" + echo "BIOS Manufacturer $bios_vendor" + echo "BIOS Version $bios_ver" + echo "BIOS Date $bios_date" + echo "BIOS ROM Size $bios_size" + + + echo -en "\n\n\n$VTLANG_ENTER_EXIT ..." + read vtInputKey +} diff --git a/src/grub2/grub/i386-efi/command.lst b/src/grub2/grub/i386-efi/command.lst new file mode 100644 index 0000000..896bb3d --- /dev/null +++ b/src/grub2/grub/i386-efi/command.lst @@ -0,0 +1,206 @@ +*acpi: acpi +*all_functional_test: functional_test +*background_image: gfxterm_background +*bls_import: blscfg +*blscfg: blscfg +*cat: cat +*cpuid: cpuid +*crc: hashsum +*cryptomount: cryptodisk +*echo: echo +*extract_syslinux_entries_configfile: syslinuxcfg +*extract_syslinux_entries_source: syslinuxcfg +*file: file +*functional_test: functional_test +*fwconnect: fwload +*fwload: fwload +*gettext: gettext +*hashsum: hashsum +*hdparm: hdparm +*hello: hello +*help: help +*hexdump: hexdump +*inb: iorw +*inl: iorw +*inw: iorw +*keystatus: keystatus +*kfreebsd: bsd +*knetbsd: bsd +*kopenbsd: bsd +*list_env: loadenv +*load_env: loadenv +*loopback: loopback +*ls: ls +*lsacpi: lsacpi +*lspci: lspci +*md5sum: hashsum +*menuentry: normal +*pcidump: pcidump +*probe: probe +*rdmsr: rdmsr +*read_byte: memrw +*read_dword: memrw +*read_word: memrw +*regexp: regexp +*save_env: loadenv +*search: search +*serial: serial +*set_keyboard_layout: setkey +*setkey: setkey +*setpci: setpci +*sha1sum: hashsum +*sha256sum: hashsum +*sha512sum: hashsum +*sleep: sleep +*smbios: smbios +*submenu: normal +*syslinux_configfile: syslinuxcfg +*syslinux_source: syslinuxcfg +*terminfo: terminfo +*test_blockarg: test_blockarg +*testspeed: testspeed +*tr: tr +*trust: pgp +*verify_detached: pgp +*xnu_splash: xnu +*zfskey: zfscrypt +.: configfile +[: test +appleloader: appleldr +authenticate: normal +background_color: gfxterm_background +backtrace: backtrace +badram: mmap +blocklist: blocklist +boot: boot +break: normal +cat: minicmd +cbmemc: cbmemc +chainloader: chain +clear: normal +cmp: cmp +configfile: configfile +continue: normal +coreboot_boottime: cbtime +cutmem: mmap +date: date +distrust: pgp +dump: minicmd +eval: eval +exit: minicmd +export: normal +extract_entries_configfile: configfile +extract_entries_source: configfile +extract_legacy_entries_configfile: legacycfg +extract_legacy_entries_source: legacycfg +fakebios: loadbios +false: true +fix_video: fixvideo +fwsetup: efifwsetup +gdbstub: gdb +gdbstub_break: gdb +gdbstub_stop: gdb +gptsync: gptsync +halt: halt +help: minicmd +hexdump_random: random +initrd16: linux16 +initrd: linux +initrdefi: linux +keymap: keylayouts +kfreebsd_loadenv: bsd +kfreebsd_module: bsd +kfreebsd_module_elf: bsd +knetbsd_module: bsd +knetbsd_module_elf: bsd +kopenbsd_ramdisk: bsd +legacy_check_password: legacycfg +legacy_configfile: legacycfg +legacy_initrd: legacycfg +legacy_initrd_nounzip: legacycfg +legacy_kernel: legacycfg +legacy_password: legacycfg +legacy_source: legacycfg +linux16: linux16 +linux: linux +linuxefi: linux +list_trusted: pgp +loadbios: loadbios +loadfont: font +lscoreboot: cbls +lsefi: lsefi +lsefimmap: lsefimmap +lsefisystab: lsefisystab +lsfonts: font +lsmmap: lsmmap +lsmod: minicmd +lssal: lssal +macppcbless: macbless +mactelbless: macbless +module2: multiboot2 +module: multiboot +multiboot2: multiboot2 +multiboot: multiboot +nativedisk: nativedisk +net_add_addr: net +net_add_dns: net +net_add_route: net +net_bootp: net +net_del_addr: net +net_del_dns: net +net_del_route: net +net_dhcp: net +net_get_dhcp_option: net +net_ipv6_autoconf: net +net_ls_addr: net +net_ls_cards: net +net_ls_dns: net +net_ls_routes: net +net_nslookup: net +normal: normal +normal_exit: normal +outb: iorw +outl: iorw +outw: iorw +parttool: parttool +password: password +password_pbkdf2: password_pbkdf2 +play: play +read: read +reboot: reboot +return: normal +rmmod: minicmd +search.file: search_fs_file +search.fs_label: search_label +search.fs_uuid: search_fs_uuid +setparams: normal +shift: normal +source: configfile +terminal_input: terminal +terminal_output: terminal +test: test +testload: testload +time: time +true: true +usb: usbtest +videoinfo: videoinfo +videotest: videotest +vt_img_extra_initrd_append: linux +vt_img_extra_initrd_reset: linux +vt_set_boot_opt: linux +vt_unset_boot_opt: linux +write_byte: memrw +write_dword: memrw +write_word: memrw +wrmsr: wrmsr +xnu_devprop_load: xnu +xnu_kernel64: xnu +xnu_kernel: xnu +xnu_kext: xnu +xnu_kextdir: xnu +xnu_mkext: xnu +xnu_ramdisk: xnu +xnu_resume: xnu +xnu_uuid: xnu_uuid +zfs-bootfs: zfsinfo +zfsinfo: zfsinfo diff --git a/src/grub2/grub/i386-efi/crypto.lst b/src/grub2/grub/i386-efi/crypto.lst new file mode 100644 index 0000000..77d9efc --- /dev/null +++ b/src/grub2/grub/i386-efi/crypto.lst @@ -0,0 +1,45 @@ +RIJNDAEL: gcry_rijndael +RIJNDAEL192: gcry_rijndael +RIJNDAEL256: gcry_rijndael +AES128: gcry_rijndael +AES-128: gcry_rijndael +AES-192: gcry_rijndael +AES-256: gcry_rijndael +ADLER32: adler32 +CRC64: crc64 +ARCFOUR: gcry_arcfour +BLOWFISH: gcry_blowfish +CAMELLIA128: gcry_camellia +CAMELLIA192: gcry_camellia +CAMELLIA256: gcry_camellia +CAST5: gcry_cast5 +CRC32: gcry_crc +CRC32RFC1510: gcry_crc +CRC24RFC2440: gcry_crc +DES: gcry_des +3DES: gcry_des +DSA: gcry_dsa +IDEA: gcry_idea +MD4: gcry_md4 +MD5: gcry_md5 +RFC2268_40: gcry_rfc2268 +AES: gcry_rijndael +AES192: gcry_rijndael +AES256: gcry_rijndael +RIPEMD160: gcry_rmd160 +RSA: gcry_rsa +SEED: gcry_seed +SERPENT128: gcry_serpent +SERPENT192: gcry_serpent +SERPENT256: gcry_serpent +SHA1: gcry_sha1 +SHA224: gcry_sha256 +SHA256: gcry_sha256 +SHA512: gcry_sha512 +SHA384: gcry_sha512 +TIGER192: gcry_tiger +TIGER: gcry_tiger +TIGER2: gcry_tiger +TWOFISH: gcry_twofish +TWOFISH128: gcry_twofish +WHIRLPOOL: gcry_whirlpool diff --git a/src/grub2/grub/i386-efi/fdt.lst b/src/grub2/grub/i386-efi/fdt.lst new file mode 100644 index 0000000..e69de29 diff --git a/src/grub2/grub/i386-efi/fs.lst b/src/grub2/grub/i386-efi/fs.lst new file mode 100644 index 0000000..0acd240 --- /dev/null +++ b/src/grub2/grub/i386-efi/fs.lst @@ -0,0 +1,37 @@ +affs +afs +bfs +btrfs +cbfs +cpio +cpio_be +exfat +ext2 +f2fs +fat +hfs +hfsplus +iso9660 +jfs +minix +minix2 +minix2_be +minix3 +minix3_be +minix_be +newc +nilfs2 +ntfs +odc +procfs +reiserfs +romfs +sfs +squash4 +tar +udf +ufs1 +ufs1_be +ufs2 +xfs +zfs diff --git a/src/grub2/grub/i386-efi/moddep.lst b/src/grub2/grub/i386-efi/moddep.lst new file mode 100644 index 0000000..b025ad7 --- /dev/null +++ b/src/grub2/grub/i386-efi/moddep.lst @@ -0,0 +1,269 @@ +videotest: font video gfxmenu +odc: archelp +loopback: extcmd +setkey: extcmd +macho: +gcry_des: crypto +memrw: extcmd +terminfo: extcmd +f2fs: fshelp +part_gpt: +romfs: fshelp +read: +lsefimmap: +aout: +gcry_arcfour: crypto +tftp: net priority_queue +newc: archelp +minix2_be: +elf: +videotest_checksum: font functional_test video_fb +password_pbkdf2: crypto gcry_sha512 pbkdf2 normal +gcry_seed: crypto +pcidump: extcmd +bsd: elf serial crypto gcry_md5 verifiers extcmd aout video boot cpuid relocator mmap +sfs: fshelp +reiserfs: fshelp +part_sunpc: +zstd: +gfxmenu: video_colors trig bitmap_scale gfxterm font normal video bitmap +backtrace: +jfs: +help: extcmd normal +configfile: normal +cbls: cbtable +gfxterm_menu: font functional_test procfs normal video_fb +gcry_idea: crypto +tr: extcmd +shift_test: functional_test +ohci: cs5536 usb boot +afs: fshelp +spkmodem: terminfo +usb_keyboard: keylayouts usb +xzio: crypto +syslinuxcfg: extcmd normal +search_fs_file: +wrmsr: +usbms: scsi usb +test_blockarg: extcmd normal +true: +affs: fshelp +iso9660: fshelp +smbios: extcmd +exfat: fshelp +setjmp_test: setjmp functional_test +gfxterm: font video +efinet: net +disk: +appleldr: boot +xfs: fshelp +testspeed: extcmd normal +cpio_be: archelp +functional_test: btrfs extcmd video video_fb +bswap_test: functional_test +sleep: extcmd normal +memdisk: +gcry_rijndael: crypto +mdraid09_be: diskfilter +gettext: +gcry_sha1: crypto +hfspluscomp: gzio hfsplus +cmp: +random: hexdump +offsetio: +file: elf macho extcmd offsetio +usbserial_usbdebug: serial usb usbserial_common +video_colors: +morse: +hashsum: crypto extcmd normal +usb: +halt: acpi +gdb: serial backtrace +gfxterm_background: video_colors bitmap_scale gfxterm extcmd video bitmap +search_fs_uuid: +gcry_dsa: pgp mpi +keystatus: extcmd +linux: ventoy verifiers video boot relocator mmap +geli: cryptodisk crypto gcry_sha512 pbkdf2 gcry_sha256 +cmdline_cat_test: font functional_test normal procfs video_fb +rdmsr: extcmd +part_sun: +cbtable: +pbkdf2_test: functional_test pbkdf2 gcry_sha1 +video_bochs: video video_fb +verifiers: +bufio: +usbserial_ftdi: serial usb usbserial_common +legacy_password_test: functional_test legacycfg +cpuid: extcmd +blscfg: extcmd normal +hdparm: extcmd hexdump +bfs: fshelp +gcry_blowfish: crypto +test: +nilfs2: fshelp +gcry_rsa: pgp mpi +cryptodisk: crypto extcmd procfs +nativedisk: +minicmd: +signature_test: functional_test procfs +ata: scsi +udf: fshelp +gzio: gcry_crc +xnu_uuid: gcry_md5 +uhci: usb +pata: ata +mul_test: functional_test +adler32: crypto +terminal: +div: +ehci: cs5536 usb boot +crypto: +part_bsd: part_msdos +cs5536: +ventoy: ext2 fshelp elf btrfs crypto font gcry_md5 exfat udf datetime div extcmd normal video gcry_sha1 mmap iso9660 +gcry_sha512: crypto +password: crypto normal +fshelp: +sleep_test: functional_test datetime +iorw: extcmd +xnu: macho bitmap_scale random verifiers extcmd boot video bitmap relocator mmap +mmap: +exfctest: functional_test +zfsinfo: zfs +ldm: part_gpt diskfilter part_msdos +eval: normal +part_dvh: +lssal: +blocklist: +ext2: fshelp +net: priority_queue bufio datetime boot +part_acorn: +videoinfo: video +btrfs: zstd lzopio raid6rec gzio +lsmmap: mmap +strtoull_test: functional_test +bitmap: +ntfs: fshelp +multiboot: net linux video boot relocator mmap +gcry_crc: crypto +png: bufio bitmap +jpeg: bufio bitmap +macbless: disk +div_test: functional_test div +regexp: extcmd normal +parttool: normal +usbserial_pl2303: serial usb usbserial_common +cpio: archelp +gcry_rmd160: crypto +fat: fshelp +ufs1_be: +archelp: +http: net +zfs: gzio +raid6rec: diskfilter +lsefisystab: +minix2: +lsacpi: extcmd acpi +datehook: datetime normal +loadenv: disk extcmd +bitmap_scale: bitmap +probe: extcmd +minix3: +tar: archelp +loadbios: +hfs: fshelp +procfs: archelp +boot: +keylayouts: +progress: normal +kernel: +usbtest: usb +relocator: mmap +acpi: extcmd mmap +tga: bufio bitmap +fwload: extcmd +reboot: +serial: extcmd terminfo +zfscrypt: crypto pbkdf2 extcmd zfs gcry_sha1 gcry_rijndael +efi_uga: video video_fb +dm_nv: diskfilter +cmp_test: functional_test +luks: cryptodisk crypto pbkdf2 +font: bufio video +raid5rec: diskfilter +crc64: crypto +datetime: +efifwsetup: +ctz_test: functional_test +video: +cbmemc: cbtable normal terminfo +hfsplus: fshelp +gcry_cast5: crypto +extcmd: +squash4: fshelp zstd lzopio zfs xzio gzio +part_plan: +minix_be: +gcry_whirlpool: crypto +gcry_tiger: crypto +fixvideo: +search: search_fs_uuid search_fs_file extcmd search_label +lspci: extcmd +cbtime: cbtable +video_fb: +minix3_be: +trig: +msdospart: disk parttool +priority_queue: +gcry_twofish: crypto +part_dfly: +xnu_uuid_test: functional_test +diskfilter: +testload: +part_apple: +hexdump: extcmd +date: datetime normal +pbkdf2: crypto +gcry_sha256: crypto +ls: extcmd normal +usbserial_common: serial usb +ntfscomp: ntfs +mouse: +lzopio: crypto +video_cirrus: video video_fb +hello: extcmd +scsi: +linux16: linux boot video relocator mmap +cat: extcmd +ahci: ata boot +pgp: crypto verifiers extcmd mpi gcry_sha1 +normal: terminal crypto verifiers bufio extcmd boot gettext +ufs1: +mdraid09: diskfilter +lvm: diskfilter +chain: net efinet boot +cbfs: archelp +ufs2: +time: +setpci: extcmd +gptsync: disk +search_label: +setjmp: +multiboot2: linux net video boot relocator mmap acpi +gcry_rfc2268: crypto +mdraid1x: diskfilter +mpi: crypto +legacycfg: crypto password gcry_md5 normal +play: +part_amiga: +efi_gop: video video_fb +minix: +echo: extcmd +lsefi: +gcry_serpent: crypto +gcry_md4: crypto +gcry_md5: crypto +part_msdos: +gcry_camellia: crypto +at_keyboard: keylayouts boot +all_video: efi_gop efi_uga video_bochs video_cirrus diff --git a/src/grub2/grub/i386-efi/partmap.lst b/src/grub2/grub/i386-efi/partmap.lst new file mode 100644 index 0000000..761233a --- /dev/null +++ b/src/grub2/grub/i386-efi/partmap.lst @@ -0,0 +1,11 @@ +part_acorn +part_amiga +part_apple +part_bsd +part_dfly +part_dvh +part_gpt +part_msdos +part_plan +part_sun +part_sunpc diff --git a/src/grub2/grub/i386-efi/parttool.lst b/src/grub2/grub/i386-efi/parttool.lst new file mode 100644 index 0000000..68b4b5c --- /dev/null +++ b/src/grub2/grub/i386-efi/parttool.lst @@ -0,0 +1 @@ +msdos: msdospart diff --git a/src/grub2/grub/i386-efi/terminal.lst b/src/grub2/grub/i386-efi/terminal.lst new file mode 100644 index 0000000..9afb9bd --- /dev/null +++ b/src/grub2/grub/i386-efi/terminal.lst @@ -0,0 +1,10 @@ +iat_keyboard: at_keyboard +imouse: mouse +iserial: serial +iserial_*: serial +oaudio: morse +ocbmemc: cbmemc +ogfxterm: gfxterm +oserial: serial +oserial_*: serial +ospkmodem: spkmodem diff --git a/src/grub2/grub/i386-efi/video.lst b/src/grub2/grub/i386-efi/video.lst new file mode 100644 index 0000000..ae9ba23 --- /dev/null +++ b/src/grub2/grub/i386-efi/video.lst @@ -0,0 +1,4 @@ +efi_gop +efi_uga +video_bochs +video_cirrus diff --git a/src/grub2/grub/i386-pc/command.lst b/src/grub2/grub/i386-pc/command.lst new file mode 100644 index 0000000..a21a2f9 --- /dev/null +++ b/src/grub2/grub/i386-pc/command.lst @@ -0,0 +1,212 @@ +*acpi: acpi +*all_functional_test: functional_test +*background_image: gfxterm_background +*bls_import: blscfg +*blscfg: blscfg +*cat: cat +*cpuid: cpuid +*crc: hashsum +*cryptomount: cryptodisk +*drivemap: drivemap +*echo: echo +*extract_syslinux_entries_configfile: syslinuxcfg +*extract_syslinux_entries_source: syslinuxcfg +*file: file +*functional_test: functional_test +*gettext: gettext +*halt: halt +*hashsum: hashsum +*hdparm: hdparm +*hello: hello +*help: help +*hexdump: hexdump +*inb: iorw +*inl: iorw +*inw: iorw +*keystatus: keystatus +*kfreebsd: bsd +*knetbsd: bsd +*kopenbsd: bsd +*list_env: loadenv +*load_env: loadenv +*loopback: loopback +*ls: ls +*lsacpi: lsacpi +*lspci: lspci +*md5sum: hashsum +*menuentry: normal +*pcidump: pcidump +*plan9: plan9 +*probe: probe +*rdmsr: rdmsr +*read_byte: memrw +*read_dword: memrw +*read_word: memrw +*regexp: regexp +*save_env: loadenv +*search: search +*sendkey: sendkey +*serial: serial +*set_keyboard_layout: setkey +*setkey: setkey +*setpci: setpci +*sha1sum: hashsum +*sha256sum: hashsum +*sha512sum: hashsum +*sleep: sleep +*smbios: smbios +*submenu: normal +*syslinux_configfile: syslinuxcfg +*syslinux_source: syslinuxcfg +*terminfo: terminfo +*test_blockarg: test_blockarg +*testspeed: testspeed +*tr: tr +*trust: pgp +*verify_detached: pgp +*xnu_splash: xnu +*zfskey: zfscrypt +.: configfile +[: test +authenticate: normal +background_color: gfxterm_background +backtrace: backtrace +badram: mmap +blocklist: blocklist +boot: boot +break: normal +cat: minicmd +cbmemc: cbmemc +chainloader: chain +clear: normal +cmosclean: cmostest +cmosdump: cmosdump +cmosset: cmostest +cmostest: cmostest +cmp: cmp +configfile: configfile +continue: normal +coreboot_boottime: cbtime +cutmem: mmap +date: date +distrust: pgp +dump: minicmd +efiemu_loadcore: efiemu +efiemu_prepare: efiemu +efiemu_unload: efiemu +eval: eval +exit: minicmd +export: normal +extract_entries_configfile: configfile +extract_entries_source: configfile +extract_legacy_entries_configfile: legacycfg +extract_legacy_entries_source: legacycfg +false: true +freedos: freedos +gdbstub: gdb +gdbstub_break: gdb +gdbstub_stop: gdb +gptsync: gptsync +help: minicmd +hexdump_random: random +initrd16: linux16 +initrd: linux +initrdefi: linux +keymap: keylayouts +kfreebsd_loadenv: bsd +kfreebsd_module: bsd +kfreebsd_module_elf: bsd +knetbsd_module: bsd +knetbsd_module_elf: bsd +kopenbsd_ramdisk: bsd +legacy_check_password: legacycfg +legacy_configfile: legacycfg +legacy_initrd: legacycfg +legacy_initrd_nounzip: legacycfg +legacy_kernel: legacycfg +legacy_password: legacycfg +legacy_source: legacycfg +linux16: linux16 +linux: linux +linuxefi: linux +list_trusted: pgp +loadfont: font +lsapm: lsapm +lscoreboot: cbls +lsfonts: font +lsmmap: lsmmap +lsmod: minicmd +macppcbless: macbless +mactelbless: macbless +module2: multiboot2 +module: multiboot +multiboot2: multiboot2 +multiboot: multiboot +nativedisk: nativedisk +net_add_addr: net +net_add_dns: net +net_add_route: net +net_bootp: net +net_del_addr: net +net_del_dns: net +net_del_route: net +net_dhcp: net +net_get_dhcp_option: net +net_ipv6_autoconf: net +net_ls_addr: net +net_ls_cards: net +net_ls_dns: net +net_ls_routes: net +net_nslookup: net +normal: normal +normal_exit: normal +ntldr: ntldr +outb: iorw +outl: iorw +outw: iorw +parttool: parttool +password: password +password_pbkdf2: password_pbkdf2 +play: play +pxechainloader: pxechain +read: read +reboot: reboot +return: normal +rmmod: minicmd +search.file: search_fs_file +search.fs_label: search_label +search.fs_uuid: search_fs_uuid +setparams: normal +shift: normal +source: configfile +terminal_input: terminal +terminal_output: terminal +test: test +testload: testload +time: time +true: true +truecrypt: truecrypt +usb: usbtest +vbeinfo: videoinfo +vbetest: videotest +videoinfo: videoinfo +videotest: videotest +vt_img_extra_initrd_append: linux +vt_img_extra_initrd_reset: linux +vt_set_boot_opt: linux +vt_unset_boot_opt: linux +write_byte: memrw +write_dword: memrw +write_word: memrw +wrmsr: wrmsr +xnu_devprop_load: xnu +xnu_kernel64: xnu +xnu_kernel: xnu +xnu_kext: xnu +xnu_kextdir: xnu +xnu_mkext: xnu +xnu_ramdisk: xnu +xnu_resume: xnu +xnu_uuid: xnu_uuid +zfs-bootfs: zfsinfo +zfsinfo: zfsinfo diff --git a/src/grub2/grub/i386-pc/crypto.lst b/src/grub2/grub/i386-pc/crypto.lst new file mode 100644 index 0000000..77d9efc --- /dev/null +++ b/src/grub2/grub/i386-pc/crypto.lst @@ -0,0 +1,45 @@ +RIJNDAEL: gcry_rijndael +RIJNDAEL192: gcry_rijndael +RIJNDAEL256: gcry_rijndael +AES128: gcry_rijndael +AES-128: gcry_rijndael +AES-192: gcry_rijndael +AES-256: gcry_rijndael +ADLER32: adler32 +CRC64: crc64 +ARCFOUR: gcry_arcfour +BLOWFISH: gcry_blowfish +CAMELLIA128: gcry_camellia +CAMELLIA192: gcry_camellia +CAMELLIA256: gcry_camellia +CAST5: gcry_cast5 +CRC32: gcry_crc +CRC32RFC1510: gcry_crc +CRC24RFC2440: gcry_crc +DES: gcry_des +3DES: gcry_des +DSA: gcry_dsa +IDEA: gcry_idea +MD4: gcry_md4 +MD5: gcry_md5 +RFC2268_40: gcry_rfc2268 +AES: gcry_rijndael +AES192: gcry_rijndael +AES256: gcry_rijndael +RIPEMD160: gcry_rmd160 +RSA: gcry_rsa +SEED: gcry_seed +SERPENT128: gcry_serpent +SERPENT192: gcry_serpent +SERPENT256: gcry_serpent +SHA1: gcry_sha1 +SHA224: gcry_sha256 +SHA256: gcry_sha256 +SHA512: gcry_sha512 +SHA384: gcry_sha512 +TIGER192: gcry_tiger +TIGER: gcry_tiger +TIGER2: gcry_tiger +TWOFISH: gcry_twofish +TWOFISH128: gcry_twofish +WHIRLPOOL: gcry_whirlpool diff --git a/src/grub2/grub/i386-pc/fdt.lst b/src/grub2/grub/i386-pc/fdt.lst new file mode 100644 index 0000000..e69de29 diff --git a/src/grub2/grub/i386-pc/fs.lst b/src/grub2/grub/i386-pc/fs.lst new file mode 100644 index 0000000..0acd240 --- /dev/null +++ b/src/grub2/grub/i386-pc/fs.lst @@ -0,0 +1,37 @@ +affs +afs +bfs +btrfs +cbfs +cpio +cpio_be +exfat +ext2 +f2fs +fat +hfs +hfsplus +iso9660 +jfs +minix +minix2 +minix2_be +minix3 +minix3_be +minix_be +newc +nilfs2 +ntfs +odc +procfs +reiserfs +romfs +sfs +squash4 +tar +udf +ufs1 +ufs1_be +ufs2 +xfs +zfs diff --git a/src/grub2/grub/i386-pc/moddep.lst b/src/grub2/grub/i386-pc/moddep.lst new file mode 100644 index 0000000..de15670 --- /dev/null +++ b/src/grub2/grub/i386-pc/moddep.lst @@ -0,0 +1,274 @@ +videotest: font video gfxmenu +odc: archelp +loopback: extcmd +setkey: extcmd +macho: +gcry_des: crypto +memrw: extcmd +terminfo: extcmd +f2fs: fshelp +part_gpt: +romfs: fshelp +read: +aout: +gcry_arcfour: crypto +vga_text: +tftp: net priority_queue +newc: archelp +minix2_be: +elf: +videotest_checksum: font functional_test video_fb +password_pbkdf2: crypto gcry_sha512 pbkdf2 normal +gcry_seed: crypto +pcidump: extcmd pci +bsd: elf serial crypto gcry_md5 verifiers extcmd vbe aout video boot cpuid relocator mmap +sfs: fshelp +reiserfs: fshelp +part_sunpc: +zstd: +gfxmenu: video_colors trig bitmap_scale gfxterm font normal video bitmap +backtrace: +jfs: +help: extcmd normal +configfile: normal +cbls: cbtable +gfxterm_menu: font functional_test procfs normal video_fb +gcry_idea: crypto +tr: extcmd +shift_test: functional_test +ohci: cs5536 usb boot pci +afs: fshelp +spkmodem: terminfo +usb_keyboard: keylayouts usb +xzio: crypto +syslinuxcfg: extcmd normal +search_fs_file: +wrmsr: +vga: video video_fb +usbms: scsi usb +test_blockarg: extcmd normal +true: +affs: fshelp +iso9660: fshelp +smbios: extcmd acpi +exfat: fshelp +setjmp_test: setjmp functional_test +gfxterm: font video +disk: +xfs: fshelp +testspeed: extcmd normal +cpio_be: archelp +functional_test: btrfs extcmd video video_fb +pxechain: pxe video boot relocator +bswap_test: functional_test +sleep: extcmd normal +memdisk: +gcry_rijndael: crypto +mdraid09_be: diskfilter +gettext: +gcry_sha1: crypto +hfspluscomp: gzio hfsplus +cmp: +random: hexdump acpi +offsetio: +file: elf macho extcmd offsetio +usbserial_usbdebug: serial usb usbserial_common +video_colors: +morse: +hashsum: crypto extcmd normal +usb: pci +halt: extcmd acpi +gdb: serial backtrace +gfxterm_background: video_colors bitmap_scale gfxterm extcmd video bitmap +search_fs_uuid: +gcry_dsa: pgp mpi +keystatus: extcmd +linux: ventoy verifiers vbe normal video boot relocator mmap +geli: cryptodisk crypto gcry_sha512 pbkdf2 gcry_sha256 +cmdline_cat_test: font functional_test normal procfs video_fb +rdmsr: extcmd +part_sun: +cbtable: +plan9: verifiers extcmd boot video relocator +sendkey: extcmd boot +pbkdf2_test: functional_test pbkdf2 gcry_sha1 +video_bochs: pci video video_fb +verifiers: +bufio: +usbserial_ftdi: serial usb usbserial_common +legacy_password_test: functional_test legacycfg +cpuid: extcmd +blscfg: extcmd normal +hdparm: extcmd hexdump +bfs: fshelp +gcry_blowfish: crypto +test: +nilfs2: fshelp +gcry_rsa: pgp mpi +cryptodisk: crypto extcmd procfs +nativedisk: +minicmd: +signature_test: functional_test procfs +ata: scsi +udf: fshelp +gzio: gcry_crc +xnu_uuid: gcry_md5 +uhci: usb pci +pata: ata pci +mul_test: functional_test +adler32: crypto +terminal: +div: +ehci: cs5536 usb boot pci +crypto: +part_bsd: part_msdos +cs5536: pci +biosdisk: +ventoy: ext2 fshelp elf btrfs crypto font gcry_md5 exfat udf div extcmd datetime normal video gcry_sha1 iso9660 reboot acpi +lsapm: +gcry_sha512: crypto +password: crypto normal +efiemu: gcry_crc crypto cpuid acpi +fshelp: +sleep_test: functional_test datetime +iorw: extcmd +xnu: macho bitmap_scale random verifiers extcmd video bitmap boot relocator efiemu mmap +mmap: boot +exfctest: functional_test +zfsinfo: zfs +ldm: part_gpt diskfilter part_msdos +cmostest: +eval: normal +part_dvh: +blocklist: +ext2: fshelp +net: priority_queue bufio datetime boot +drivemap: extcmd boot mmap +part_acorn: +videoinfo: video +btrfs: zstd lzopio raid6rec gzio +lsmmap: +strtoull_test: functional_test +bitmap: +vbe: video video_fb +ntfs: fshelp +multiboot: net linux vbe video boot relocator mmap lsapm +gcry_crc: crypto +png: bufio bitmap +jpeg: bufio bitmap +macbless: disk +div_test: functional_test div +regexp: extcmd normal +parttool: normal +usbserial_pl2303: serial usb usbserial_common +cpio: archelp +gcry_rmd160: crypto +fat: fshelp +ufs1_be: +truecrypt: video boot relocator gzio mmap +archelp: +ntldr: chain boot video relocator +http: net +zfs: gzio +raid6rec: diskfilter +minix2: +mda_text: +lsacpi: extcmd acpi +datehook: datetime normal +loadenv: disk extcmd +bitmap_scale: bitmap +probe: extcmd +minix3: +tar: archelp +hfs: fshelp +procfs: archelp +boot: +keylayouts: +progress: normal +kernel: +usbtest: usb +relocator: mmap +acpi: extcmd mmap +tga: bufio bitmap +reboot: relocator +serial: extcmd terminfo +zfscrypt: crypto pbkdf2 extcmd zfs gcry_sha1 gcry_rijndael +dm_nv: diskfilter +cmp_test: functional_test +luks: cryptodisk crypto pbkdf2 +font: bufio video +raid5rec: diskfilter +crc64: crypto +datetime: +ctz_test: functional_test +video: +pci: +cbmemc: cbtable normal terminfo +cmosdump: +hfsplus: fshelp +gcry_cast5: crypto +extcmd: +squash4: fshelp zstd lzopio zfs xzio gzio +part_plan: +minix_be: +gcry_whirlpool: crypto +pxe: net boot +gcry_tiger: crypto +search: search_fs_uuid search_fs_file extcmd search_label +lspci: extcmd pci +cbtime: cbtable +video_fb: +minix3_be: +trig: +msdospart: disk parttool +priority_queue: +gcry_twofish: crypto +part_dfly: +xnu_uuid_test: functional_test +diskfilter: +testload: +part_apple: +hexdump: extcmd +date: datetime normal +pbkdf2: crypto +gcry_sha256: crypto +ls: extcmd normal +usbserial_common: serial usb +ntfscomp: ntfs +lzopio: crypto +video_cirrus: pci video video_fb +hello: extcmd +scsi: +linux16: linux boot video relocator mmap +cat: extcmd +ahci: ata boot pci +pgp: crypto verifiers extcmd mpi gcry_sha1 +normal: terminal crypto verifiers bufio extcmd boot gettext +ufs1: +mdraid09: diskfilter +lvm: diskfilter +cbfs: archelp +chain: video boot relocator +ufs2: +time: +setpci: extcmd pci +gptsync: disk +freedos: chain boot video relocator +search_label: +setjmp: +multiboot2: linux net vbe boot video relocator mmap lsapm acpi +gcry_rfc2268: crypto +mdraid1x: diskfilter +mpi: crypto +legacycfg: linux crypto password gcry_md5 normal +play: +part_amiga: +minix: +echo: extcmd +gcry_serpent: crypto +gcry_md4: crypto +gcry_md5: crypto +part_msdos: +gcry_camellia: crypto +at_keyboard: keylayouts boot +all_video: vbe vga video_bochs video_cirrus diff --git a/src/grub2/grub/i386-pc/partmap.lst b/src/grub2/grub/i386-pc/partmap.lst new file mode 100644 index 0000000..761233a --- /dev/null +++ b/src/grub2/grub/i386-pc/partmap.lst @@ -0,0 +1,11 @@ +part_acorn +part_amiga +part_apple +part_bsd +part_dfly +part_dvh +part_gpt +part_msdos +part_plan +part_sun +part_sunpc diff --git a/src/grub2/grub/i386-pc/parttool.lst b/src/grub2/grub/i386-pc/parttool.lst new file mode 100644 index 0000000..68b4b5c --- /dev/null +++ b/src/grub2/grub/i386-pc/parttool.lst @@ -0,0 +1 @@ +msdos: msdospart diff --git a/src/grub2/grub/i386-pc/terminal.lst b/src/grub2/grub/i386-pc/terminal.lst new file mode 100644 index 0000000..2cb224c --- /dev/null +++ b/src/grub2/grub/i386-pc/terminal.lst @@ -0,0 +1,11 @@ +iat_keyboard: at_keyboard +iserial: serial +iserial_*: serial +oaudio: morse +ocbmemc: cbmemc +ogfxterm: gfxterm +omda_text: mda_text +oserial: serial +oserial_*: serial +ospkmodem: spkmodem +ovga_text: vga_text diff --git a/src/grub2/grub/i386-pc/video.lst b/src/grub2/grub/i386-pc/video.lst new file mode 100644 index 0000000..6ca853e --- /dev/null +++ b/src/grub2/grub/i386-pc/video.lst @@ -0,0 +1,4 @@ +vbe +vga +video_bochs +video_cirrus diff --git a/src/grub2/grub/keyboard.cfg b/src/grub2/grub/keyboard.cfg new file mode 100644 index 0000000..41caba9 --- /dev/null +++ b/src/grub2/grub/keyboard.cfg @@ -0,0 +1,62 @@ +submenu "$VTLANG_KEYBRD_LAYOUT" --class=debug_krdlayout --class=F5tool { + menuentry QWERTY_USA --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout QWERTY_USA + } + menuentry AZERTY --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout AZERTY + } + menuentry CZECH_QWERTY --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout CZECH_QWERTY + } + menuentry CZECH_QWERTZ --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout CZECH_QWERTZ + } + menuentry DANISH --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout DANISH + } + menuentry DVORAK_USA --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout DVORAK_USA + } + menuentry FRENCH --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout FRENCH + } + menuentry GERMAN --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout GERMAN + } + menuentry ITALIANO --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout ITALIANO + } + menuentry JAPAN_106 --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout JAPAN_106 + } + menuentry LATIN_USA --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout LATIN_USA + } + menuentry PORTU_BRAZIL --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout PORTU_BRAZIL + } + menuentry QWERTY_UK --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout QWERTY_UK + } + menuentry QWERTZ --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout QWERTZ + } + menuentry QWERTZ_HUN --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout QWERTZ_HUN + } + menuentry QWERTZ_SLOV_CROAT --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout QWERTZ_SLOV_CROAT + } + menuentry SPANISH --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout SPANISH + } + menuentry SWEDISH --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout SWEDISH + } + menuentry TURKISH_Q --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout TURKISH_Q + } + menuentry VIETNAMESE --class=debug_kbd --class=debug_krdlayout --class=F5tool { + set_keyboard_layout VIETNAMESE + } +} diff --git a/src/grub2/grub/localboot.cfg b/src/grub2/grub/localboot.cfg new file mode 100644 index 0000000..c1a2826 --- /dev/null +++ b/src/grub2/grub/localboot.cfg @@ -0,0 +1,222 @@ + +if [ "$grub_platform" = "pc" ]; then + menuentry "$VTLANG_LB_SBOOT_WINDOWS" --class=boot_windows --class=F4boot { + + set partid=3 + while [ $partid -le 128 ]; do + if vt_check_part_exist $partid; then + for bt in bootmgr BOOTMGR Bootmgr BootMGR; do + if [ -f ($hisodev,$partid)/$bt ]; then + set root=($hisodev,$partid) + ntldr /$bt + boot + fi + done + else + break + fi + vt_incr partid 1 + done + + if search -n -s -f /Boot/BCD; then + for bt in bootmgr BOOTMGR Bootmgr BootMGR; do + if [ -f /$bt ]; then + if regexp '^hd0' $root; then + ntldr /$bt + else + drivemap -s hd0 $root + ntldr /$bt + fi + break + fi + done + elif search -n -s -f /NTDETECT.COM; then + drivemap -s hd0 $root + ntldr /ntldr + else + echo "Windows NOT found ..." + fi + } + + menuentry "$VTLANG_LB_SBOOT_G4D" --class=boot_g4d --class=F4boot { + if search -n -s -f /grldr; then + ntldr /grldr + else + echo "Grub4dos NOT found ..." + fi + } + + menuentry "$VTLANG_LB_SBOOT_HDD1" --class=boot_disk --class=F4boot { + set root=(hd0,1) + chainloader +1 + boot + } + + menuentry "$VTLANG_LB_SBOOT_HDD2" --class=boot_disk --class=F4boot { + set root=(hd1,1) + chainloader +1 + boot + } + + menuentry "$VTLANG_LB_SBOOT_HDD3" --class=boot_disk --class=F4boot { + set root=(hd2,1) + chainloader +1 + boot + } + +else + + menuentry "$VTLANG_LB_SBOOT_WINDOWS" --class=boot_windows --class=F4boot { + + set partid=3 + while [ $partid -le 128 ]; do + if vt_check_part_exist $partid; then + if [ -f ($hisodev,$partid)/EFI/Microsoft/Boot/bootmgfw.efi ]; then + set root=($hisodev,$partid) + terminal_output console + chainloader /EFI/Microsoft/Boot/bootmgfw.efi + boot + elif [ -f ($hisodev,$partid)/efi/Microsoft/Boot/bootmgfw.efi ]; then + set root=($hisodev,$partid) + terminal_output console + chainloader /efi/Microsoft/Boot/bootmgfw.efi + boot + elif [ -f ($hisodev,$partid)/VTEFI/Microsoft/Boot/bootmgfw.efi ]; then + set root=($hisodev,$partid) + terminal_output console + chainloader /VTEFI/Microsoft/Boot/bootmgfw.efi + boot + fi + else + break + fi + vt_incr partid 1 + done + + if search -n -s -f /EFI/Microsoft/Boot/bootmgfw.efi; then + terminal_output console + chainloader /EFI/Microsoft/Boot/bootmgfw.efi + boot + elif search -n -s -f /efi/Microsoft/Boot/bootmgfw.efi; then + terminal_output console + chainloader /efi/Microsoft/Boot/bootmgfw.efi + boot + else + echo "Windows NOT found ..." + fi + } + + if [ "$grub_cpu" = "i386" ]; then + menuentry "$VTLANG_LB_SBOOT_IA32EFI" --class=boot_uefi --class=F4boot { + set HISO_SEARCH_NO_HISOEFI=1 + if search -n -s -f /efi/boot/bootia32.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /efi/boot/bootia32.efi + boot + elif search -n -s -f /vtefi/boot/bootia32.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /vtefi/boot/bootia32.efi + boot + else + unset HISO_SEARCH_NO_HISOEFI + echo "BOOTIA32.EFI NOT found ..." + fi + } + + menuentry "$VTLANG_LB_SBOOT_XORBOOT" --class=boot_xorboot --class=F4boot { + set HISO_SEARCH_NO_HISOEFI=1 + if search -n -s -f /efi/xorboot/xorboot32.xor; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + if [ -f /efi/xorboot/bootia32.efi ]; then + chainloader /efi/xorboot/bootia32.efi + elif [ -f /efi/xorboot/xorboot.efi ]; then + chainloader /efi/xorboot/xorboot.efi + fi + boot + elif search -n -s -f /vtefi/xorboot/xorboot32.xor; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + if [ -f /vtefi/xorboot/bootia32.efi ]; then + chainloader /vtefi/xorboot/bootia32.efi + elif [ -f /vtefi/xorboot/xorboot.efi ]; then + chainloader /vtefi/xorboot/xorboot.efi + fi + boot + else + unset HISO_SEARCH_NO_HISOEFI + echo "xorboot NOT found ..." + fi + } + elif [ "$grub_cpu" = "arm64" ]; then + menuentry "$VTLANG_LB_SBOOT_AA64EFI" --class=boot_uefi --class=F4boot { + set HISO_SEARCH_NO_HISOEFI=1 + if search -n -s -f /efi/boot/bootaa64.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /efi/boot/bootaa64.efi + boot + elif search -n -s -f /vtefi/boot/bootaa64.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /vtefi/boot/bootaa64.efi + boot + else + unset HISO_SEARCH_NO_HISOEFI + echo "BOOTAA64.EFI NOT found ..." + fi + } + else + menuentry "$VTLANG_LB_SBOOT_X64EFI" --class=boot_uefi --class=F4boot { + set HISO_SEARCH_NO_HISOEFI=1 + if search -n -s -f /efi/boot/bootx64.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /efi/boot/bootx64.efi + boot + elif search -n -s -f /vtefi/boot/bootx64.efi; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + chainloader /vtefi/boot/bootx64.efi + boot + else + unset HISO_SEARCH_NO_HISOEFI + echo "BOOTX64.EFI NOT found ..." + fi + } + + menuentry "$VTLANG_LB_SBOOT_XORBOOT" --class=boot_xorboot --class=F4boot { + set HISO_SEARCH_NO_HISOEFI=1 + if search -n -s -f /efi/xorboot/xorboot.xor; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + if [ -f /efi/xorboot/bootx64.efi ]; then + chainloader /efi/xorboot/bootx64.efi + elif [ -f /efi/xorboot/xorboot.efi ]; then + chainloader /efi/xorboot/xorboot.efi + fi + boot + elif search -n -s -f /vtefi/xorboot/xorboot.xor; then + unset HISO_SEARCH_NO_HISOEFI + terminal_output console + if [ -f /vtefi/xorboot/bootx64.efi ]; then + chainloader /vtefi/xorboot/bootx64.efi + elif [ -f /vtefi/xorboot/xorboot.efi ]; then + chainloader /vtefi/xorboot/xorboot.efi + fi + boot + else + unset HISO_SEARCH_NO_HISOEFI + echo "xorboot NOT found ..." + fi + } + fi + + +fi + +menuentry "$VTLANG_RETURN_PREVIOUS" --class=hisoret HISO_RET { + echo "Return ..." +} diff --git a/src/grub2/grub/menu/ar_AR.json b/src/grub2/grub/menu/ar_AR.json new file mode 100644 index 0000000..47cffc6 --- /dev/null +++ b/src/grub2/grub/menu/ar_AR.json @@ -0,0 +1,98 @@ +{ + "VTLANG_LANGUAGE_NAME": "Arabic (العربية)", + + "VTLANG_STR_HOTKEY_LIST": "L: لغة F1: مساعدة F2: تصفح F3: عرض لائحي F4: إقلاع محلي F5: أدوات F6: عوده", + "VTLANG_STR_HOTKEY_TREE": "L: لغة F1: مساعدة F2: تصفح F3: عرض شجري F4: إقلاع محلي F5: أدوات F6: عوده", + "VTLANG_RETURN_PREVIOUS": "عودة إلى القائمة السابقة [Esc]", + "VTLANG_RETURN_PRV_NOESC": "عودة إلى القائمة السابقة", + + "VTLANG_MENU_LANG": "اختيار اللغة في القائمة", + + "VTLANG_LB_SBOOT_WINDOWS": "البحث والإقلاع على Windows", + "VTLANG_LB_SBOOT_G4D": "البحث والإقلاع على Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "الإقلاع على القرص المحلي الأول", + "VTLANG_LB_SBOOT_HDD2": "الإقلاع على القرص المحلي الثاني", + "VTLANG_LB_SBOOT_HDD3": "الإقلاع على القرص المحلي الثالث", + "VTLANG_LB_SBOOT_X64EFI": "البحث والإقلاع على BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "البحث والإقلاع على BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "البحث والإقلاع على BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "البحث والإقلاع على xorboot", + + "VTLANG_FILE_CHKSUM": "تدقيق المجموع للملف", + "VTLANG_CHKSUM_MD5_CALC": "احسب md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "احسب sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "احسب sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "احسب sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "احسب وتحقق md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "احسب وتحقق sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "احسب وتحقق sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "احسب وتحقق sha512sum", + + "VTLANG_POWER": "الطاقة", + "VTLANG_POWER_REBOOT": "إعادة التشغيل", + "VTLANG_POWER_HALT": "إيقاف", + "VTLANG_POWER_BOOT_EFIFW": "إعادة التشغيل إلى إعداد EFI", + + "VTLANG_KEYBRD_LAYOUT": "تخطيطات لوحة المفاتيح", + "VTLANG_HWINFO": "معلومات حول العتاد", + + "VTLANG_RESOLUTION_CFG": "تكوين الدقة", + "VTLANG_SCREEN_MODE": "وضع عرض الشاشة", + "VTLANG_SCREEN_TEXT_MODE": "فرض تحديد وضع النص", + "VTLANG_SCREEN_GUI_MODE": "فرض تحديد وضع الرسومات", + + "VTLANG_THEME_SELECT": "اختر السمة", + + "VTLANG_UEFI_UTIL": "أدوات Hiperiso UEFI المساعدة", + "VTLANG_UTIL_SHOW_EFI_DRV": "عرض برامج تشغيل EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "إصلاح فشل تهيئة Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "التحقق من تكوين json للبرنامج الإضافي (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "التحقق من تكوين برنامج الإضافي العام للتحكم", + "VTLANG_JSON_CHK_THEME": "التحقق من تكوين برنامج الإضافي الخاص بالسمة", + "VTLANG_JSON_CHK_AUTOINS": "التحقق من تكوين برنامج الإضافي للتثبيت التلقائي", + "VTLANG_JSON_CHK_PERSIST": "التحقق من تكوين برنامج الإضافي المستمر", + "VTLANG_JSON_CHK_MENU_ALIAS": "التحقق من تكوين برنامج الإضافي الخاص بالقائمة المستعارة", + "VTLANG_JSON_CHK_MENU_TIP": "التحقق من تكوين برنامج الإضافي الخاص بتلميح القائمة", + "VTLANG_JSON_CHK_MENU_CLASS": "التحقق من تكوين برنامج الإضافي الخاص بفئة القائمة", + "VTLANG_JSON_CHK_INJECTION": "التحقق من تكوين برنامج الإضافي الخاص بالتدخل", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "التحقق من تكوين برنامج الإضافي الخاص بالتثبيت التلقائي لـ memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "التحقق من تكوين برنامج الإضافي الخاص بقائمة الصور", + "VTLANG_JSON_CHK_IMG_BLIST": "التحقق من تكوين برنامج الإضافي الخاص بقائمة سوداء للصور", + "VTLANG_JSON_CHK_CONF_REPLACE": "التحقق من تكوين برنامج الإضافي الخاص باستبدال ملف التكوين للإقلاع", + "VTLANG_JSON_CHK_DUD": "التحقق من تكوين برنامج الإضافي الخاص بـ dud", + "VTLANG_JSON_CHK_PASSWORD": "التحقق من تكوين برنامج الإضافي الخاص بكلمة المرور", + + "VTLANG_NORMAL_MODE": "الإقلاع في الوضع العادي", + "VTLANG_WIMBOOT_MODE": "الإقلاع في وضع wimboot", + "VTLANG_GRUB2_MODE": "الإقلاع في وضع grub2", + "VTLANG_MEMDISK_MODE": "الإقلاع في وضع memdisk", + + "VTLANG_RET_TO_LISTVIEW": "العودة إلى ListView", + "VTLANG_RET_TO_TREEVIEW": "العودة إلى TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "الإقلاع بدون قالب التثبيت التلقائي", + "VTLANG_AUTOINS_USE": "الإقلاع مع", + + "VTLANG_NO_PERSIST": "الإقلاع بدون الاستمرارية", + "VTLANG_PERSIST_USE": "الإقلاع مع", + + "VTLANG_BROWER_RETURN": "العودة", + + "VTLANG_ENTER_EXIT": "اضغط على مفتاح Enter للخروج", + "VTLANG_ENTER_REBOOT": "اضغط على مفتاح Enter لإعادة التشغيل", + "VTLANG_ENTER_CONTINUE": "اضغط على مفتاح Enter للمتابعة", + + "VTLANG_CTRL_TEMP_SET": "إعدادات التحكم المؤقتة", + "VTLANG_WIN11_BYPASS_CHECK": "تجاوز فحص CPU/TPM/SecureBoot عند تثبيت Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "تجاوز متطلبات الحساب عبر الإنترنت عند تثبيت Windows 11", + "VTLANG_LINUX_REMOUNT": "ضم قسم Hiperiso بعد إقلاع Linux", + "VTLANG_SECONDARY_BOOT_MENU": "اظهر قائمة الإقلاع الثانوية", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/bn_BN.json b/src/grub2/grub/menu/bn_BN.json new file mode 100644 index 0000000..c3995f1 --- /dev/null +++ b/src/grub2/grub/menu/bn_BN.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Bengali (বাংলা)", + + "VTLANG_STR_HOTKEY_LIST": "L:ভাষা F1:সাহায্য F2:Browser F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:ভাষা F1:সাহায্য F2:Browser F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "পূর্ববর্তী মেনুতে ফিরে যান [Esc]", + "VTLANG_RETURN_PRV_NOESC": "পূর্ববর্তী মেনুতে ফিরে যান", + + "VTLANG_MENU_LANG": "মেনু ভাষা নির্বাচন করুন", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows অনুসন্ধান করুন এবং বুট করুন", + "VTLANG_LB_SBOOT_G4D": "Grub4dos অনুসন্ধান করুন এবং বুট করুন", + "VTLANG_LB_SBOOT_HDD1": "১ম(1st) স্থানীয় ডিস্ক বুট করুন", + "VTLANG_LB_SBOOT_HDD2": "২য়(2nd) স্থানীয় ডিস্ক বুট করুন", + "VTLANG_LB_SBOOT_HDD3": "3য়(3rd) স্থানীয় ডিস্ক বুট করুন", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI অনুসন্ধান করুন এবং বুট করুন", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI অনুসন্ধান করুন এবং বুট করুন", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI অনুসন্ধান করুন এবং বুট করুন", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot অনুসন্ধান করুন এবং বুট করুন", + + "VTLANG_FILE_CHKSUM": "ফাইল চেকসাম", + "VTLANG_CHKSUM_MD5_CALC": "md5sum গণনা করুন", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum গণনা করুন", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum গণনা করুন", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum গণনা করুন", + "VTLANG_CHKSUM_MD5_CALC_CHK": "গণনা করুন এবং md5sum চেক করুন", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "গণনা করুন এবং sha1sum চেক করুন", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "গণনা করুন এবং sha256sum চেক করুন", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "গণনা করুন এবং sha512sum চেক করুন", + + "VTLANG_POWER": "পাওয়ার", + "VTLANG_POWER_REBOOT": "রিবুট", + "VTLANG_POWER_HALT": "হল্ট", + "VTLANG_POWER_BOOT_EFIFW": "EFI সেটআপে রিবুট করুন", + + "VTLANG_KEYBRD_LAYOUT": "কীবোর্ড লেআউট", + "VTLANG_HWINFO": "হার্ডওয়্যার তথ্য", + + "VTLANG_RESOLUTION_CFG": "রেজোলিউশন কনফিগারেশন", + "VTLANG_SCREEN_MODE": "Screen Display মোড", + "VTLANG_SCREEN_TEXT_MODE": "Force Text মোড", + "VTLANG_SCREEN_GUI_MODE": "Force Graphics মোড", + + "VTLANG_THEME_SELECT": "থিম নির্বাচন করুন", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI ইউটিলিটিস", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI ড্রাইভার দেখান", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary ব্যর্থতার সমাধান করুন", + + "VTLANG_JSON_CHK_JSON": "প্লাগইন json কনফিগারেশন পরীক্ষা করুন (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "গ্লোবাল কন্ট্রোল প্লাগইন কনফিগারেশন চেক করুন", + "VTLANG_JSON_CHK_THEME": "থিম প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_AUTOINS": "অটো ইন্সটল প্লাগইন কনফিগারেশন চেক করুন", + "VTLANG_JSON_CHK_PERSIST": "persistence প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_MENU_ALIAS": "menu alias প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_MENU_TIP": "menu tip প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_MENU_CLASS": "menu class প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_INJECTION": "injection প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "auto memdisk প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_IMG_LIST": "image list প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_IMG_BLIST": "image blacklist প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_CONF_REPLACE": "boot conf replace প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_DUD": "dud প্লাগইন কনফিগারেশন পরীক্ষা করুন", + "VTLANG_JSON_CHK_PASSWORD": "password প্লাগইন কনফিগারেশন পরীক্ষা করুন", + + "VTLANG_NORMAL_MODE": "সাধারণ মোডে বুট করুন", + "VTLANG_WIMBOOT_MODE": "wimboot মোডে বুট করুন", + "VTLANG_GRUB2_MODE": "grub2 মোডে বুট করুন", + "VTLANG_MEMDISK_MODE": "memdisk মোডে বুট করুন", + + "VTLANG_RET_TO_LISTVIEW": "ListView-এ ফিরে যান", + "VTLANG_RET_TO_TREEVIEW": "TreeView-এ ফিরে যান", + + "VTLANG_NO_AUTOINS_SCRIPT": "auto install মোড বিনা বুট করুন", + "VTLANG_AUTOINS_USE": "দিয়ে বুট করুন", + + "VTLANG_NO_PERSIST": "persistence বিনা বুট করুন", + "VTLANG_PERSIST_USE": "দিয়ে বুট করুন", + + "VTLANG_BROWER_RETURN": "ফিরে", + + "VTLANG_ENTER_EXIT": "প্রস্থান করার জন্য এন্টার কী টিপুন", + "VTLANG_ENTER_REBOOT": "রিবুট করতে এন্টার কী টিপুন", + "VTLANG_ENTER_CONTINUE": "চালিয়ে যেতে এন্টার কী টিপুন", + + "VTLANG_CTRL_TEMP_SET": "অস্থায়ী নিয়ন্ত্রণ সেটিংস", + "VTLANG_WIN11_BYPASS_CHECK": "Windows 11 ইনস্টল করার সময় CPU/TPM/SecureBoot চেক বাইপাস করুন", + "VTLANG_WIN11_BYPASS_NRO": "Windows 11 ইনস্টল করার সময় অনলাইন অ্যাকাউন্টের প্রয়োজন বাইপাস করুন", + "VTLANG_LINUX_REMOUNT": "লিনাক্স বুটের পরে ভেন্টয় পার্টিশনটি মাউন্ট করুন", + "VTLANG_SECONDARY_BOOT_MENU": "গৌণ বুট মেনু দেখান", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/cs_CZ.json b/src/grub2/grub/menu/cs_CZ.json new file mode 100644 index 0000000..99271a0 --- /dev/null +++ b/src/grub2/grub/menu/cs_CZ.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Czech (Čeština)", + + "VTLANG_STR_HOTKEY_LIST": "L:Jazyk F1:Nápověda F2:Procházet F3:Seznam F4:Místní boot F5:Nástroje F6:Rozšířená nabídka", + "VTLANG_STR_HOTKEY_TREE": "L:Jazyk F1:Nápověda F2:Procházet F3:Strom F4:Místní boot F5:Nástroje F6:Rozšířená nabídka", + "VTLANG_RETURN_PREVIOUS": "Vrátit do předchozí nabídky [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Vrátit do předchozí nabídky", + + "VTLANG_MENU_LANG": "Výběrt jazyka nabídel", + + "VTLANG_LB_SBOOT_WINDOWS": "Najít a spustit Windows", + "VTLANG_LB_SBOOT_G4D": "Najít a spustit Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Spustit 1. místní disk", + "VTLANG_LB_SBOOT_HDD2": "Spustit 2. místní disk", + "VTLANG_LB_SBOOT_HDD3": "Spustit 3. místní disk", + "VTLANG_LB_SBOOT_X64EFI": "Najít a spustit BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Najít a spustit BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Najít a spustit BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Najít a spustit xorboot", + + "VTLANG_FILE_CHKSUM": "Kontrolní součet souboru", + "VTLANG_CHKSUM_MD5_CALC": "Spočítat md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Spočítat sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Spočítat sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Spočítat sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Spočítat a ověřit md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Spočítat a ověřit sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Spočítat a ověřit sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Spočítat a ověřit sha512sum", + + "VTLANG_POWER": "Napájení", + "VTLANG_POWER_REBOOT": "Restartovat", + "VTLANG_POWER_HALT": "Vypnout", + "VTLANG_POWER_BOOT_EFIFW": "Restartovat do EFI nastavení", + + "VTLANG_KEYBRD_LAYOUT": "Rozložení klávesnice", + "VTLANG_HWINFO": "Informace o hardwaru", + + "VTLANG_RESOLUTION_CFG": "Nastavení rolišení", + "VTLANG_SCREEN_MODE": "Nastavení režimu zobrazení", + "VTLANG_SCREEN_TEXT_MODE": "Vynutit textový režim", + "VTLANG_SCREEN_GUI_MODE": "Vynutit grafický režim", + + "VTLANG_THEME_SELECT": "Výběr motivu", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI nástroje", + "VTLANG_UTIL_SHOW_EFI_DRV": "Zobrazit EFI ovladače", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Opravit chybu Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "Zkontrolovat json konfiguraci zásuvných modulů (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Zkontrolovat konfiguraci hlavního zásuvného modulu", + "VTLANG_JSON_CHK_THEME": "Zkontrolovat konfiguraci zásuvného modulu motivů", + "VTLANG_JSON_CHK_AUTOINS": "Zkontrolovat konfiguraci zásuvného modulu automatické instalace", + "VTLANG_JSON_CHK_PERSIST": "Zkontrolovat konfiguraci zásuvného modulu perzistence", + "VTLANG_JSON_CHK_MENU_ALIAS": "Zkontrolovat konfiguraci zásuvného modulu aliasů", + "VTLANG_JSON_CHK_MENU_TIP": "Zkontrolovat konfiguraci zásuvného modulu tip", + "VTLANG_JSON_CHK_MENU_CLASS": "Zkontrolovat konfiguraci zásuvného modulu tříd", + "VTLANG_JSON_CHK_INJECTION": "Zkontrolovat konfiguraci zásuvného modulu injekcí", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Zkontrolovat konfiguraci zásuvného modulu automatického memdisku", + "VTLANG_JSON_CHK_IMG_LIST": "Zkontrolovat konfiguraci zásuvného modulu seznamu obrazů", + "VTLANG_JSON_CHK_IMG_BLIST": "Zkontrolovat konfiguraci zásuvného modulu černé listiny obrazů", + "VTLANG_JSON_CHK_CONF_REPLACE": "Zkontrolovat konfiguraci zásuvného modulu nahrazení konfigurace spouštění", + "VTLANG_JSON_CHK_DUD": "Zkontrolovat konfiguraci zásuvného modulu dud", + "VTLANG_JSON_CHK_PASSWORD": "Zkontrolovat konfiguraci zásuvného modulu hesla", + + "VTLANG_NORMAL_MODE": "Spustit normálně", + "VTLANG_WIMBOOT_MODE": "Spustit v režimu wimboot", + "VTLANG_GRUB2_MODE": "Spustit v režimu grub2", + "VTLANG_MEMDISK_MODE": "Spustit v režimu memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Vrátis do zobrazení seznamu", + "VTLANG_RET_TO_TREEVIEW": "Vrátit do zobrazení stromu", + + "VTLANG_NO_AUTOINS_SCRIPT": "Spustit bez šablony automatické instalace", + "VTLANG_AUTOINS_USE": "Spustit s", + + "VTLANG_NO_PERSIST": "Spustit bez perzistence", + "VTLANG_PERSIST_USE": "Spustit s", + + "VTLANG_BROWER_RETURN": "Vrátit", + + "VTLANG_ENTER_EXIT": "zmáčkněte Enter pro ukončení", + "VTLANG_ENTER_REBOOT": "zmáčkněte Enter pro restart", + "VTLANG_ENTER_CONTINUE": "zmáčkněte enter pro pokračování", + + "VTLANG_CTRL_TEMP_SET": "Dočasné řídící nastavení", + "VTLANG_WIN11_BYPASS_CHECK": "Obejít CPU/TPM/SecureBoot kontrolu při instalaci Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Obejít požadování online účtu při instalaci Windows 11", + "VTLANG_LINUX_REMOUNT": "Připojit Hiperiso oddíl po spuštění Linuxu", + "VTLANG_SECONDARY_BOOT_MENU": "Zobrazit druhou spouštěcí nabídku", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/de_DE.json b/src/grub2/grub/menu/de_DE.json new file mode 100644 index 0000000..f2837d6 --- /dev/null +++ b/src/grub2/grub/menu/de_DE.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "German (Deutsch)", + + "VTLANG_STR_HOTKEY_LIST": "L:Sprache F1:Hilfe F2:Browser F3:Listenansicht F4:Lokaler Start F5:Werkzeuge F6:Erweitert", + "VTLANG_STR_HOTKEY_TREE": "L:Sprache F1:Hilfe F2:Browser F3:Listenansicht F4:Lokaler Start F5:Werkzeuge F6:Erweitert", + "VTLANG_RETURN_PREVIOUS": "Zu vorherigem Menü [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Zu vorherigem Menü", + + "VTLANG_MENU_LANG": "Menüsprache auswählen", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows suchen und starten", + "VTLANG_LB_SBOOT_G4D": "Grub4dos suchen und starten", + "VTLANG_LB_SBOOT_HDD1": "Vom ersten lokalen Datenträger starten", + "VTLANG_LB_SBOOT_HDD2": "Vom zweiten lokalen Datenträger starten", + "VTLANG_LB_SBOOT_HDD3": "Vom dritten lokalen Datenträger starten", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI suchen und starten", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI suchen und starten", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI suchen und starten", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot suchen und starten", + + "VTLANG_FILE_CHKSUM": "Dateiprüfsumme", + "VTLANG_CHKSUM_MD5_CALC": "md5sum berechnen", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum berechnen", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum berechnen", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum berechnen", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum berechnen und prüfen", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum berechnen und prüfen", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum berechnen und prüfen", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum berechnen und prüfen", + + "VTLANG_POWER": "Power", + "VTLANG_POWER_REBOOT": "Neustart", + "VTLANG_POWER_HALT": "Herunterfahren", + "VTLANG_POWER_BOOT_EFIFW": "Neustart in EFI-Konfiguration", + + "VTLANG_KEYBRD_LAYOUT": "Tastaturlayout", + "VTLANG_HWINFO": "Hardwareinformationen", + + "VTLANG_RESOLUTION_CFG": "Auflösungseinstellungen", + "VTLANG_SCREEN_MODE": "Bildschirmanzeigemodus", + "VTLANG_SCREEN_TEXT_MODE": "Textmodus erzwingen", + "VTLANG_SCREEN_GUI_MODE": "Grafikmodus erzwingen", + + "VTLANG_THEME_SELECT": "Design auswählen", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI-Dienstprogramme", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI-Treiber anzeigen", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary Fehler beheben", + + "VTLANG_JSON_CHK_JSON": "Konfiguration des JSON-Plugins prüfen (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Konfiguration des Plugins für die allgemeine Kontrolle prüfen", + "VTLANG_JSON_CHK_THEME": "Konfiguration des Design-Plugins prüfen", + "VTLANG_JSON_CHK_AUTOINS": "Konfiguration des Plugins für die automatische Installation prüfen", + "VTLANG_JSON_CHK_PERSIST": "Konfiguration des Persistenz-Plugins prüfen", + "VTLANG_JSON_CHK_MENU_ALIAS": "Konfiguration des Menü-Alias-Plugin prüfen", + "VTLANG_JSON_CHK_MENU_TIP": "Konfiguration des Menütipp-Plugins prüfen", + "VTLANG_JSON_CHK_MENU_CLASS": "Konfiguration des Menüklassen-Plugins prüfen", + "VTLANG_JSON_CHK_INJECTION": "Konfiguration des Injektions-Plugins prüfen", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Konfiguration des auto-memdisk-Plugins prüfen", + "VTLANG_JSON_CHK_IMG_LIST": "Konfiguration des Abbild-Listen-Plugins prüfen", + "VTLANG_JSON_CHK_IMG_BLIST": "Konfiguration des Abbild-Sperrlisten-Plugins prüfen", + "VTLANG_JSON_CHK_CONF_REPLACE": "Konfiguration des Boot-Conf-Replace-Plugins prüfen", + "VTLANG_JSON_CHK_DUD": "Konfiguration des dud-Plugins prüfen", + "VTLANG_JSON_CHK_PASSWORD": "Konfiguration des Passwort-Plugins prüfen", + + "VTLANG_NORMAL_MODE": "In Normal-Modus starten", + "VTLANG_WIMBOOT_MODE": "In wimboot-Modus starten", + "VTLANG_GRUB2_MODE": "In grub2-Modus starten", + "VTLANG_MEMDISK_MODE": "In memdisk-Modus starten", + + "VTLANG_RET_TO_LISTVIEW": "Zurück zur Listenansicht", + "VTLANG_RET_TO_TREEVIEW": "Zurück zur Baumansicht", + + "VTLANG_NO_AUTOINS_SCRIPT": "Ohne Vorlage für die automatische Installation starten", + "VTLANG_AUTOINS_USE": "Start mit", + + "VTLANG_NO_PERSIST": "Ohne Persistenz starten", + "VTLANG_PERSIST_USE": "Start mit", + + "VTLANG_BROWER_RETURN": "Zurück", + + "VTLANG_ENTER_EXIT": "Drücken Sie zum Beenden die Eingabetaste", + "VTLANG_ENTER_REBOOT": "Drücken Sie die Eingabetaste, um neu zu starten", + "VTLANG_ENTER_CONTINUE": "Drücken Sie die Eingabetaste, um fortzufahren", + + "VTLANG_CTRL_TEMP_SET": "Temporäre Steuerungseinstellungen", + "VTLANG_WIN11_BYPASS_CHECK": "Umgehen Sie die CPU/TPM/SecureBoot-Prüfung bei der Installation von Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Umgehen Sie die Online-Kontoanforderung bei der Installation von Windows 11", + "VTLANG_LINUX_REMOUNT": "Mounten Sie die Hiperiso-Partition nach dem Booten von Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Sekundäres Bootmenü anzeigen", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/el_GR.json b/src/grub2/grub/menu/el_GR.json new file mode 100644 index 0000000..7d97be3 --- /dev/null +++ b/src/grub2/grub/menu/el_GR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Greek (Ελληνικά)", + + "VTLANG_STR_HOTKEY_LIST": "L:Γλώσσα F1:Βοήθεια F2:Περιήγηση F3:Προβολή Λίστας F4:Εκκίνηση από τοπικό δίσκο F5:Εργαλεία F6:Προσ. Μενού", + "VTLANG_STR_HOTKEY_TREE": "L:Γλώσσα F1:Βοήθεια F2:Περιήγηση F3:Προβολή Δένδρου F4:Εκκίνηση από τοπικό δίσκο F5:Εργαλεία F6:Προσ. Μενού", + "VTLANG_RETURN_PREVIOUS": "Επιστροφή στο προηγούμενο μενού [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Επιστροφή στο προηγούμενο μενού", + + "VTLANG_MENU_LANG": "Επιλογή Γλώσσας Μενού", + + "VTLANG_LB_SBOOT_WINDOWS": "Αναζήτηση και εκκίνηση των Windows", + "VTLANG_LB_SBOOT_G4D": "Αναζήτηση και εκκίνηση του Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Εκκίνηση του 1ου τοπικού δίσκου", + "VTLANG_LB_SBOOT_HDD2": "Εκκίνηση του 2ου τοπικού δίσκου", + "VTLANG_LB_SBOOT_HDD3": "Εκκίνηση του 3ου τοπικού δίσκου", + "VTLANG_LB_SBOOT_X64EFI": "Αναζήτηση και εκκίνηση του BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Αναζήτηση και εκκίνηση του BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Αναζήτηση και εκκίνηση του BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Αναζήτηση και εκκίνηση του xorboot", + + "VTLANG_FILE_CHKSUM": "Αρχείο checksum", + "VTLANG_CHKSUM_MD5_CALC": "Υπολογισμός md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Υπολογισμός sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Υπολογισμός sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Υπολογισμός sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Υπολογισμός και έλεγχος md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Υπολογισμός και έλεγχος sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Υπολογισμός και έλεγχος sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Υπολογισμός και έλεγχος sha512sum", + + "VTLANG_POWER": "Λειτουργία", + "VTLANG_POWER_REBOOT": "Επανεκκίνηση", + "VTLANG_POWER_HALT": "Απενεργοποίηση", + "VTLANG_POWER_BOOT_EFIFW": "Επανεκκίνηση σε EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Διατάξεις Πληκτρολογίου", + "VTLANG_HWINFO": "Πληροφορίες υλικού", + + "VTLANG_RESOLUTION_CFG": "Διαμόρφωση ανάλυσης", + "VTLANG_SCREEN_MODE": "Λειτουργία Προβολής Οθόνης", + "VTLANG_SCREEN_TEXT_MODE": "Επιβολή λειτουργίας κειμένου", + "VTLANG_SCREEN_GUI_MODE": "Επιβολή λειτουργίας Γραφικών (GUI)", + + "VTLANG_THEME_SELECT": "Επιλογή Θέματος", + + "VTLANG_UEFI_UTIL": "Εργαλεία Hiperiso UEFI", + "VTLANG_UTIL_SHOW_EFI_DRV": "Προβολή EFI Drivers", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Διόρθωση αποτυχίας Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "Ελεγχος διαμόρφωσης json πρόσθετων (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Ελεγχος διαμόρφωσης του πρόσθετου καθολικού ελέγχου", + "VTLANG_JSON_CHK_THEME": "Ελεγχος διαμόρφωσης του πρόσθετου θέματος", + "VTLANG_JSON_CHK_AUTOINS": "Ελεγχος διαμόρφωσης του πρόσθετου αυτόματης εγκατάστασης", + "VTLANG_JSON_CHK_PERSIST": "Ελεγχος διαμόρφωσης του πρόσθετου επιμονής", + "VTLANG_JSON_CHK_MENU_ALIAS": "Ελεγχος διαμόρφωσης του πρόσθετου ψευδώνυμου μενού", + "VTLANG_JSON_CHK_MENU_TIP": "Ελεγχος διαμόρφωσης του πρόσθετου συμβουλών μενού", + "VTLANG_JSON_CHK_MENU_CLASS": "Ελεγχος διαμόρφωσης του πρόσθετου κατηγορίας μενού", + "VTLANG_JSON_CHK_INJECTION": "Ελεγχος διαμόρφωσης του πρόσθετου injection", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Ελεγχος διαμόρφωσης του πρόσθετου auto memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Ελεγχος διαμόρφωσης του πρόσθετου Λίστα images", + "VTLANG_JSON_CHK_IMG_BLIST": "Ελεγχος διαμόρφωσης του πρόσθετου Μαύρη λίστα images", + "VTLANG_JSON_CHK_CONF_REPLACE": "Ελεγχος διαμόρφωσης του πρόσθετου Αντικατάσταση διαμόρφ. εκκίνησης", + "VTLANG_JSON_CHK_DUD": "Ελεγχος διαμόρφωσης του πρόσθετου dud", + "VTLANG_JSON_CHK_PASSWORD": "Ελεγχος διαμόρφωσης του πρόσθετου Κωδικός πρόσβασης", + + "VTLANG_NORMAL_MODE": "Κανονική εκκίνηση", + "VTLANG_WIMBOOT_MODE": "Εκκίνηση σε λειτουργία wimboot", + "VTLANG_GRUB2_MODE": "Εκκίνηση σε λειτουργία grub2", + "VTLANG_MEMDISK_MODE": "Εκκίνηση σε λειτουργία memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Επιστροφή σε Προβολή Λίστας", + "VTLANG_RET_TO_TREEVIEW": "Επιστροφή σε Προβολή Δένδρου", + + "VTLANG_NO_AUTOINS_SCRIPT": "Εκκίνηση χωρίς πρότυπο αυτόματης εγκατάστασης", + "VTLANG_AUTOINS_USE": "Εκκίνηση", + + "VTLANG_NO_PERSIST": "Εκκίνηση χωρίς επιμονή", + "VTLANG_PERSIST_USE": "Εκκίνηση", + + "VTLANG_BROWER_RETURN": "Επιστροφή", + + "VTLANG_ENTER_EXIT": "πατήστε το πλήκτρο Enter για έξοδο", + "VTLANG_ENTER_REBOOT": "πατήστε το πλήκτρο Enter για επανεκκίνηση", + "VTLANG_ENTER_CONTINUE": "πατήστε το πλήκτρο Enter για να συνεχίσετε", + + "VTLANG_CTRL_TEMP_SET": "Προσωρινές ρυθμίσεις ελέγχου", + "VTLANG_WIN11_BYPASS_CHECK": "Παράκαμψη ελέγχου CPU/TPM/SecureBoot κατά την εγκατάσταση των Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Παράκαμψη της απαίτησης online λογαριασμού κατά την εγκατάσταση των Windows 11", + "VTLANG_LINUX_REMOUNT": "Προσάρτηση διαμερίσματος Hiperiso μετά την εκκίνηση του Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Εμφάνιση δευτερεύοντος μενού εκκίνησης", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} \ No newline at end of file diff --git a/src/grub2/grub/menu/en_US.json b/src/grub2/grub/menu/en_US.json new file mode 100644 index 0000000..47cb7f4 --- /dev/null +++ b/src/grub2/grub/menu/en_US.json @@ -0,0 +1,98 @@ +{ + "VTLANG_LANGUAGE_NAME": "English (English)", + + "VTLANG_STR_HOTKEY_LIST": "L:Language F1:Help F2:Browse F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Language F1:Help F2:Browse F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Return to previous menu [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Return to previous menu", + + "VTLANG_MENU_LANG": "Menu Language Select", + + "VTLANG_LB_SBOOT_WINDOWS": "Search and boot Windows", + "VTLANG_LB_SBOOT_G4D": "Search and boot Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Boot the 1st local disk", + "VTLANG_LB_SBOOT_HDD2": "Boot the 2nd local disk", + "VTLANG_LB_SBOOT_HDD3": "Boot the 3rd local disk", + "VTLANG_LB_SBOOT_X64EFI": "Search and boot BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Search and boot BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Search and boot BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Search and boot xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Calculate md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calculate sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calculate sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calculate sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calculate and check md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calculate and check sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calculate and check sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calculate and check sha512sum", + + "VTLANG_POWER": "Power", + "VTLANG_POWER_REBOOT": "Reboot", + "VTLANG_POWER_HALT": "Halt", + "VTLANG_POWER_BOOT_EFIFW": "Reboot to EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Keyboard Layouts", + "VTLANG_HWINFO": "Hardware Information", + + "VTLANG_RESOLUTION_CFG": "Resolution Configuration", + "VTLANG_SCREEN_MODE": "Screen Display Mode", + "VTLANG_SCREEN_TEXT_MODE": "Force Text Mode", + "VTLANG_SCREEN_GUI_MODE": "Force Graphics Mode", + + "VTLANG_THEME_SELECT": "Theme Select", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "Show EFI Drivers", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Fixup Windows BlinitializeLibrary Failure", + + "VTLANG_JSON_CHK_JSON": "Check plugin json configuration (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Check global control plugin configuration", + "VTLANG_JSON_CHK_THEME": "Check theme plugin configuration", + "VTLANG_JSON_CHK_AUTOINS": "Check auto install plugin configuration", + "VTLANG_JSON_CHK_PERSIST": "Check persistence plugin configuration", + "VTLANG_JSON_CHK_MENU_ALIAS": "Check menu alias plugin configuration", + "VTLANG_JSON_CHK_MENU_TIP": "Check menu tip plugin configuration", + "VTLANG_JSON_CHK_MENU_CLASS": "Check menu class plugin configuration", + "VTLANG_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Check auto memdisk plugin configuration", + "VTLANG_JSON_CHK_IMG_LIST": "Check image list plugin configuration", + "VTLANG_JSON_CHK_IMG_BLIST": "Check image blacklist plugin configuration", + "VTLANG_JSON_CHK_CONF_REPLACE": "Check boot conf replace plugin configuration", + "VTLANG_JSON_CHK_DUD": "Check dud plugin configuration", + "VTLANG_JSON_CHK_PASSWORD": "Check password plugin configuration", + + "VTLANG_NORMAL_MODE": "Boot in normal mode", + "VTLANG_WIMBOOT_MODE": "Boot in wimboot mode", + "VTLANG_GRUB2_MODE": "Boot in grub2 mode", + "VTLANG_MEMDISK_MODE": "Boot in memdisk mode", + + "VTLANG_RET_TO_LISTVIEW": "Return to ListView", + "VTLANG_RET_TO_TREEVIEW": "Return to TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Boot without auto installation template", + "VTLANG_AUTOINS_USE": "Boot with", + + "VTLANG_NO_PERSIST": "Boot without persistence", + "VTLANG_PERSIST_USE": "Boot with", + + "VTLANG_BROWER_RETURN": "Return", + + "VTLANG_ENTER_EXIT": "press Enter key to exit", + "VTLANG_ENTER_REBOOT": "press Enter key to reboot", + "VTLANG_ENTER_CONTINUE": "press Enter key to continue", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/es_ES.json b/src/grub2/grub/menu/es_ES.json new file mode 100644 index 0000000..3cbf481 --- /dev/null +++ b/src/grub2/grub/menu/es_ES.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Spanish (Español)", + + "VTLANG_STR_HOTKEY_LIST": "L:Idioma F1:Ayuda F2:Navegar F3:Vista de lista F4:Arranque local F5:Herramientas F6:Menú ext.", + "VTLANG_STR_HOTKEY_TREE": "L:Idioma F1:Ayuda F2:Navegar F3:Vista de árbol F4:Arranque local F5:Herramientas F6:Menú ext.", + "VTLANG_RETURN_PREVIOUS": "Regresar al menú anterior [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Regresar al menú anterior", + + "VTLANG_MENU_LANG": "Selección de idioma del menú", + + "VTLANG_LB_SBOOT_WINDOWS": "Buscar y arrancar Windows", + "VTLANG_LB_SBOOT_G4D": "Buscar y arrancar Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Arrancar el 1er disco local", + "VTLANG_LB_SBOOT_HDD2": "Arrancar el 2do disco local", + "VTLANG_LB_SBOOT_HDD3": "Arrancar el 3er disco local", + "VTLANG_LB_SBOOT_X64EFI": "Buscar y arrancar BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Buscar y arrancar BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Buscar y arrancar BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Buscar y arrancar xorboot", + + "VTLANG_FILE_CHKSUM": "Suma de comprobación del archivo", + "VTLANG_CHKSUM_MD5_CALC": "Calcular md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calcular sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calcular sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calcular sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calcular y comprobar md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calcular y comprobar sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calcular y comprobar sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calcular y comprobar sha512sum", + + "VTLANG_POWER": "Energía", + "VTLANG_POWER_REBOOT": "Reiniciar", + "VTLANG_POWER_HALT": "Apagar", + "VTLANG_POWER_BOOT_EFIFW": "Reiniciar a la configuración EFI", + + "VTLANG_KEYBRD_LAYOUT": "Distribuciones de teclado", + "VTLANG_HWINFO": "Información de hardware", + + "VTLANG_RESOLUTION_CFG": "Configuración de resolución", + "VTLANG_SCREEN_MODE": "Modo de visualización de pantalla", + "VTLANG_SCREEN_TEXT_MODE": "Forzar modo texto", + "VTLANG_SCREEN_GUI_MODE": "Forzar modo gráfico", + + "VTLANG_THEME_SELECT": "Selección de tema", + + "VTLANG_UEFI_UTIL": "Utilidades UEFI de Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Mostrar controladores EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Reparar error BlinitializeLibrary de Windows", + + "VTLANG_JSON_CHK_JSON": "Comprobar configuración del complemento de json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Comprobar configuración del complemento de control global", + "VTLANG_JSON_CHK_THEME": "Comprobar configuración del complemento de tema", + "VTLANG_JSON_CHK_AUTOINS": "Comprobar configuración del complemento de autoinstalación", + "VTLANG_JSON_CHK_PERSIST": "Comprobar configuración del complemento de persistencia", + "VTLANG_JSON_CHK_MENU_ALIAS": "Comprobar configuración del complemento de alias de menú", + "VTLANG_JSON_CHK_MENU_TIP": "Comprobar configuración del complemento de consejo de menú", + "VTLANG_JSON_CHK_MENU_CLASS": "Comprobar configuración del complemento de clases de menú", + "VTLANG_JSON_CHK_INJECTION": "Comprobar configuración del complemento de inyección", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Comprobar configuración del complemento auto memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Comprobar configuración del complemento de lista de imágenes", + "VTLANG_JSON_CHK_IMG_BLIST": "Comprobar configuración del complemento de lista negra de imágenes", + "VTLANG_JSON_CHK_CONF_REPLACE": "Comprobar configuración del complemento de reemplazo de configuración de arranque", + "VTLANG_JSON_CHK_DUD": "Comprobar configuración del complemento dud", + "VTLANG_JSON_CHK_PASSWORD": "Comprobar configuración del complemento de contraseñas", + + "VTLANG_NORMAL_MODE": "Arrancar en modo normal", + "VTLANG_WIMBOOT_MODE": "Arrancar en modo wimboot", + "VTLANG_GRUB2_MODE": "Arrancar en modo grub2", + "VTLANG_MEMDISK_MODE": "Arrancar en modo memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Regresar a vista de lista", + "VTLANG_RET_TO_TREEVIEW": "regresar a vista de árbol", + + "VTLANG_NO_AUTOINS_SCRIPT": "Arrancar sin plantilla de autoinstalación", + "VTLANG_AUTOINS_USE": "Arrancar con", + + "VTLANG_NO_PERSIST": "Arrancar sin persistencia", + "VTLANG_PERSIST_USE": "Arrancar con", + + "VTLANG_BROWER_RETURN": "Regresar", + + "VTLANG_ENTER_EXIT": "Presiona la tecla Entrar para salir", + "VTLANG_ENTER_REBOOT": "Presiona la tecla Entrar para reiniciar", + "VTLANG_ENTER_CONTINUE": "Presiona la tecla Entrar para continuar", + + "VTLANG_CTRL_TEMP_SET": "Ajustes de control temporales", + "VTLANG_WIN11_BYPASS_CHECK": "Omitir comprobación de CPU/TPM/SecureBoot al instalar Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Omitir requisito de cuenta en línea al instalar Windows 11", + "VTLANG_LINUX_REMOUNT": "Montar partición de Hiperiso después de arrancar Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Mostrar menú de arranque secundario", + "VTLANG_WIN_UEFI_RES_LOCK": "Bloquear la resolución al arrancar Windows/WinPE en modo UEFI", + "VTLANG_UEFI_RES_LOCK_NONE": "Ninguno", + "VTLANG_UEFI_RES_LOCK_MAX": "La más alta", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fija 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "Al menos 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/fa_IR.json b/src/grub2/grub/menu/fa_IR.json new file mode 100644 index 0000000..fb4f2a8 --- /dev/null +++ b/src/grub2/grub/menu/fa_IR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Persian (فارسی)", + + "VTLANG_STR_HOTKEY_LIST": "L:زبان F1:راهنما F2:مرور F3:نمای لیستی F4:بوت محلی F5:ابزار F6:بازگشت", + "VTLANG_STR_HOTKEY_TREE": "L:زبان F1:راهنما F2:مرور F3:نمای درختی F4:بوت محلی F5:ابزار F6:بازگشت", + "VTLANG_RETURN_PREVIOUS": "بازگشت به منوی قبلی [Esc]", + "VTLANG_RETURN_PRV_NOESC": "بازگشت به منوی قبلی", + + "VTLANG_MENU_LANG": "منوی انتخاب زبان", + + "VTLANG_LB_SBOOT_WINDOWS": "جستجو و بوت ویندوز", + "VTLANG_LB_SBOOT_G4D": "جستجو و بوت Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "بوت اولین دیسک محلی", + "VTLANG_LB_SBOOT_HDD2": "بوت دومین دیسک محلی", + "VTLANG_LB_SBOOT_HDD3": "بوت سومین دیسک محلی", + "VTLANG_LB_SBOOT_X64EFI": "جستجو و بوت BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "جستجو و بوت BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "جستجو و بوت BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "جستجو و بوت xorboot", + + "VTLANG_FILE_CHKSUM": "اعتبارسنجی فایل", + "VTLANG_CHKSUM_MD5_CALC": "محاسبه md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "محاسبه sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "محاسبه sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "محاسبه sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "محاسبه و بررسی md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "محاسبه و بررسی sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "محاسبه و بررسی sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "محاسبه و بررسی sha512sum", + + "VTLANG_POWER": "انرژی", + "VTLANG_POWER_REBOOT": "ریبوت", + "VTLANG_POWER_HALT": "توقف", + "VTLANG_POWER_BOOT_EFIFW": "ریبوت به تنظیمات EFI", + + "VTLANG_KEYBRD_LAYOUT": "نمایه صفحه کلید", + "VTLANG_HWINFO": "اطلاعات سخت افزار", + + "VTLANG_RESOLUTION_CFG": "پیکربندی رزولوشن", + "VTLANG_SCREEN_MODE": "حالت نمایش صفحه", + "VTLANG_SCREEN_TEXT_MODE": "حالت متنی اجباری", + "VTLANG_SCREEN_GUI_MODE": "حالت گرافیکی اجباری", + + "VTLANG_THEME_SELECT": "انتخاب تم", + + "VTLANG_UEFI_UTIL": "ابزار های کمکی Hiperiso UEFI", + "VTLANG_UTIL_SHOW_EFI_DRV": "نمایش درایور های EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "رفع خطای Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "بررسی پیکربندی json افزونه (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "بررسی پیکربندی افزونه کنترل سراسری", + "VTLANG_JSON_CHK_THEME": "بررسی پیکربندی افزونه قالب", + "VTLANG_JSON_CHK_AUTOINS": "بررسی پیکربندی افزونه نصب خودکار", + "VTLANG_JSON_CHK_PERSIST": "بررسی پیکربندی افزونه‌ی تداوم", + "VTLANG_JSON_CHK_MENU_ALIAS": "بررسی پیکربندی افزونه نام مستعار منو", + "VTLANG_JSON_CHK_MENU_TIP": "بررسی پیکربندی افزونه نکته منو", + "VTLANG_JSON_CHK_MENU_CLASS": "بررسی پیکربندی افزونه کلاس منو", + "VTLANG_JSON_CHK_INJECTION": "بررسی پیکربندی افزونه تزریق", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "بررسی پیکربندی افزونه memdisk خودکار", + "VTLANG_JSON_CHK_IMG_LIST": "بررسی پیکربندی افزونه لیست ایمیج ها", + "VTLANG_JSON_CHK_IMG_BLIST": "بررسی پیکربندی افزونه لیست سیاه ایمیج", + "VTLANG_JSON_CHK_CONF_REPLACE": "بررسی پیکربندی افزونه جایگزینی فایل پیکربندی بوت", + "VTLANG_JSON_CHK_DUD": "بررسی پیکربندی افزونه dud", + "VTLANG_JSON_CHK_PASSWORD": "بررسی پیکربندی افزونه کلمه عبور", + + "VTLANG_NORMAL_MODE": "بوت در حالت عادی", + "VTLANG_WIMBOOT_MODE": "بوت در حالت wimboot", + "VTLANG_GRUB2_MODE": "بوت در حالت grub2", + "VTLANG_MEMDISK_MODE": "بوت در حالت memdisk", + + "VTLANG_RET_TO_LISTVIEW": "بازگشت به نمای لیستی", + "VTLANG_RET_TO_TREEVIEW": "بازگشت به نمای درختی", + + "VTLANG_NO_AUTOINS_SCRIPT": "بوت بدون قالب نصب خودکار", + "VTLANG_AUTOINS_USE": "بوت با", + + "VTLANG_NO_PERSIST": "بوت بدون تداوم", + "VTLANG_PERSIST_USE": "بوت با", + + "VTLANG_BROWER_RETURN": "بازگشت", + + "VTLANG_ENTER_EXIT": "جهت خروج دکمه Enter را فشار دهید", + "VTLANG_ENTER_REBOOT": "جهت ریبوت دکمه Enter را فشار دهید", + "VTLANG_ENTER_CONTINUE": "جهت ادامه دکمه Enter را فشار دهید", + + "VTLANG_CTRL_TEMP_SET": "تنظیمات کنترل موقت", + "VTLANG_WIN11_BYPASS_CHECK": "دور زدن بررسی CPU/TPM/SecureBoot در هنگام نصب ویندوز 11", + "VTLANG_WIN11_BYPASS_NRO": "دور زدن نیاز به حساب کاربری آنلاین هنگام نصب ویندوز 11", + "VTLANG_LINUX_REMOUNT": "اتصال پارتیشن Hiperiso بعد از بوت لینوکس", + "VTLANG_SECONDARY_BOOT_MENU": "نمایش منوی بوت ثانویه", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/fr_FR.json b/src/grub2/grub/menu/fr_FR.json new file mode 100644 index 0000000..617027a --- /dev/null +++ b/src/grub2/grub/menu/fr_FR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "French (Français)", + + "VTLANG_STR_HOTKEY_LIST": "L:Langue F1:Aide F2:Parcourir F3:Affichage liste F4:Démarrage local F5:Outils F6:Menu étendu", + "VTLANG_STR_HOTKEY_TREE": "L:Langue F1:Aide F2:Parcourir F3:Affichage arborescence F4:Démarrage local F5:Outils F6:Menu étendu", + "VTLANG_RETURN_PREVIOUS": "Retour au menu précédent [Echap]", + "VTLANG_RETURN_PRV_NOESC": "Retour au menu précédent", + + "VTLANG_MENU_LANG": "Sélection de la langue des menus", + + "VTLANG_LB_SBOOT_WINDOWS": "Rechercher et démarrer Windows", + "VTLANG_LB_SBOOT_G4D": "Rechercher et démarrer GRUB4DOS", + "VTLANG_LB_SBOOT_HDD1": "Démarrer depuis le 1er disque local", + "VTLANG_LB_SBOOT_HDD2": "Démarrer depuis le 2e disque local", + "VTLANG_LB_SBOOT_HDD3": "Démarrer depuis le 3e disque local", + "VTLANG_LB_SBOOT_X64EFI": "Rechercher et démarrer BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Rechercher et démarrer BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Rechercher et démarrer BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Rechercher et démarrer xorboot", + + "VTLANG_FILE_CHKSUM": "Somme de contrôle du fichier", + "VTLANG_CHKSUM_MD5_CALC": "Calculer MD5", + "VTLANG_CHKSUM_SHA1_CALC": "Calculer SHA1", + "VTLANG_CHKSUM_SHA256_CALC": "Calculer SHA256", + "VTLANG_CHKSUM_SHA512_CALC": "Calculer SHA512", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calculer et vérifier MD5", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calculer et vérifier SHA1", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calculer et vérifier SHA256", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calculer et vérifier SHA512", + + "VTLANG_POWER": "Extinction", + "VTLANG_POWER_REBOOT": "Redémarrer", + "VTLANG_POWER_HALT": "Éteindre", + "VTLANG_POWER_BOOT_EFIFW": "Redémarrer et accéder au menu EFI", + + "VTLANG_KEYBRD_LAYOUT": "Dispositions de clavier", + "VTLANG_HWINFO": "Informations sur le matériel", + + "VTLANG_RESOLUTION_CFG": "Configuration de la résolution", + "VTLANG_SCREEN_MODE": "Mode d’affichage", + "VTLANG_SCREEN_TEXT_MODE": "Mode texte", + "VTLANG_SCREEN_GUI_MODE": "Mode graphique", + + "VTLANG_THEME_SELECT": "Sélection du thème", + + "VTLANG_UEFI_UTIL": "Utilitaires UEFI de Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Afficher les pilotes EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Contourner l’échec de Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "Afficher le fichier de configuration (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Afficher la configuration du plugin de contrôle global", + "VTLANG_JSON_CHK_THEME": "Afficher la configuration du plugin de thème", + "VTLANG_JSON_CHK_AUTOINS": "Afficher la configuration du plugin d’installation automatique", + "VTLANG_JSON_CHK_PERSIST": "Afficher la configuration du plugin de persistance", + "VTLANG_JSON_CHK_MENU_ALIAS": "Afficher la configuration du plugin des alias du menu", + "VTLANG_JSON_CHK_MENU_TIP": "Afficher la configuration du plugin des astuces du menu", + "VTLANG_JSON_CHK_MENU_CLASS": "Afficher la configuration du plugin des classes du menu", + "VTLANG_JSON_CHK_INJECTION": "Afficher la configuration du plugin d’injection", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Afficher la configuration du plugin memdisk automatique", + "VTLANG_JSON_CHK_IMG_LIST": "Afficher la configuration du plugin de liste des images", + "VTLANG_JSON_CHK_IMG_BLIST": "Afficher la configuration du plugin de liste noire des images", + "VTLANG_JSON_CHK_CONF_REPLACE": "Afficher la configuration du plugin de substitution des fichiers de démarrage", + "VTLANG_JSON_CHK_DUD": "Afficher la configuration du plugin de disques de mise à jour des pilotes", + "VTLANG_JSON_CHK_PASSWORD": "Afficher la configuration du plugin de mots de passe", + + "VTLANG_NORMAL_MODE": "Démarrer en mode normal", + "VTLANG_WIMBOOT_MODE": "Démarrer en mode WimBoot", + "VTLANG_GRUB2_MODE": "Démarrer en mode GRUB 2", + "VTLANG_MEMDISK_MODE": "Démarrer en mode Memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Revenir à l’affichage en liste", + "VTLANG_RET_TO_TREEVIEW": "Revenir à l’affichage en arborescence", + + "VTLANG_NO_AUTOINS_SCRIPT": "Démarrer en ignorant le modèle d’auto-installation", + "VTLANG_AUTOINS_USE": "Démarrer en chargeant le modèle d’auto-installation", + + "VTLANG_NO_PERSIST": "Démarrer sans persistance", + "VTLANG_PERSIST_USE": "Démarrer avec la persistance", + + "VTLANG_BROWER_RETURN": "Retour", + + "VTLANG_ENTER_EXIT": "appuyez sur la touche Entrée pour quitter", + "VTLANG_ENTER_REBOOT": "appuyez sur la touche Entrée pour redémarrer", + "VTLANG_ENTER_CONTINUE": "appuyez sur la touche Entrée pour continuer", + + "VTLANG_CTRL_TEMP_SET": "Paramètres de contrôle temporaires", + "VTLANG_WIN11_BYPASS_CHECK": "Ignorer la vérification CPU/TPM/SecureBoot lors de l'installation de Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Contourner l'exigence de compte en ligne lors de l'installation de Windows 11", + "VTLANG_LINUX_REMOUNT": "Monter la partition Hiperiso après le démarrage de Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Afficher le menu de démarrage secondaire", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/hi_HI.json b/src/grub2/grub/menu/hi_HI.json new file mode 100644 index 0000000..6fe84bb --- /dev/null +++ b/src/grub2/grub/menu/hi_HI.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Hindi (हिन्दी)", + + "VTLANG_STR_HOTKEY_LIST": "L:भाषा F1:मदद F2:ब्राउज़र F3:ListView F4:स्थानीयबूट F5:उपकरण F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:भाषा F1:मदद F2:ब्राउज़र F3:TreeView F4:स्थानीयबूट F5:उपकरण F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "पिछले मेनू पर लौटें [Esc]", + "VTLANG_RETURN_PRV_NOESC": "पिछले मेनू पर लौटें", + + "VTLANG_MENU_LANG": "मेनू भाषा का चयन करें", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows खोजें और बूट करें", + "VTLANG_LB_SBOOT_G4D": "Grub4dos खोजें और बूट करें", + "VTLANG_LB_SBOOT_HDD1": "पहली(1st) स्थानीय डिस्क को बूट करें", + "VTLANG_LB_SBOOT_HDD2": "दूसरी(2nd) स्थानीय डिस्क बूट करें", + "VTLANG_LB_SBOOT_HDD3": "तीसरी(3rd) स्थानीय डिस्क बूट करें", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI खोजें और बूट करें", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI खोजें और बूट करें", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI खोजें और बूट करें", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot खोजें और बूट करें", + + "VTLANG_FILE_CHKSUM": "फ़ाइल चेकसम", + "VTLANG_CHKSUM_MD5_CALC": "Md5sum की गणना करें", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum की गणना करें", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum की गणना करें", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum की गणना करें", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum की गणना और जाँच करें", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum की गणना और जाँच करें", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum की गणना और जाँच करें", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum की गणना और जाँच करें", + + "VTLANG_POWER": "पावर", + "VTLANG_POWER_REBOOT": "रीबूट", + "VTLANG_POWER_HALT": "हाल्ट", + "VTLANG_POWER_BOOT_EFIFW": "EFI सेटअप के लिए रीबूट करें", + + "VTLANG_KEYBRD_LAYOUT": "कीबोर्ड लेआउट", + "VTLANG_HWINFO": "हार्डवेयर की जानकारी", + + "VTLANG_RESOLUTION_CFG": "रिज़ॉल्यूशन कॉन्फ़िगरेशन", + "VTLANG_SCREEN_MODE": "Screen Display मोड", + "VTLANG_SCREEN_TEXT_MODE": "फोर्स Text मोड", + "VTLANG_SCREEN_GUI_MODE": "फोर्स Graphics मोड", + + "VTLANG_THEME_SELECT": "थीम का चयन", + + "VTLANG_UEFI_UTIL": "वेंटोय UEFI यूटिलिटीज", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI ड्राइवर्स दिखाएं", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary विफलता को ठीक करें", + + "VTLANG_JSON_CHK_JSON": "प्लगइन json विन्यास की जाँच करें (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "global control प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_THEME": "theme प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_AUTOINS": "auto install प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_PERSIST": "persistence प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_MENU_ALIAS": "menu alias प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_MENU_TIP": "menu tip प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_MENU_CLASS": "menu class प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_INJECTION": "injection प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "auto memdisk प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_IMG_LIST": "image list प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_IMG_BLIST": "image blacklist प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_CONF_REPLACE": "boot conf replace प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_DUD": "dud प्लगइन विन्यास की जाँच करें", + "VTLANG_JSON_CHK_PASSWORD": "password प्लगइन विन्यास की जाँच करें", + + "VTLANG_NORMAL_MODE": "सामान्य मोड में बूट करें", + "VTLANG_WIMBOOT_MODE": "wimboot मोड में बूट करें", + "VTLANG_GRUB2_MODE": "grub2 मोड में बूट करें", + "VTLANG_MEMDISK_MODE": "memdisk मोड में बूट करें", + + "VTLANG_RET_TO_LISTVIEW": "ListView पर वापस जाएँ", + "VTLANG_RET_TO_TREEVIEW": "TreeView पर वापस जाएँ", + + "VTLANG_NO_AUTOINS_SCRIPT": "ऑटो इंस्टॉलेशन टेम्पलेट के बिना बूट करें", + "VTLANG_AUTOINS_USE": "के साथ बूट करें", + + "VTLANG_NO_PERSIST": "बिना persistence के बूट करें", + "VTLANG_PERSIST_USE": "के साथ बूट करें", + + "VTLANG_BROWER_RETURN": "लौटें", + + "VTLANG_ENTER_EXIT": "बाहर निकलने के लिए एंटर कुंजी दबाएं", + "VTLANG_ENTER_REBOOT": "रिबूट करने के लिए एंटर कुंजी दबाएं", + "VTLANG_ENTER_CONTINUE": "जारी रखने के लिए एंटर कुंजी दबाएं", + + "VTLANG_CTRL_TEMP_SET": "अस्थायी नियंत्रण सेटिंग्स", + "VTLANG_WIN11_BYPASS_CHECK": "जब विंडोज 11 स्थापित करें, CPU/TPM/SECUREBOOT CHECK को बायपास करें", + "VTLANG_WIN11_BYPASS_NRO": "विंडोज 11 स्थापित करते समय ऑनलाइन खाते की आवश्यकता बाईपास", + "VTLANG_LINUX_REMOUNT": "लिनक्स बूट के बाद वेंटॉय विभाजन को माउंट करें", + "VTLANG_SECONDARY_BOOT_MENU": "द्वितीयक बूट मेनू दिखाएं", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/hr_HR.json b/src/grub2/grub/menu/hr_HR.json new file mode 100644 index 0000000..4ddef87 --- /dev/null +++ b/src/grub2/grub/menu/hr_HR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Croatian (Hrvatski)", + + "VTLANG_STR_HOTKEY_LIST": "L:Jezik F1:Help F2:Browse F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Jezik F1:Help F2:Browse F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Return to previous menu [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Return to previous menu", + + "VTLANG_MENU_LANG": "Menu Language Select", + + "VTLANG_LB_SBOOT_WINDOWS": "Search and boot Windows", + "VTLANG_LB_SBOOT_G4D": "Search and boot Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Boot the 1st local disk", + "VTLANG_LB_SBOOT_HDD2": "Boot the 2nd local disk", + "VTLANG_LB_SBOOT_HDD3": "Boot the 3rd local disk", + "VTLANG_LB_SBOOT_X64EFI": "Search and boot BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Search and boot BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Search and boot BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Search and boot xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Calculate md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calculate sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calculate sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calculate sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calculate and check md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calculate and check sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calculate and check sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calculate and check sha512sum", + + "VTLANG_POWER": "Power", + "VTLANG_POWER_REBOOT": "Reboot", + "VTLANG_POWER_HALT": "Halt", + "VTLANG_POWER_BOOT_EFIFW": "Reboot to EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Keyboard Layouts", + "VTLANG_HWINFO": "Hardware Information", + + "VTLANG_RESOLUTION_CFG": "Resolution Configuration", + "VTLANG_SCREEN_MODE": "Screen Display Mode", + "VTLANG_SCREEN_TEXT_MODE": "Force Text Mode", + "VTLANG_SCREEN_GUI_MODE": "Force Graphics Mode", + + "VTLANG_THEME_SELECT": "Theme Select", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "Show EFI Drivers", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Fixup Windows BlinitializeLibrary Failure", + + "VTLANG_JSON_CHK_JSON": "Check plugin json configuration (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Check global control plugin configuration", + "VTLANG_JSON_CHK_THEME": "Check theme plugin configuration", + "VTLANG_JSON_CHK_AUTOINS": "Check auto install plugin configuration", + "VTLANG_JSON_CHK_PERSIST": "Check persistence plugin configuration", + "VTLANG_JSON_CHK_MENU_ALIAS": "Check menu alias plugin configuration", + "VTLANG_JSON_CHK_MENU_TIP": "Check menu tip plugin configuration", + "VTLANG_JSON_CHK_MENU_CLASS": "Check menu class plugin configuration", + "VTLANG_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Check auto memdisk plugin configuration", + "VTLANG_JSON_CHK_IMG_LIST": "Check image list plugin configuration", + "VTLANG_JSON_CHK_IMG_BLIST": "Check image blacklist plugin configuration", + "VTLANG_JSON_CHK_CONF_REPLACE": "Check boot conf replace plugin configuration", + "VTLANG_JSON_CHK_DUD": "Check dud plugin configuration", + "VTLANG_JSON_CHK_PASSWORD": "Check password plugin configuration", + + "VTLANG_NORMAL_MODE": "Boot in normal mode", + "VTLANG_WIMBOOT_MODE": "Boot in wimboot mode", + "VTLANG_GRUB2_MODE": "Boot in grub2 mode", + "VTLANG_MEMDISK_MODE": "Boot in memdisk mode", + + "VTLANG_RET_TO_LISTVIEW": "Return to ListView", + "VTLANG_RET_TO_TREEVIEW": "Return to TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Boot without auto installation template", + "VTLANG_AUTOINS_USE": "Boot with", + + "VTLANG_NO_PERSIST": "Boot without persistence", + "VTLANG_PERSIST_USE": "Boot with", + + "VTLANG_BROWER_RETURN": "Return", + + "VTLANG_ENTER_EXIT": "pritisnite tipku Enter za izlaz", + "VTLANG_ENTER_REBOOT": "pritisnite tipku Enter za ponovno pokretanje", + "VTLANG_ENTER_CONTINUE": "pritisnite tipku Enter za nastavak", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/hu_HU.json b/src/grub2/grub/menu/hu_HU.json new file mode 100644 index 0000000..7032e4f --- /dev/null +++ b/src/grub2/grub/menu/hu_HU.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Magyar (Hungarian)", + + "VTLANG_STR_HOTKEY_LIST": "L:Nyelv F1:Súgó F2:Tallózás F3:Listanézet F4:Helyi indítás F5:Eszközök F6:Bővített menü", + "VTLANG_STR_HOTKEY_TREE": "L:Nyelv F1:Súgó F2:Tallózás F3:Fanézet F4:Helyi indítás F5:Eszközök F6:Bővített menü", + "VTLANG_RETURN_PREVIOUS": "Vissza az előző menübe [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Vissza az előző menübe", + + "VTLANG_MENU_LANG": "Menü nyelvének kiválasztása", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows keresése és indítása", + "VTLANG_LB_SBOOT_G4D": "Grub4dos keresése és indítása", + "VTLANG_LB_SBOOT_HDD1": "Indítás az 1. helyi lemezről", + "VTLANG_LB_SBOOT_HDD2": "Indítás a 2. helyi lemezről", + "VTLANG_LB_SBOOT_HDD3": "Indítás a 3. helyi lemezről", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI keresése és indítása", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI keresése és indítása", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI keresése és indítása", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot keresése és indítása", + + "VTLANG_FILE_CHKSUM": "Fájl ellenőrzőösszege", + "VTLANG_CHKSUM_MD5_CALC": "md5sum kiszámítása", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum kiszámítása", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum kiszámítása", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum kiszámítása", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum kiszámítása és ellenőrzése", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum kiszámítása és ellenőrzése", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum kiszámítása és ellenőrzése", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum kiszámítása és ellenőrzése", + + "VTLANG_POWER": "Főkapcsoló", + "VTLANG_POWER_REBOOT": "Újraindítás", + "VTLANG_POWER_HALT": "Leállítás", + "VTLANG_POWER_BOOT_EFIFW": "Újraindítás EFI beállításba", + + "VTLANG_KEYBRD_LAYOUT": "Billentyűzetkiosztások", + "VTLANG_HWINFO": "Hardverinformációk", + + "VTLANG_RESOLUTION_CFG": "Felbontás beállítása", + "VTLANG_SCREEN_MODE": "Képernyő megjelenítési módja", + "VTLANG_SCREEN_TEXT_MODE": "Szöveges mód kényszerítése", + "VTLANG_SCREEN_GUI_MODE": "Grafikus mód kényszerítése", + + "VTLANG_THEME_SELECT": "Téma kiválasztása", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI-segédprogramok", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI-illesztőprogramok megjelenítése", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "A Windows BlinitializeLibrary hibájának javítása", + + "VTLANG_JSON_CHK_JSON": "A bővítmény JSON-beállításának (hiperiso.json) ellenőrzése", + "VTLANG_JSON_CHK_CONTROL": "A globális vezérlőbővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_THEME": "A téma bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_AUTOINS": "Az automatikus telepítés bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_PERSIST": "Az állandóság bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_MENU_ALIAS": "A menüálnév bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_MENU_TIP": "A menütipp bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_MENU_CLASS": "A menüosztály bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_INJECTION": "A befecskendezés bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Az automatikus memórialemez bővítmény beállításának ellenőrzése", + "VTLANG_JSON_CHK_IMG_LIST": "A lemezképlista bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_IMG_BLIST": "A lemezkép-tiltólista bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_CONF_REPLACE": "Az indítási beállítás csere bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_DUD": "A dud bővítmény beállításnak ellenőrzése", + "VTLANG_JSON_CHK_PASSWORD": "A jelszó bővítmény beállításnak ellenőrzése", + + "VTLANG_NORMAL_MODE": "Indítás normál módban", + "VTLANG_WIMBOOT_MODE": "Indítás wimboot módban", + "VTLANG_GRUB2_MODE": "Indítás grub2 módban", + "VTLANG_MEMDISK_MODE": "Indítás memórialemez módban", + + "VTLANG_RET_TO_LISTVIEW": "Vissza a listanézethez", + "VTLANG_RET_TO_TREEVIEW": "Vissza a fanézethez", + + "VTLANG_NO_AUTOINS_SCRIPT": "Indítás automatikus telepítési sablon nélkül", + "VTLANG_AUTOINS_USE": "Indítás ezzel:", + + "VTLANG_NO_PERSIST": "Indítás állandóság nélkül", + "VTLANG_PERSIST_USE": "Indítás ezzel:", + + "VTLANG_BROWER_RETURN": "Vissza", + + "VTLANG_ENTER_EXIT": "nyomja meg az Enter billentyűt a kilépéshez", + "VTLANG_ENTER_REBOOT": "nyomja meg az Enter billentyűt az újraindításhoz", + "VTLANG_ENTER_CONTINUE": "nyomja meg az Enter billentyűt a folytatáshoz", + + "VTLANG_CTRL_TEMP_SET": "Ideiglenes vezérlési beállítások", + "VTLANG_WIN11_BYPASS_CHECK": "CPU/TPM/SecureBoot ellenőrzés megkerülése Windows 11 telepítésekor", + "VTLANG_WIN11_BYPASS_NRO": "Internetes fiók követelményének megkerülése Windows 11 telepítésekor", + "VTLANG_LINUX_REMOUNT": "Hiperiso partíció csatolása a Linux indítása után", + "VTLANG_SECONDARY_BOOT_MENU": "Másodlagos indítási menü megjelenítése", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} \ No newline at end of file diff --git a/src/grub2/grub/menu/id_ID.json b/src/grub2/grub/menu/id_ID.json new file mode 100644 index 0000000..b97c8cb --- /dev/null +++ b/src/grub2/grub/menu/id_ID.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Indonesian (Bahasa Indonesia)", + + "VTLANG_STR_HOTKEY_LIST": "L:Bahasa F1:Bantuan F2:Jelajah F3:ListView F4:boot lokal F5:Alat Utilitas F6:Menu Eksternal", + "VTLANG_STR_HOTKEY_TREE": "L:Bahasa F1:Bantuan F2:Jelajah F3:ListView F4:boot lokal F5:Alat Utilitas F6:Menu Eksternal", + "VTLANG_RETURN_PREVIOUS": "Kembali ke menu sebelumnya [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Kembali ke menu sebelumnya", + + "VTLANG_MENU_LANG": "Menu Pilihan Bahasa", + + "VTLANG_LB_SBOOT_WINDOWS": "Mencari dan jalankan boot ke Windows", + "VTLANG_LB_SBOOT_G4D": "Mencari dan jalankan boot ke Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Jalankan boot ke disk lokal 1", + "VTLANG_LB_SBOOT_HDD2": "Jalankan boot ke disk lokal 2", + "VTLANG_LB_SBOOT_HDD3": "Jalankan boot ke disk lokal 3", + "VTLANG_LB_SBOOT_X64EFI": "Jalankan boot ke disk lokal nomor 1 BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Mencari dan jalankan boot ke BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Mencari dan jalankan boot ke BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Mencari dan jalankan boot ke xorboot", + + "VTLANG_FILE_CHKSUM": "Berkas checksum", + "VTLANG_CHKSUM_MD5_CALC": "Menghitung md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Menghitung sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Menghitung sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Menghitung sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Menghitung dan memeriksa md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Menghitung dan memeriksa sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Menghitung dan memeriksa sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Menghitung dan memeriksa sha512sum", + + "VTLANG_POWER": "Daya", + "VTLANG_POWER_REBOOT": "Memulai ulang", + "VTLANG_POWER_HALT": "Mematikan", + "VTLANG_POWER_BOOT_EFIFW": "Memulai ulang menuju EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Tata letak Keyboard", + "VTLANG_HWINFO": "Informasi Perangkat Keras", + + "VTLANG_RESOLUTION_CFG": "Setelan Resolusi", + "VTLANG_SCREEN_MODE": "Mode Tampilan Layar", + "VTLANG_SCREEN_TEXT_MODE": "Paksa ke Mode Teks", + "VTLANG_SCREEN_GUI_MODE": "Paksa ke Mode Grafis", + + "VTLANG_THEME_SELECT": "Pilih Tema", + + "VTLANG_UEFI_UTIL": "Utilitas UEFI Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Tampilkan Driver EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Memperbaiki Kegagalan Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "Periksa setelan plugin (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Periksa setelan plugin global control", + "VTLANG_JSON_CHK_THEME": "Periksa setelan plugin theme", + "VTLANG_JSON_CHK_AUTOINS": "Periksa setelan plugin auto install", + "VTLANG_JSON_CHK_PERSIST": "Periksa setelan plugin persistence", + "VTLANG_JSON_CHK_MENU_ALIAS": "Periksa setelan plugin menu alias", + "VTLANG_JSON_CHK_MENU_TIP": "Periksa setelan plugin tip", + "VTLANG_JSON_CHK_MENU_CLASS": "Periksa setelan class plugin menu", + "VTLANG_JSON_CHK_INJECTION": "Periksa setelan plugin injection", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Periksa setelan plugin auto memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Periksa setelan plugin image list", + "VTLANG_JSON_CHK_IMG_BLIST": "Periksa setelant plugin image blacklis", + "VTLANG_JSON_CHK_CONF_REPLACE": "Periksa setelan plugin boot conf replace", + "VTLANG_JSON_CHK_DUD": "Periksa setelan plugin dud", + "VTLANG_JSON_CHK_PASSWORD": "Periksa setelan plugin password", + + "VTLANG_NORMAL_MODE": "Jalankan boot di mode normal", + "VTLANG_WIMBOOT_MODE": "Jalankan boot di mode wimboot", + "VTLANG_GRUB2_MODE": "Jalankan boot di mode grub2", + "VTLANG_MEMDISK_MODE": "Jalankan boot di mode memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Kembali ke ListView", + "VTLANG_RET_TO_TREEVIEW": "Kembali ke TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Jalankan boot tanpa templat instalasi otomatis", + "VTLANG_AUTOINS_USE": "Jalankan boot dengan", + + "VTLANG_NO_PERSIST": "Jalankan boot tanpa persistence", + "VTLANG_PERSIST_USE": "Jalankan boot", + + "VTLANG_BROWER_RETURN": "Kembali", + + "VTLANG_ENTER_EXIT": "tekan tombol Enter untuk keluar", + "VTLANG_ENTER_REBOOT": "tekan tombol Enter untuk memulai ulang", + "VTLANG_ENTER_CONTINUE": "tekan tombol Enter untuk melanjutkan", + + "VTLANG_CTRL_TEMP_SET": "Pengaturan Kontrol Sementara", + "VTLANG_WIN11_BYPASS_CHECK": "Melewati pemeriksaaan CPU/TPM/SecureBoot ketika memasang Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Melewati persyaratan akun online ketika memasang Windows 11", + "VTLANG_LINUX_REMOUNT": "Memuat partisi Hiperiso setelah boot ke Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Tampilkan menu boot sekunder", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/it_IT.json b/src/grub2/grub/menu/it_IT.json new file mode 100644 index 0000000..a5e8fbd --- /dev/null +++ b/src/grub2/grub/menu/it_IT.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Italiano (Italian)", + + "VTLANG_STR_HOTKEY_LIST": "L:Lingua F1:Aiuto F2:Sfoglia F3:VistaElenco F4:BootLocale F5:Strumenti F6:MenuEx", + "VTLANG_STR_HOTKEY_TREE": "L:Lingua F1:Aiuto F2:Sfoglia F3:VistaStruttura F4:BootLocale F5:Strumenti F6:MenuEx", + "VTLANG_RETURN_PREVIOUS": "Torna al menu precedente [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Torna al menu precedente", + + "VTLANG_MENU_LANG": "Selezione lingua interfaccia", + + "VTLANG_LB_SBOOT_WINDOWS": "Cerca e avvia Windows", + "VTLANG_LB_SBOOT_G4D": "Cerca e avvia Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Avvia il 1° disco locale", + "VTLANG_LB_SBOOT_HDD2": "Avvia il 2° disco locale", + "VTLANG_LB_SBOOT_HDD3": "Avvia il 3° disco locale", + "VTLANG_LB_SBOOT_X64EFI": "Cerca e avvia BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Cerca e avvia BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Cerca e avvia BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Cerca e avvia xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Calcola md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calcola sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calcola sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calcola sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calcola e controlla md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calcola e controlla sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calcola e controlla sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calcola e controlla sha512sum", + + "VTLANG_POWER": "Spegni il computer", + "VTLANG_POWER_REBOOT": "Riavvia il computer", + "VTLANG_POWER_HALT": "Arresta il computer", + "VTLANG_POWER_BOOT_EFIFW": "Riavvia il computer nell'impostazione EFI", + + "VTLANG_KEYBRD_LAYOUT": "Layout tastiera", + "VTLANG_HWINFO": "Informazioni hardware computer", + + "VTLANG_RESOLUTION_CFG": "Imposta risoluzione schermo", + "VTLANG_SCREEN_MODE": "Modalità schermo (testo/grafica)", + "VTLANG_SCREEN_TEXT_MODE": "Forza modalità testo schermo", + "VTLANG_SCREEN_GUI_MODE": "Forza modalità grafica schermo", + + "VTLANG_THEME_SELECT": "Seleziona tema interfaccia", + + "VTLANG_UEFI_UTIL": "Utilità UEFI Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Visualizza driver EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Correzione fallimento BlinitializeLibrary di Windows", + + "VTLANG_JSON_CHK_JSON": "Modifica file .json plugin (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Modifica controllo globale della configurazione dei plugin", + "VTLANG_JSON_CHK_THEME": "Modifica tema configurazione dei plugin", + "VTLANG_JSON_CHK_AUTOINS": "Modifica installazione automatica della configurazione dei plugin", + "VTLANG_JSON_CHK_PERSIST": "Modifica persistenza della configurazione dei plugin", + "VTLANG_JSON_CHK_MENU_ALIAS": "Modifica l'alias del menu della configurazione dei plugin", + "VTLANG_JSON_CHK_MENU_TIP": "Modifica suggerimento del menu della configurazione dei plugin", + "VTLANG_JSON_CHK_MENU_CLASS": "Modifica classe menu configurazione plugin", + "VTLANG_JSON_CHK_INJECTION": "Modifica injection della configurazione plugin", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Modifica memdisk automatico della configurazione dei plugin", + "VTLANG_JSON_CHK_IMG_LIST": "Modifica elenco immagini configurazione plugin", + "VTLANG_JSON_CHK_IMG_BLIST": "Modifica elenco immagini vietate configurazione plugin", + "VTLANG_JSON_CHK_CONF_REPLACE": "Modifica sostituzione configurazione di avvio configurazione dei plugin", + "VTLANG_JSON_CHK_DUD": "Modifica dud configurazione plugin", + "VTLANG_JSON_CHK_PASSWORD": "Modifica password configurazione plugin", + + "VTLANG_NORMAL_MODE": "Avvia in modalità normale", + "VTLANG_WIMBOOT_MODE": "Avvia in modalità wimboot", + "VTLANG_GRUB2_MODE": "Avvia in modalità grub2", + "VTLANG_MEMDISK_MODE": "Avvia in modalità memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Torna alla VistaElenco", + "VTLANG_RET_TO_TREEVIEW": "Torna alla VistaStruttura", + + "VTLANG_NO_AUTOINS_SCRIPT": "Avvia senza il modello installazione automatica", + "VTLANG_AUTOINS_USE": "Avvia con", + + "VTLANG_NO_PERSIST": "Avvia senza persistenza", + "VTLANG_PERSIST_USE": "Avvia con", + + "VTLANG_BROWER_RETURN": "Indietro", + + "VTLANG_ENTER_EXIT": "Premi il tasto 'Invio' per uscire", + "VTLANG_ENTER_REBOOT": "Premi il tasto 'Invio' per riavviare", + "VTLANG_ENTER_CONTINUE": "Premi il tasto 'Invio' per continuare", + + "VTLANG_CTRL_TEMP_SET": "Impostazioni controllo temporaneo", + "VTLANG_WIN11_BYPASS_CHECK": "Durante l'installazione di Windows 11 bypassa il controllo CPU/TPM/SecureBoot ", + "VTLANG_WIN11_BYPASS_NRO": "Durante l'installazione di Windows 11 bypassa il requisito di un account online ", + "VTLANG_LINUX_REMOUNT": "Dopo l'avvio di Linux monta la partizione Hiperiso ", + "VTLANG_SECONDARY_BOOT_MENU": "Visualizza menu di avvio secondario", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/ja_JP.json b/src/grub2/grub/menu/ja_JP.json new file mode 100644 index 0000000..f824484 --- /dev/null +++ b/src/grub2/grub/menu/ja_JP.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Japanese (日本語)", + + "VTLANG_STR_HOTKEY_LIST": "L:言語 F1:説明 F2:閲覧 F3:表示切替(階層) F4:手許から起動 F5:道具 F6:拡張", + "VTLANG_STR_HOTKEY_TREE": "L:言語 F1:説明 F2:閲覧 F3:表示切替(一覧) F4:手許から起動 F5:道具 F6:拡張", + "VTLANG_RETURN_PREVIOUS": "前に戻る [Esc]", + "VTLANG_RETURN_PRV_NOESC": "前に戻る", + + "VTLANG_MENU_LANG": "表示言語", + + "VTLANG_LB_SBOOT_WINDOWS": "Windowsを検索して起動する", + "VTLANG_LB_SBOOT_G4D": "GRUB4DOSを検索して起動する", + "VTLANG_LB_SBOOT_HDD1": "最初の機器を起動します", + "VTLANG_LB_SBOOT_HDD2": "2番目の機器を起動する", + "VTLANG_LB_SBOOT_HDD3": "3番目の機器を起動する", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFIを検索して起動する", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFIを検索して起動する", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFIを検索して起動する", + "VTLANG_LB_SBOOT_XORBOOT": "xorbootを検索して起動する", + + "VTLANG_FILE_CHKSUM": "検査合計", + "VTLANG_CHKSUM_MD5_CALC": "MD5を算出する", + "VTLANG_CHKSUM_SHA1_CALC": "SHA1を算出する", + "VTLANG_CHKSUM_SHA256_CALC": "SHA256を算出する", + "VTLANG_CHKSUM_SHA512_CALC": "SHA512を算出する", + "VTLANG_CHKSUM_MD5_CALC_CHK": "MD5を算出して検証する", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "SHA1を算出して検証する", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "SHA256を算出して検証する", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "SHA512を算出して検証する", + + "VTLANG_POWER": "電源", + "VTLANG_POWER_REBOOT": "再起動", + "VTLANG_POWER_HALT": "電源断", + "VTLANG_POWER_BOOT_EFIFW": "再起動してEFIを構成する", + + "VTLANG_KEYBRD_LAYOUT": "鍵盤配列", + "VTLANG_HWINFO": "機器情報", + + "VTLANG_RESOLUTION_CFG": "画面解像度", + "VTLANG_SCREEN_MODE": "表示の種類", + "VTLANG_SCREEN_TEXT_MODE": "CLI表示を強制する", + "VTLANG_SCREEN_GUI_MODE": "GUI表示を強制する", + + "VTLANG_THEME_SELECT": "外観", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFIドライバを表示する", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windowsが「BlinitializeLibrary Failure」で起動しないのを修正する", + + "VTLANG_JSON_CHK_JSON": "拡張機能のJSON構成ファイル (hiperiso.json) を検査する", + "VTLANG_JSON_CHK_CONTROL": "拡張機能「global control」の構成を検査する", + "VTLANG_JSON_CHK_THEME": "拡張機能「theme」の構成を検査する", + "VTLANG_JSON_CHK_AUTOINS": "拡張機能「auto install」の構成を検査する", + "VTLANG_JSON_CHK_PERSIST": "拡張機能「persistence」の構成を検査する", + "VTLANG_JSON_CHK_MENU_ALIAS": "拡張機能「menu alias」の構成を検査する", + "VTLANG_JSON_CHK_MENU_TIP": "拡張機能「menu tip」の構成を検査する", + "VTLANG_JSON_CHK_MENU_CLASS": "拡張機能「menu class」の構成を検査する", + "VTLANG_JSON_CHK_INJECTION": "拡張機能「injection」の構成を検査する", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "拡張機能「auto memdisk」の構成を検査する", + "VTLANG_JSON_CHK_IMG_LIST": "拡張機能「image list」の構成を検査する", + "VTLANG_JSON_CHK_IMG_BLIST": "拡張機能「image blacklist」の構成を検査する", + "VTLANG_JSON_CHK_CONF_REPLACE": "拡張機能「boot conf replace」の構成を検査する", + "VTLANG_JSON_CHK_DUD": "拡張機能「dud」の構成を検査する", + "VTLANG_JSON_CHK_PASSWORD": "拡張機能「password」の構成を検査する", + + "VTLANG_NORMAL_MODE": "通常どおり起動", + "VTLANG_WIMBOOT_MODE": "WimBootを介して起動", + "VTLANG_GRUB2_MODE": "GRUB2を介して起動", + "VTLANG_MEMDISK_MODE": "MEMDISKを介して起動", + + "VTLANG_RET_TO_LISTVIEW": "一覧表示に切り替える", + "VTLANG_RET_TO_TREEVIEW": "階層表示に切り替える", + + "VTLANG_NO_AUTOINS_SCRIPT": "起動後に自動でインストールを行わない", + "VTLANG_AUTOINS_USE": "自動インストールを行う", + + "VTLANG_NO_PERSIST": "Live環境の永続保管領域を無効にする", + "VTLANG_PERSIST_USE": "有効にする", + + "VTLANG_BROWER_RETURN": "戻る", + + "VTLANG_ENTER_EXIT": "[Enter]を押して終了します", + "VTLANG_ENTER_REBOOT": "[Enter]を押して再起動します", + "VTLANG_ENTER_CONTINUE": "[Enter]を押して続行します", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/ka_GE.json b/src/grub2/grub/menu/ka_GE.json new file mode 100644 index 0000000..d8eac52 --- /dev/null +++ b/src/grub2/grub/menu/ka_GE.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Georgian (ქართული)", + + "VTLANG_STR_HOTKEY_LIST": "L:ენა F1:დახმარება F2:დათვალიერება F3:სიის ხედი F4:ლოკალური ჩატვირთვა F5:ხელსაწყოები F6:გასვლა", + "VTLANG_STR_HOTKEY_TREE": "L:ენა F1:დახმარება F2:დათვალიერება F3:ხის ხედი F4:ლოკალური ჩატვირთვა F5:ხელსაწყოები F6:გასვლა", + "VTLANG_RETURN_PREVIOUS": "წინა მენიუში დაბრუნება [Esc]", + "VTLANG_RETURN_PRV_NOESC": "წინა მენიუში დაბრუნება", + + "VTLANG_MENU_LANG": "მენიუს ენის არჩევა", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows-ის მოძებნა და ჩატვირთვა", + "VTLANG_LB_SBOOT_G4D": "Grub4dos-ის მოძებნა და ჩატვირთვა", + "VTLANG_LB_SBOOT_HDD1": "1-ლი ლოკალური მყარი დისკიდან ჩატვირთვა", + "VTLANG_LB_SBOOT_HDD2": "მე-2 ლოკალური მყარი დისკიდან ჩატვირთვა", + "VTLANG_LB_SBOOT_HDD3": "მე-3 ლოკალური მყარი დისკიდან ჩატვირთვა", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI-ის მოძებნა და ჩატვირთვა", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI-ის მოძებნა და ჩატვირთვა", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI-ის მოძებნა და ჩატვირთვა", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot-ის მოძებნა და ჩატვირთვა", + + "VTLANG_FILE_CHKSUM": "ფაილის საკონტროლო ჯამი", + "VTLANG_CHKSUM_MD5_CALC": "md5sum გამოთვლა", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum გამოთვლა", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum გამოთვლა", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum გამოთვლა", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum გამოთვლა და შემოწმება", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum გამოთვლა და შემოწმება", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum გამოთვლა და შემოწმება", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum გამოთვლა და შემოწმება", + + "VTLANG_POWER": "კომპიუტერის გამორთვა", + "VTLANG_POWER_REBOOT": "კომპიუტერის გადატვირთვა", + "VTLANG_POWER_HALT": "კომპიუტერის გაჩერება", + "VTLANG_POWER_BOOT_EFIFW": "გადატვირთვა EFI კონფიგურაციის რეჟიმში", + + "VTLANG_KEYBRD_LAYOUT": "კლავიატურის განლაგებები", + "VTLANG_HWINFO": "ინფორმაცია მოწყობილობების შესახებ", + + "VTLANG_RESOLUTION_CFG": "გარჩევადობის კონფიგურაცია", + "VTLANG_SCREEN_MODE": "ჩვენების რეჟიმი", + "VTLANG_SCREEN_TEXT_MODE": "ჩვენების ტექსტური რეჟიმი", + "VTLANG_SCREEN_GUI_MODE": "ჩვენების გრაფიკული რეჟიმი", + + "VTLANG_THEME_SELECT": "თემის არჩევა", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI დრაივერების ჩვენება", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary ხარვეზის გასწორება", + + "VTLANG_JSON_CHK_JSON": "მოდულების json კონფიგურაციის შემოწმება (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "global control მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_THEME": "theme მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_AUTOINS": "auto install მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_PERSIST": "persistence მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_MENU_ALIAS": "menu alias მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_MENU_TIP": "menu tip მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_MENU_CLASS": "menu class მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_INJECTION": "injection მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "auto memdisk მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_IMG_LIST": "image list მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_IMG_BLIST": "image blacklist მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_CONF_REPLACE": "boot conf replace მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_DUD": "dud მოდულის კონფიგურაციის შემოწმება", + "VTLANG_JSON_CHK_PASSWORD": "password მოდულის კონფიგურაციის შემოწმება", + + "VTLANG_NORMAL_MODE": "ჩატვირთვა normal რეჟიმში", + "VTLANG_WIMBOOT_MODE": "ჩატვირთვა wimboot რეჟიმში", + "VTLANG_GRUB2_MODE": "ჩატვირთვა grub2 რეჟიმში", + "VTLANG_MEMDISK_MODE": "ჩატვირთვა memdisk რეჟიმში", + + "VTLANG_RET_TO_LISTVIEW": "სიის ხედის დაბრუნება", + "VTLANG_RET_TO_TREEVIEW": "ხის ხედის დაბრუნება", + + "VTLANG_NO_AUTOINS_SCRIPT": "ჩატვირთვა ავტომატური ინსტალაციის სკრიპტის გარეშე", + "VTLANG_AUTOINS_USE": "ჩატვირთვა ავტომატური ინსტალაციის რეჟიმში", + + "VTLANG_NO_PERSIST": "ჩატვირთვა ცვლილებების შენახვის რეჟიმის გარეშე", + "VTLANG_PERSIST_USE": "ჩატვირთვა ცვლილებების შენახვის რეჟიმში", + + "VTLANG_BROWER_RETURN": "დაბრუნება", + + "VTLANG_ENTER_EXIT": "გასასვლელად დააჭირეთ Enter ღილაკს", + "VTLANG_ENTER_REBOOT": "დააჭირეთ Enter ღილაკს გადატვირთვისთვის", + "VTLANG_ENTER_CONTINUE": "გასაგრძელებლად დააჭირეთ Enter ღილაკს", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/ko_KR.json b/src/grub2/grub/menu/ko_KR.json new file mode 100644 index 0000000..e2620ef --- /dev/null +++ b/src/grub2/grub/menu/ko_KR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Korean (한국어)", + + "VTLANG_STR_HOTKEY_LIST": " L:언어 F1:도움말 F2:찾아보기 F3:목록 보기 F4:로컬 부팅 F5:도구 F6:확장 메뉴", + "VTLANG_STR_HOTKEY_TREE": " L:언어 F1:도움말 F2:찾아보기 F3:트리 보기 F4:로컬 부팅 F5:도구 F6:확장 메뉴", + "VTLANG_RETURN_PREVIOUS": "이전 메뉴로 돌아가기 [Esc]", + "VTLANG_RETURN_PRV_NOESC": "이전 메뉴로 돌아가기", + + "VTLANG_MENU_LANG": "메뉴 언어 선택", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows 검색 및 부팅", + "VTLANG_LB_SBOOT_G4D": "Grub4dos 검색 및 부팅", + "VTLANG_LB_SBOOT_HDD1": "첫 번째 로컬 디스크 부팅", + "VTLANG_LB_SBOOT_HDD2": "두 번째 로컬 디스크 부팅", + "VTLANG_LB_SBOOT_HDD3": "세 번째 로컬 디스크 부팅", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI 검색 및 부팅", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI 검색 및 부팅", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI 검색 및 부팅", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot 검색 및 부팅", + + "VTLANG_FILE_CHKSUM": "파일 체크섬", + "VTLANG_CHKSUM_MD5_CALC": "md5 검사값 계산", + "VTLANG_CHKSUM_SHA1_CALC": "sha1 검사값 계산", + "VTLANG_CHKSUM_SHA256_CALC": "sha256 검사값 계산", + "VTLANG_CHKSUM_SHA512_CALC": "sha512 검사값 계산", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5 검사값 계산 및 확인", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1 검사값 계산 및 확인", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256 검사값 계산 및 확인", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512 검사값 계산 및 확인", + + "VTLANG_POWER": "전원", + "VTLANG_POWER_REBOOT": "다시 시작", + "VTLANG_POWER_HALT": "전원 끄기", + "VTLANG_POWER_BOOT_EFIFW": "UEFI 설정으로 다시 시작", + + "VTLANG_KEYBRD_LAYOUT": "키보드 레이아웃", + "VTLANG_HWINFO": "하드웨어 정보", + + "VTLANG_RESOLUTION_CFG": "해상도 구성", + "VTLANG_SCREEN_MODE": "화면 표시 모드", + "VTLANG_SCREEN_TEXT_MODE": "강제 텍스트 모드", + "VTLANG_SCREEN_GUI_MODE": "강제 그래픽 모드", + + "VTLANG_THEME_SELECT": "테마 선택", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI 유틸리티", + "VTLANG_UTIL_SHOW_EFI_DRV": "UEFI 드라이버 표시", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows 초기화 라이브러리 오류 복구", + + "VTLANG_JSON_CHK_JSON": "플러그인 파일 구성 확인 (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "전역 제어 플러그인 구성 확인", + "VTLANG_JSON_CHK_THEME": "테마 플러그인 구성 확인", + "VTLANG_JSON_CHK_AUTOINS": "자동 설치 플러그인 구성 확인", + "VTLANG_JSON_CHK_PERSIST": "영구화 플러그인 구성 확인", + "VTLANG_JSON_CHK_MENU_ALIAS": "메뉴 별칭 플러그인 구성 확인", + "VTLANG_JSON_CHK_MENU_TIP": "메뉴 팁 플러그인 구성 확인", + "VTLANG_JSON_CHK_MENU_CLASS": "메뉴 클래스 플러그인 구성 확인", + "VTLANG_JSON_CHK_INJECTION": "주입 플러그인 구성 확인", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "자동 메모리 디스크 플러그인 구성 확인", + "VTLANG_JSON_CHK_IMG_LIST": "이미지 목록 플러그인 구성 확인", + "VTLANG_JSON_CHK_IMG_BLIST": "이미지 블랙리스트 플러그인 구성 확인", + "VTLANG_JSON_CHK_CONF_REPLACE": "부팅 구성 대체 플러그인 구성 확인", + "VTLANG_JSON_CHK_DUD": "드라이버 업데이트 디스크 플러그인 구성 확인", + "VTLANG_JSON_CHK_PASSWORD": "암호 플러그인 구성 확인", + + "VTLANG_NORMAL_MODE": "일반 모드로 부팅", + "VTLANG_WIMBOOT_MODE": "wimboot 모드로 부팅", + "VTLANG_GRUB2_MODE": "grub2 모드로 부팅", + "VTLANG_MEMDISK_MODE": "메모리 디스크 모드로 부팅", + + "VTLANG_RET_TO_LISTVIEW": "목록보기로 돌아가기", + "VTLANG_RET_TO_TREEVIEW": "트리보기로 돌아가기", + + "VTLANG_NO_AUTOINS_SCRIPT": "자동 설치 스크립트 사용 안 함", + "VTLANG_AUTOINS_USE": "부팅 대상", + + "VTLANG_NO_PERSIST": "영구화된 데이터 파일 사용 안 함", + "VTLANG_PERSIST_USE": "부팅 대상", + + "VTLANG_BROWER_RETURN": "돌아가기", + + "VTLANG_ENTER_EXIT": "종료하려면 Enter 키를 누르십시오", + "VTLANG_ENTER_REBOOT": "다시 시작하려면 Enter 키를 누르십시오", + "VTLANG_ENTER_CONTINUE": "계속하려면 Enter 키를 누르십시오", + + "VTLANG_CTRL_TEMP_SET": "임시 제어 설정", + "VTLANG_WIN11_BYPASS_CHECK": "Windows 11 설치 시 CPU/TPM/SecureBoot 검사 회피", + "VTLANG_WIN11_BYPASS_NRO": "Windows 11 설치 시 온라인 계정 요구 사항 무시", + "VTLANG_LINUX_REMOUNT": "Linux 부팅 후 Hiperiso 파티션 마운트", + "VTLANG_SECONDARY_BOOT_MENU": "보조 부팅 메뉴 표시", + "VTLANG_WIN_UEFI_RES_LOCK": "UEFI 부팅 시 Windows/WinPE 해상도 고정", + "VTLANG_UEFI_RES_LOCK_NONE": "고정 안 함", + "VTLANG_UEFI_RES_LOCK_MAX": "최고 해상도로 고정", + "VTLANG_UEFI_RES_LOCK_1024_768": "1024 x 768로 고정", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "1024 x 768 이상으로 고정", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/lg_UG.json b/src/grub2/grub/menu/lg_UG.json new file mode 100644 index 0000000..7721712 --- /dev/null +++ b/src/grub2/grub/menu/lg_UG.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "English (English)", + + "VTLANG_STR_HOTKEY_LIST": "L:Language F1:Help F2:Browse F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Language F1:Help F2:Browse F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Return to previous menu [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Return to previous menu", + + "VTLANG_MENU_LANG": "Menu Language Select", + + "VTLANG_LB_SBOOT_WINDOWS": "Search and boot Windows", + "VTLANG_LB_SBOOT_G4D": "Search and boot Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Boot the 1st local disk", + "VTLANG_LB_SBOOT_HDD2": "Boot the 2nd local disk", + "VTLANG_LB_SBOOT_HDD3": "Boot the 3rd local disk", + "VTLANG_LB_SBOOT_X64EFI": "Search and boot BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Search and boot BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Search and boot BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Search and boot xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Calculate md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calculate sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calculate sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calculate sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calculate and check md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calculate and check sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calculate and check sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calculate and check sha512sum", + + "VTLANG_POWER": "Power", + "VTLANG_POWER_REBOOT": "Reboot", + "VTLANG_POWER_HALT": "Halt", + "VTLANG_POWER_BOOT_EFIFW": "Reboot to EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Keyboard Layouts", + "VTLANG_HWINFO": "Hardware Information", + + "VTLANG_RESOLUTION_CFG": "Resolution Configuration", + "VTLANG_SCREEN_MODE": "Screen Display Mode", + "VTLANG_SCREEN_TEXT_MODE": "Force Text Mode", + "VTLANG_SCREEN_GUI_MODE": "Force Graphics Mode", + + "VTLANG_THEME_SELECT": "Theme Select", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "Show EFI Drivers", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Fixup Windows BlinitializeLibrary Failure", + + "VTLANG_JSON_CHK_JSON": "Check plugin json configuration (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Check global control plugin configuration", + "VTLANG_JSON_CHK_THEME": "Check theme plugin configuration", + "VTLANG_JSON_CHK_AUTOINS": "Check auto install plugin configuration", + "VTLANG_JSON_CHK_PERSIST": "Check persistence plugin configuration", + "VTLANG_JSON_CHK_MENU_ALIAS": "Check menu alias plugin configuration", + "VTLANG_JSON_CHK_MENU_TIP": "Check menu tip plugin configuration", + "VTLANG_JSON_CHK_MENU_CLASS": "Check menu class plugin configuration", + "VTLANG_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Check auto memdisk plugin configuration", + "VTLANG_JSON_CHK_IMG_LIST": "Check image list plugin configuration", + "VTLANG_JSON_CHK_IMG_BLIST": "Check image blacklist plugin configuration", + "VTLANG_JSON_CHK_CONF_REPLACE": "Check boot conf replace plugin configuration", + "VTLANG_JSON_CHK_DUD": "Check dud plugin configuration", + "VTLANG_JSON_CHK_PASSWORD": "Check password plugin configuration", + + "VTLANG_NORMAL_MODE": "Boot in normal mode", + "VTLANG_WIMBOOT_MODE": "Boot in wimboot mode", + "VTLANG_GRUB2_MODE": "Boot in grub2 mode", + "VTLANG_MEMDISK_MODE": "Boot in memdisk mode", + + "VTLANG_RET_TO_LISTVIEW": "Return to ListView", + "VTLANG_RET_TO_TREEVIEW": "Return to TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Boot without auto installation template", + "VTLANG_AUTOINS_USE": "Boot with", + + "VTLANG_NO_PERSIST": "Boot without persistence", + "VTLANG_PERSIST_USE": "Boot with", + + "VTLANG_BROWER_RETURN": "Return", + + "VTLANG_ENTER_EXIT": "press Enter key to exit", + "VTLANG_ENTER_REBOOT": "press Enter key to reboot", + "VTLANG_ENTER_CONTINUE": "press Enter key to continue", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/pl_PL.json b/src/grub2/grub/menu/pl_PL.json new file mode 100644 index 0000000..caf692e --- /dev/null +++ b/src/grub2/grub/menu/pl_PL.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Polish (Poland)", + + "VTLANG_STR_HOTKEY_LIST": "L:Język F1:Pomoc F2:Przeglądaj F3:Widok listy F4:Localboot F5:Narzędzia F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Język F1:Pomoc F2:Przeglądaj F3:Widok drzewa F4:Localboot F5:Narzędzia F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Powrót do poprzedniego menu [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Powrót do poprzedniego menu", + + "VTLANG_MENU_LANG": "Wybierz język menu", + + "VTLANG_LB_SBOOT_WINDOWS": "Wyszukaj i uruchom Windows", + "VTLANG_LB_SBOOT_G4D": "Wyszukaj i uruchom Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Uruchom pierwszy dysk lokalny", + "VTLANG_LB_SBOOT_HDD2": "Uruchom drugi dysk lokalny", + "VTLANG_LB_SBOOT_HDD3": "Uruchom trzeci dysk lokalny", + "VTLANG_LB_SBOOT_X64EFI": "Wyszukaj i uruchom BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Wyszukaj i uruchom BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Wyszukaj i uruchom BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Wyszukaj i uruchom xorboot", + + "VTLANG_FILE_CHKSUM": "Suma kontrolna pliku", + "VTLANG_CHKSUM_MD5_CALC": "Oblicz sumę md5", + "VTLANG_CHKSUM_SHA1_CALC": "Oblicz sumę sha1", + "VTLANG_CHKSUM_SHA256_CALC": "Oblicz sumę sha256", + "VTLANG_CHKSUM_SHA512_CALC": "Oblicz sumę sha512", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Oblicz i sprawdź sumę md5", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Oblicz i sprawdź sumę sha1", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Oblicz i sprawdź sumę sha256", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Oblicz i sprawdź sumę sha512", + + "VTLANG_POWER": "Opcje zasilania", + "VTLANG_POWER_REBOOT": "Uruchom ponownie", + "VTLANG_POWER_HALT": "Zakończ", + "VTLANG_POWER_BOOT_EFIFW": "Uruchom ponownie i przejdź do konfiguracji EFI", + + "VTLANG_KEYBRD_LAYOUT": "Układy klawiatury", + "VTLANG_HWINFO": "Informacje o konfiguracji sprzętowej", + + "VTLANG_RESOLUTION_CFG": "Konfiguracja rozdzielczości", + "VTLANG_SCREEN_MODE": "Tryb wyświetlania ekranu", + "VTLANG_SCREEN_TEXT_MODE": "Wymuś tryb tekstowy", + "VTLANG_SCREEN_GUI_MODE": "Wymuś tryb graficzny", + + "VTLANG_THEME_SELECT": "Wybierz motyw", + + "VTLANG_UEFI_UTIL": "Narzędzia Hiperiso UEFI", + "VTLANG_UTIL_SHOW_EFI_DRV": "Pokaż sterowniki EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Napraw błąd BlinitializeLibrary systemu Windows", + + "VTLANG_JSON_CHK_JSON": "Sprawdź konfigurację pluginu json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Sprawdź konfigurację pluginu Global Control", + "VTLANG_JSON_CHK_THEME": "Sprawdź konfigurację pluginu Theme", + "VTLANG_JSON_CHK_AUTOINS": "Sprawdź konfigurację pluginu Auto Installation", + "VTLANG_JSON_CHK_PERSIST": "Sprawdź konfigurację pluginu Persistence", + "VTLANG_JSON_CHK_MENU_ALIAS": "Sprawdź konfigurację pluginu Menu Alias", + "VTLANG_JSON_CHK_MENU_TIP": "Sprawdź konfigurację pluginu Menu Tip", + "VTLANG_JSON_CHK_MENU_CLASS": "Sprawdź konfigurację pluginu Menu Class", + "VTLANG_JSON_CHK_INJECTION": "Sprawdź konfigurację pluginu Injection", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Sprawdź konfigurację pluginu Auto Memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Sprawdź konfigurację pluginu Image List", + "VTLANG_JSON_CHK_IMG_BLIST": "Sprawdź konfigurację pluginu Blacklist dla obrazów", + "VTLANG_JSON_CHK_CONF_REPLACE": "Sprawdź konfigurację pluginu Boot Conf Replace", + "VTLANG_JSON_CHK_DUD": "Sprawdź konfigurację pluginu DUD (Driver Update Disk)", + "VTLANG_JSON_CHK_PASSWORD": "Sprawdź konfigurację pluginu Password", + + "VTLANG_NORMAL_MODE": "Uruchom w trybie normalnym", + "VTLANG_WIMBOOT_MODE": "Uruchom w trybie Wimboot", + "VTLANG_GRUB2_MODE": "Uruchom w trybie grub2", + "VTLANG_MEMDISK_MODE": "Uruchom w trybie memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Powrót do widoku listy", + "VTLANG_RET_TO_TREEVIEW": "Powrót do widoku drzewa", + + "VTLANG_NO_AUTOINS_SCRIPT": "Uruchom bez szablonu automatycznej instalacji", + "VTLANG_AUTOINS_USE": "Uruchom z", + + "VTLANG_NO_PERSIST": "Uruchom bez persistence (zapisywania ustawień)", + "VTLANG_PERSIST_USE": "Uruchom z", + + "VTLANG_BROWER_RETURN": "Powrót", + + "VTLANG_ENTER_EXIT": "naciśnij klawisz Enter, aby wyjść", + "VTLANG_ENTER_REBOOT": "naciśnij klawisz Enter, aby ponownie uruchomić", + "VTLANG_ENTER_CONTINUE": "naciśnij klawisz Enter, aby kontynuować", + + "VTLANG_CTRL_TEMP_SET": "Tymczasowe ustawienia kontroli", + "VTLANG_WIN11_BYPASS_CHECK": "Pominięcie sprawdzania CPU/TPM/SecureBoot podczas instalacji Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Pominięcie wymogu posiadania konta Microsoft podczas instalacji Windows 11", + "VTLANG_LINUX_REMOUNT": "Zamontuj partycję Hiperiso po uruchomieniu Linuksa", + "VTLANG_SECONDARY_BOOT_MENU": "Pokaż dodatkowe menu rozruchowe (boot menu)", + "VTLANG_WIN_UEFI_RES_LOCK": "Zablokuj rozdzielczość podczas bootowania UEFI Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "Brak", + "VTLANG_UEFI_RES_LOCK_MAX": "Najwyższa", + "VTLANG_UEFI_RES_LOCK_1024_768": "Stała 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "Co najmniej 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/pt_BR.json b/src/grub2/grub/menu/pt_BR.json new file mode 100644 index 0000000..db9c107 --- /dev/null +++ b/src/grub2/grub/menu/pt_BR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Brazilian Portuguese (Português Brasileiro)", + + "VTLANG_STR_HOTKEY_LIST": "L:Idioma F1:Ajuda F2:Explorar F3:Visualização em Lista F4:Inicialização Local F5:Ferramentas F6:Sair", + "VTLANG_STR_HOTKEY_TREE": "L:Idioma F1:Ajuda F2:Explorar F3:Visualização em Árvore F4:Inicialização Local F5:Ferramentas F6:Sair", + "VTLANG_RETURN_PREVIOUS": "Retornar ao menu anterior [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Retornar ao menu anterior", + + "VTLANG_MENU_LANG": "Menu de Seleção dos Idiomas", + + "VTLANG_LB_SBOOT_WINDOWS": "Procurar e iniciar o Windows", + "VTLANG_LB_SBOOT_G4D": "Procurar e iniciar o Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Iniciar o 1º disco local", + "VTLANG_LB_SBOOT_HDD2": "Iniciar o 2º disco local", + "VTLANG_LB_SBOOT_HDD3": "Iniciar o 3º disco local", + "VTLANG_LB_SBOOT_X64EFI": "Procurar e iniciar o BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Procurar e iniciar o BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Procurar e iniciar o BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Procurar e iniciar o xorboot", + + "VTLANG_FILE_CHKSUM": "Checksum do arquivo", + "VTLANG_CHKSUM_MD5_CALC": "Calcular o md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calcular o sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calcular o sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calcular o sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calcular e verificar o md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calcular e verificar o sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calcular e verificar o sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calcular e verificar o sha512sum", + + "VTLANG_POWER": "Energia", + "VTLANG_POWER_REBOOT": "Reiniciar", + "VTLANG_POWER_HALT": "Desligar", + "VTLANG_POWER_BOOT_EFIFW": "Reiniciar com a configuração do EFI", + + "VTLANG_KEYBRD_LAYOUT": "Esquemas do Teclado", + "VTLANG_HWINFO": "Informações do Hardware", + + "VTLANG_RESOLUTION_CFG": "Configuração da Resolução", + "VTLANG_SCREEN_MODE": "Modo de Exibição da Tela", + "VTLANG_SCREEN_TEXT_MODE": "Forçar o Modo Texto", + "VTLANG_SCREEN_GUI_MODE": "Forçar o Modo Gráfico", + + "VTLANG_THEME_SELECT": "Seleção de Tema", + + "VTLANG_UEFI_UTIL": "Utilitários UEFI do Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Mostrar os Drivers EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Consertar a Falha BlinitializeLibrary do Windows", + + "VTLANG_JSON_CHK_JSON": "Verificar a configuração do plugin json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Verificar a configuração do plugin de controle global", + "VTLANG_JSON_CHK_THEME": "Verificar a configuração do plugin dos temas", + "VTLANG_JSON_CHK_AUTOINS": "Verificar a configuração do plugin de instalação automática", + "VTLANG_JSON_CHK_PERSIST": "Verificar a configuração do plugin de persistência", + "VTLANG_JSON_CHK_MENU_ALIAS": "Verificar a configuração do plugin do menu alias", + "VTLANG_JSON_CHK_MENU_TIP": "Verificar a configuração do plugin do menu das dicas", + "VTLANG_JSON_CHK_MENU_CLASS": "Verificar a configuração do plugin do menu classe", + "VTLANG_JSON_CHK_INJECTION": "Verificar a configuração do plugin de injeção", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Verificar a configuração do plugin automático do memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Verificar a configuração do plugin da lista de imagens", + "VTLANG_JSON_CHK_IMG_BLIST": "Verificar a configuração do plugin da lista negra de imagens", + "VTLANG_JSON_CHK_CONF_REPLACE": "Verificar a configuração do plugin de substituição da configuração de inicialização", + "VTLANG_JSON_CHK_DUD": "Verificar a configuração do plugin dud", + "VTLANG_JSON_CHK_PASSWORD": "Verificar a configuração do plugin das senhas", + + "VTLANG_NORMAL_MODE": "Iniciar no modo normal", + "VTLANG_WIMBOOT_MODE": "Iniciar no modo wimboot", + "VTLANG_GRUB2_MODE": "Iniciar no modo grub2", + "VTLANG_MEMDISK_MODE": "Iniciar no modo memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Retornar pra Visualização em Lista", + "VTLANG_RET_TO_TREEVIEW": "Retornar para Visualização em Árvore", + + "VTLANG_NO_AUTOINS_SCRIPT": "Iniciar sem modelo de instalação automática", + "VTLANG_AUTOINS_USE": "Iniciar com", + + "VTLANG_NO_PERSIST": "Iniciar sem persistência", + "VTLANG_PERSIST_USE": "Iniciar com", + + "VTLANG_BROWER_RETURN": "Retornar", + + "VTLANG_ENTER_EXIT": "Pressione a tecla Enter pra sair", + "VTLANG_ENTER_REBOOT": "Pressione a tecla Enter pra reiniciar", + "VTLANG_ENTER_CONTINUE": "Pressione a tecla Enter pra continuar", + + "VTLANG_CTRL_TEMP_SET": "Configurações do Controle Temporário", + "VTLANG_WIN11_BYPASS_CHECK": "Ignorar a verificação da CPU/TPM/SecureBoot quando instalar o Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Ignorar o requerimento de conta online quanto instalar o Windows 11", + "VTLANG_LINUX_REMOUNT": "Montar a partição do Hiperiso após iniciar o Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Mostrar o menu secundário da inicialização", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/pt_PT.json b/src/grub2/grub/menu/pt_PT.json new file mode 100644 index 0000000..5d26a71 --- /dev/null +++ b/src/grub2/grub/menu/pt_PT.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Portuguese (Português de Portugal)", + + "VTLANG_STR_HOTKEY_LIST": "L:Idioma F1:Ajuda F2:Navegar F3:Estrutura F4:Arranque local F5:Ferramentas F6:Sair", + "VTLANG_STR_HOTKEY_TREE": "L:Idioma F1:Ajuda F2:Navegar F3:Estrutura F4:Arranque local F5:Ferramentas F6:Sair", + "VTLANG_RETURN_PREVIOUS": "Voltar ao menu anterior [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Voltar ao menu anterior", + + "VTLANG_MENU_LANG": "Seleção de idioma do menu", + + "VTLANG_LB_SBOOT_WINDOWS": "Pesquisar e iniciar o Windows", + "VTLANG_LB_SBOOT_G4D": "Pesquisar e iniciar o Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Arrancar o 1º disco local", + "VTLANG_LB_SBOOT_HDD2": "Arrancar o 2º disco local", + "VTLANG_LB_SBOOT_HDD3": "Arrancar o 3º disco local", + "VTLANG_LB_SBOOT_X64EFI": "Pesquisar e iniciar o BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Pesquisar e iniciar o BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Pesquisar e iniciar o BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Pesquisar e iniciar o xorboot", + + "VTLANG_FILE_CHKSUM": "Checksum do ficheiro", + "VTLANG_CHKSUM_MD5_CALC": "Calcular MD5", + "VTLANG_CHKSUM_SHA1_CALC": "Calcular SHA1", + "VTLANG_CHKSUM_SHA256_CALC": "Calcular SHA256", + "VTLANG_CHKSUM_SHA512_CALC": "Calcular SHA512", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calcular e verificar MD5", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calcular e verificar SHA1", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calcular e verificar SHA256", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calcular e verificar SHA512", + + "VTLANG_POWER": "Energia", + "VTLANG_POWER_REBOOT": "Reiniciar", + "VTLANG_POWER_HALT": "Desligar", + "VTLANG_POWER_BOOT_EFIFW": "Reiniciar com a configuração EFI", + + "VTLANG_KEYBRD_LAYOUT": "Esquemas de teclado", + "VTLANG_HWINFO": "Informação do hardware", + + "VTLANG_RESOLUTION_CFG": "Configuração da resolução", + "VTLANG_SCREEN_MODE": "Modo de exibição", + "VTLANG_SCREEN_TEXT_MODE": "Modo texto", + "VTLANG_SCREEN_GUI_MODE": "Modo gráfico", + + "VTLANG_THEME_SELECT": "Seleção de tema", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "Mostrar controladores EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Corrigir falha BlinitializeLibrary do Windows", + + "VTLANG_JSON_CHK_JSON": "Verificar configuração do plugin json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Verificar a configuração do plugin de controlo global", + "VTLANG_JSON_CHK_THEME": "Verificar configuração do plugin do tema", + "VTLANG_JSON_CHK_AUTOINS": "Verificar a configuração do plugin de instalação automática", + "VTLANG_JSON_CHK_PERSIST": "Verificar a configuração do plugin de persistência", + "VTLANG_JSON_CHK_MENU_ALIAS": "Verificar a configuração do plugin do menu alias", + "VTLANG_JSON_CHK_MENU_TIP": "Verificar a configuração do plugin do menu de dica", + "VTLANG_JSON_CHK_MENU_CLASS": "Verificar a configuração do plugin do menu classe", + "VTLANG_JSON_CHK_INJECTION": "Verificar a configuração do plugin de injeção", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Verificar a configuração do plugin automático do memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Verificar configuração do plugin da lista de imagens", + "VTLANG_JSON_CHK_IMG_BLIST": "Verificar configuração do plugin da lista negra de imagens", + "VTLANG_JSON_CHK_CONF_REPLACE": "Verificar a configuração do plugin de substituição de conf. de arranque", + "VTLANG_JSON_CHK_DUD": "Verificar configuração do plugin dud", + "VTLANG_JSON_CHK_PASSWORD": "Verificar configuração do plugin palavra-passe", + + "VTLANG_NORMAL_MODE": "Arrancar no modo normal", + "VTLANG_WIMBOOT_MODE": "Arrancar no modo wimboot", + "VTLANG_GRUB2_MODE": "Arrancar no modo grub2", + "VTLANG_MEMDISK_MODE": "Arrancar no modo memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Voltar para Lista", + "VTLANG_RET_TO_TREEVIEW": "Voltar para Estrutura", + + "VTLANG_NO_AUTOINS_SCRIPT": "Arrancar sem modelo de instalação automática", + "VTLANG_AUTOINS_USE": "Arrancar com", + + "VTLANG_NO_PERSIST": "Arrancar sem persistência", + "VTLANG_PERSIST_USE": "Arrancar com", + + "VTLANG_BROWER_RETURN": "Voltar", + + "VTLANG_ENTER_EXIT": "pressione a tecla Enter para sair", + "VTLANG_ENTER_REBOOT": "pressione a tecla Enter para reiniciar", + "VTLANG_ENTER_CONTINUE": "pressione a tecla Enter para continuar", + + "VTLANG_CTRL_TEMP_SET": "Configurações de Controle Temporário", + "VTLANG_WIN11_BYPASS_CHECK": "Ignorar checagem de CPU/TPM/SecureBoot quando instalando Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Ignorar requerimento de conta online quanto instalando Windows 11", + "VTLANG_LINUX_REMOUNT": "Montar partição Hiperiso após boot do Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Mostar menu seundário de boot", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/ru_RU.json b/src/grub2/grub/menu/ru_RU.json new file mode 100644 index 0000000..afa6f74 --- /dev/null +++ b/src/grub2/grub/menu/ru_RU.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Russian (Русский)", + + "VTLANG_STR_HOTKEY_LIST": "L:Язык F1:Помощь F2:Обзор F3:ВидСписок F4:ЛокалЗагрузка F5:Сервис F6:РасширМеню", + "VTLANG_STR_HOTKEY_TREE": "L:Язык F1:Помощь F2:Обзор F3:ВидДерево F4:ЛокалЗагрузка F5:Сервис F6:РасширМеню", + "VTLANG_RETURN_PREVIOUS": "Вернуться в предыдущее меню [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Вернуться в предыдущее меню", + + "VTLANG_MENU_LANG": "Выбор языка меню", + + "VTLANG_LB_SBOOT_WINDOWS": "Найти и загрузить Windows", + "VTLANG_LB_SBOOT_G4D": "Найти и загрузить Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Загрузить 1-й локальный диск", + "VTLANG_LB_SBOOT_HDD2": "Загрузить 2-й локальный диск", + "VTLANG_LB_SBOOT_HDD3": "Загрузить 3-й локальный диск", + "VTLANG_LB_SBOOT_X64EFI": "Найти и загрузить OOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Найти и загрузить BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Найти и загрузить BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Найти и загрузить xorboot", + + "VTLANG_FILE_CHKSUM": "Контрольная сумма файла", + "VTLANG_CHKSUM_MD5_CALC": "Вычислить md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Вычислить sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Вычислить sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Вычислить sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Вычислить и проверить md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Вычислить и проверить sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Вычислить и проверить sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Вычислить и проверить sha512sum", + + "VTLANG_POWER": "Питание", + "VTLANG_POWER_REBOOT": "Перезагрузить", + "VTLANG_POWER_HALT": "Завершить работу", + "VTLANG_POWER_BOOT_EFIFW": "Перезагрузиться в настройку EFI", + + "VTLANG_KEYBRD_LAYOUT": "Раскладки клавиатуры", + "VTLANG_HWINFO": "Сведения об оборудовании", + + "VTLANG_RESOLUTION_CFG": "Конфигурация разрешения", + "VTLANG_SCREEN_MODE": "Режим отображения экрана", + "VTLANG_SCREEN_TEXT_MODE": "Выбрать текстовый режим", + "VTLANG_SCREEN_GUI_MODE": "Выбрать графический режим", + + "VTLANG_THEME_SELECT": "Выбор темы", + + "VTLANG_UEFI_UTIL": "Утилиты UEFI Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Показать драйверы EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Исправить ошибку Windows «BlinitializeLibrary»", + + "VTLANG_JSON_CHK_JSON": "Проверить настройки расширения «json» (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Проверить настройки расширения «global control»", + "VTLANG_JSON_CHK_THEME": "Проверить настройки расширения «theme»", + "VTLANG_JSON_CHK_AUTOINS": "Проверить настройки расширения «auto install»", + "VTLANG_JSON_CHK_PERSIST": "Проверить настройки расширения «persistence»", + "VTLANG_JSON_CHK_MENU_ALIAS": "Проверить настройки расширения «menu alias»", + "VTLANG_JSON_CHK_MENU_TIP": "Проверить настройки расширения «menu tip»", + "VTLANG_JSON_CHK_MENU_CLASS": "Проверить настройки расширения «menu class»", + "VTLANG_JSON_CHK_INJECTION": "Проверить настройки расширения «injection»", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Проверить настройки расширения «auto memdisk»", + "VTLANG_JSON_CHK_IMG_LIST": "Проверить настройки расширения «image list»", + "VTLANG_JSON_CHK_IMG_BLIST": "Проверить настройки расширения «image blacklist»", + "VTLANG_JSON_CHK_CONF_REPLACE": "Проверить настройки расширения «boot conf replace»", + "VTLANG_JSON_CHK_DUD": "Проверить настройки расширения «dud»", + "VTLANG_JSON_CHK_PASSWORD": "Проверить настройки расширения «password»", + + "VTLANG_NORMAL_MODE": "Загрузиться в обычном режиме", + "VTLANG_WIMBOOT_MODE": "Загрузиться в режиме wimboot", + "VTLANG_GRUB2_MODE": "Загрузиться в режиме grub2", + "VTLANG_MEMDISK_MODE": "Загрузиться в режиме memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Вернуться к Виду списком", + "VTLANG_RET_TO_TREEVIEW": "Вернуться к Виду древом", + + "VTLANG_NO_AUTOINS_SCRIPT": "Загрузка без шаблона автоматической установки", + "VTLANG_AUTOINS_USE": "Загрузиться с", + + "VTLANG_NO_PERSIST": "Загрузка без сохраняемости", + "VTLANG_PERSIST_USE": "Загрузиться с", + + "VTLANG_BROWER_RETURN": "Вернуться", + + "VTLANG_ENTER_EXIT": "нажмите клавишу ввода, чтобы выйти", + "VTLANG_ENTER_REBOOT": "нажмите клавишу ввода для перезагрузки", + "VTLANG_ENTER_CONTINUE": "нажмите клавишу ввода, чтобы продолжить", + + "VTLANG_CTRL_TEMP_SET": "Настройки временного управления", + "VTLANG_WIN11_BYPASS_CHECK": "Обойти проверку CPU/TPM/SecureBoot при установке Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Обойти требование сетевой учётной записи при установке Windows 11", + "VTLANG_LINUX_REMOUNT": "Смонтировать раздел Hiperiso после загрузки Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Показать вторичное загрузочное меню", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/sl_si.json b/src/grub2/grub/menu/sl_si.json new file mode 100644 index 0000000..7d9a0f6 --- /dev/null +++ b/src/grub2/grub/menu/sl_si.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Slovenija (Slovenski)", + + "VTLANG_STR_HOTKEY_LIST": "L:Jezik F1:Pomoč F2:Prebrskaj F3:ListView F4:Localboot F5:Orodja F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Jezik F1:Pomoč F2:Prebrskaj F3:TreeView F4:Localboot F5:Orodja F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Vrnitev v prejšnji meni [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Vrnitev v prejšnji meni", + + "VTLANG_MENU_LANG": "Izbira jezika menija", + + "VTLANG_LB_SBOOT_WINDOWS": "Iskanje in zagon sistema Windows", + "VTLANG_LB_SBOOT_G4D": "Iskanje in zagon Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Zagon 1. lokalnega diska", + "VTLANG_LB_SBOOT_HDD2": "Zagon 2. lokalnega diska", + "VTLANG_LB_SBOOT_HDD3": "Zagon 3. lokalnega diska", + "VTLANG_LB_SBOOT_X64EFI": "Iskanje in zagon BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Iskanje in zagon BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Iskanje in zagon BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Iskanje in zagon xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Izračunaj md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Izračunaj sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Izračunaj sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Izračunaj sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Izračunaj in preveri md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Izračunaj in preveri sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Izračunaj in preveri sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Izračunaj in preveri sha512sum", + + "VTLANG_POWER": "Napajanje", + "VTLANG_POWER_REBOOT": "Ponovni zagon", + "VTLANG_POWER_HALT": "Halt", + "VTLANG_POWER_BOOT_EFIFW": "Ponovni zagon v nastavitev EFI", + + "VTLANG_KEYBRD_LAYOUT": "Postavitev tipkovnice", + "VTLANG_HWINFO": "Informacije o strojni opremi", + + "VTLANG_RESOLUTION_CFG": "Nastavitev ločljivosti", + "VTLANG_SCREEN_MODE": "Način prikaza na zaslonu", + "VTLANG_SCREEN_TEXT_MODE": "Vsili besedilni način", + "VTLANG_SCREEN_GUI_MODE": "Vsili grafični način", + + "VTLANG_THEME_SELECT": "Izbira teme", + + "VTLANG_UEFI_UTIL": "Pripomočki Hiperiso UEFI", + "VTLANG_UTIL_SHOW_EFI_DRV": "Prikaži gonilnike EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Popravek napake Windows BlinitializeLibrary", + + "VTLANG_JSON_CHK_JSON": "Preverite konfiguracijo vtičnika json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Preverite konfiguracijo globalnega nadzornega vtičnika", + "VTLANG_JSON_CHK_THEME": "Preverite konfiguracijo vtičnika teme", + "VTLANG_JSON_CHK_AUTOINS": "Preverite konfiguracijo vtičnika za samodejno namestitev", + "VTLANG_JSON_CHK_PERSIST": "Preverite konfiguracijo vtičnika persistence", + "VTLANG_JSON_CHK_MENU_ALIAS": "Preverite konfiguracijo vtičnika menija", + "VTLANG_JSON_CHK_MENU_TIP": "Preverite konfiguracijo vtičnika za nasvete menija", + "VTLANG_JSON_CHK_MENU_CLASS": "Preverite konfiguracijo vtičnika razreda menija", + "VTLANG_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Preverite konfiguracijo vtičnika Auto Memdisk.", + "VTLANG_JSON_CHK_IMG_LIST": "Preverite konfiguracijo vtičnika za seznam slik", + "VTLANG_JSON_CHK_IMG_BLIST": "Preverite konfiguracijo vtičnika za črno listo slik", + "VTLANG_JSON_CHK_CONF_REPLACE": "Preverite boot conf zamenjajte plugin konfiguracijo", + "VTLANG_JSON_CHK_DUD": "Preverite konfiguracijo vtičnika dud", + "VTLANG_JSON_CHK_PASSWORD": "Preverite konfiguracijo vtičnika za geslo", + + "VTLANG_NORMAL_MODE": "Zagon v običajnem načinu", + "VTLANG_WIMBOOT_MODE": "Zagon v načinu wimboot", + "VTLANG_GRUB2_MODE": "Zagon v načinu grub2", + "VTLANG_MEMDISK_MODE": "Zagon v načinu memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Vrnitev na ListView", + "VTLANG_RET_TO_TREEVIEW": "Vrnitev v TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Zagon brez predloge za samodejno namestitev", + "VTLANG_AUTOINS_USE": "Zagon z", + + "VTLANG_NO_PERSIST": "Boot without persistence", + "VTLANG_PERSIST_USE": "Zagon z", + + "VTLANG_BROWER_RETURN": "Nazaj", + + "VTLANG_ENTER_EXIT": "za izhod pritisnite tipko Enter", + "VTLANG_ENTER_REBOOT": "pritisnite tipko Enter za ponovni zagon", + "VTLANG_ENTER_CONTINUE": "za nadaljevanje pritisnite tipko Enter", + + "VTLANG_CTRL_TEMP_SET": "Začasne nadzorne nastavitve", + "VTLANG_WIN11_BYPASS_CHECK": "Obid preverjanja CPU/TPM/SecureBoot pri namestitvi sistema Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Obid zahteve po spletnem računu pri namestitvi sistema Windows 11", + "VTLANG_LINUX_REMOUNT": "Priklopi Hiperiso particijo po zagonu Linuxa", + "VTLANG_SECONDARY_BOOT_MENU": "Prikaz sekundarnega zagonskega menija", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/sr_RS.json b/src/grub2/grub/menu/sr_RS.json new file mode 100644 index 0000000..8c987e0 --- /dev/null +++ b/src/grub2/grub/menu/sr_RS.json @@ -0,0 +1,99 @@ + + "VTLANG_LANGUAGE_NAME": "Serbian Latin (Srpski)", + + "VTLANG_STR_HOTKEY_LIST": "L:Језик F1:Help F2:Browse F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Језик F1:Help F2:Browse F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Return to previous menu [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Return to previous menu", + + "VTLANG_MENU_LANG": "Menu Language Select", + + "VTLANG_LB_SBOOT_WINDOWS": "Search and boot Windows", + "VTLANG_LB_SBOOT_G4D": "Search and boot Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Boot the 1st local disk", + "VTLANG_LB_SBOOT_HDD2": "Boot the 2nd local disk", + "VTLANG_LB_SBOOT_HDD3": "Boot the 3rd local disk", + "VTLANG_LB_SBOOT_X64EFI": "Search and boot BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Search and boot BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Search and boot BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Search and boot xorboot", + + "VTLANG_FILE_CHKSUM": "File checksum", + "VTLANG_CHKSUM_MD5_CALC": "Calculate md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Calculate sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Calculate sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Calculate sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Calculate and check md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Calculate and check sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Calculate and check sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Calculate and check sha512sum", + + "VTLANG_POWER": "Power", + "VTLANG_POWER_REBOOT": "Reboot", + "VTLANG_POWER_HALT": "Halt", + "VTLANG_POWER_BOOT_EFIFW": "Reboot to EFI setup", + + "VTLANG_KEYBRD_LAYOUT": "Keyboard Layouts", + "VTLANG_HWINFO": "Hardware Information", + + "VTLANG_RESOLUTION_CFG": "Resolution Configuration", + "VTLANG_SCREEN_MODE": "Screen Display Mode", + "VTLANG_SCREEN_TEXT_MODE": "Force Text Mode", + "VTLANG_SCREEN_GUI_MODE": "Force Graphics Mode", + + "VTLANG_THEME_SELECT": "Theme Select", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "Show EFI Drivers", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Fixup Windows BlinitializeLibrary Failure", + + "VTLANG_JSON_CHK_JSON": "Check plugin json configuration (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Check global control plugin configuration", + "VTLANG_JSON_CHK_THEME": "Check theme plugin configuration", + "VTLANG_JSON_CHK_AUTOINS": "Check auto install plugin configuration", + "VTLANG_JSON_CHK_PERSIST": "Check persistence plugin configuration", + "VTLANG_JSON_CHK_MENU_ALIAS": "Check menu alias plugin configuration", + "VTLANG_JSON_CHK_MENU_TIP": "Check menu tip plugin configuration", + "VTLANG_JSON_CHK_MENU_CLASS": "Check menu class plugin configuration", + "VTLANG_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Check auto memdisk plugin configuration", + "VTLANG_JSON_CHK_IMG_LIST": "Check image list plugin configuration", + "VTLANG_JSON_CHK_IMG_BLIST": "Check image blacklist plugin configuration", + "VTLANG_JSON_CHK_CONF_REPLACE": "Check boot conf replace plugin configuration", + "VTLANG_JSON_CHK_DUD": "Check dud plugin configuration", + "VTLANG_JSON_CHK_PASSWORD": "Check password plugin configuration", + + "VTLANG_NORMAL_MODE": "Boot in normal mode", + "VTLANG_WIMBOOT_MODE": "Boot in wimboot mode", + "VTLANG_GRUB2_MODE": "Boot in grub2 mode", + "VTLANG_MEMDISK_MODE": "Boot in memdisk mode", + + "VTLANG_RET_TO_LISTVIEW": "Return to ListView", + "VTLANG_RET_TO_TREEVIEW": "Return to TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Boot without auto installation template", + "VTLANG_AUTOINS_USE": "Boot with", + + "VTLANG_NO_PERSIST": "Boot without persistence", + "VTLANG_PERSIST_USE": "Boot with", + + "VTLANG_BROWER_RETURN": "Return", + + "VTLANG_ENTER_EXIT": "press Enter key to exit", + "VTLANG_ENTER_REBOOT": "press Enter key to reboot", + "VTLANG_ENTER_CONTINUE": "press Enter key to continue", + + "VTLANG_CTRL_TEMP_SET": "Temporary Control Settings", + "VTLANG_WIN11_BYPASS_CHECK": "Bypass CPU/TPM/SecureBoot check when install Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bypass online account requirement when install Windows 11", + "VTLANG_LINUX_REMOUNT": "Mount Hiperiso partition after boot Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Show secondary boot menu", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/ta_IN.json b/src/grub2/grub/menu/ta_IN.json new file mode 100644 index 0000000..b6cb4da --- /dev/null +++ b/src/grub2/grub/menu/ta_IN.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Tamil (தமிழ்)", + + "VTLANG_STR_HOTKEY_LIST": "L:மொழி F1:உதவி F2:உலாவுக F3:பட்டியல்பார்வை F4:லோக்கல்பூட் F5:கருவிகள் F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:மொழி F1:உதவி F2:உலாவுக F3:மரப்பார்வை F4:லோக்கல்பூட் F5:கருவிகள் F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "முந்தைய பட்டியலுக்குத் திரும்பு [Esc]", + "VTLANG_RETURN_PRV_NOESC": "முந்தைய பட்டியலுக்குத் திரும்பு", + + "VTLANG_MENU_LANG": "மொழி தேர்வு பட்டியல்", + + "VTLANG_LB_SBOOT_WINDOWS": "விண்டோஸைத் தேடி துவக்கவும்", + "VTLANG_LB_SBOOT_G4D": "Grub4dos ஐத் தேடி துவக்கவும்", + "VTLANG_LB_SBOOT_HDD1": "1வது உள்ளூர் வட்டை துவக்கவும்", + "VTLANG_LB_SBOOT_HDD2": "2வது உள்ளூர் வட்டை துவக்கவும்", + "VTLANG_LB_SBOOT_HDD3": "3வது உள்ளூர் வட்டை துவக்கவும்", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI ஐத் தேடி துவக்கவும்", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI ஐத் தேடி துவக்கவும்", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI ஐத் தேடி துவக்கவும்", + "VTLANG_LB_SBOOT_XORBOOT": "xorboot ஐத் தேடி துவக்கவும்", + + "VTLANG_FILE_CHKSUM": "கோப்பு செக்சம்", + "VTLANG_CHKSUM_MD5_CALC": "md5sum ஐக் கணக்கிடவும்", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum ஐக் கணக்கிடவும்", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum ஐக் கணக்கிடவும்", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum ஐக் கணக்கிடவும்", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum ஐக் கணக்கிட்டு சரிபார்க்கவும்", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum ஐக் கணக்கிட்டு சரிபார்க்கவும்", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum ஐக் கணக்கிட்டு சரிபார்க்கவும்", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum ஐக் கணக்கிட்டு சரிபார்க்கவும்", + + "VTLANG_POWER": "பவர்", + "VTLANG_POWER_REBOOT": "மறுதொடக்கம்", + "VTLANG_POWER_HALT": "நிறுத்து", + "VTLANG_POWER_BOOT_EFIFW": "EFI அமைப்பிற்கு மீண்டும் துவக்கவும்", + + "VTLANG_KEYBRD_LAYOUT": "விசைப்பலகை தளவமைப்புகள்", + "VTLANG_HWINFO": "வன்பொருள் தகவல்", + + "VTLANG_RESOLUTION_CFG": "தீர்மானம் கட்டமைப்பு", + "VTLANG_SCREEN_MODE": "திரை காட்சி பயன்முறை", + "VTLANG_SCREEN_TEXT_MODE": "கட்டாய உரை பயன்முறை", + "VTLANG_SCREEN_GUI_MODE": "கட்டாய கிராபிக்ஸ் பயன்முறை", + + "VTLANG_THEME_SELECT": "தீம் தேர்வு", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI பயன்பாடுகள்", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI இயக்கிகளைக் காட்டு", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary தோல்வியைச் சரிசெய்தல்", + + "VTLANG_JSON_CHK_JSON": "செருகுநிரல் json உள்ளமைவைச் சரிபார்க்கவும் (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "உலகளாவிய கட்டுப்பாட்டு செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_THEME": "தீம் செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_AUTOINS": "தானாக நிறுவும் செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_PERSIST": "நிலைத்தன்மை செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_MENU_ALIAS": "பட்டியலில் மாற்று செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_MENU_TIP": "பட்டியலில் முனை செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_MENU_CLASS": "பட்டியலில் வகுப்பு செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_INJECTION": "ஊசி செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "ஆட்டோ மெம்டிஸ்க் செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_IMG_LIST": "பட பட்டியல் செருகுநிரல் உள்ளமைவை சரிபார்க்கவும்", + "VTLANG_JSON_CHK_IMG_BLIST": "படத்தின் தடுப்புப்பட்டியல் செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + "VTLANG_JSON_CHK_CONF_REPLACE": "பூட் conf சொருகி உள்ளமைவை மாற்றுவதை சரிபார்க்கவும்", + "VTLANG_JSON_CHK_DUD": "dud செருகுநிரல் உள்ளமைவை சரிபார்க்கவும்", + "VTLANG_JSON_CHK_PASSWORD": "கடவுச்சொல் செருகுநிரல் உள்ளமைவைச் சரிபார்க்கவும்", + + "VTLANG_NORMAL_MODE": "சாதாரண பயன்முறையில் துவக்கவும்", + "VTLANG_WIMBOOT_MODE": "wimboot பயன்முறையில் துவக்கவும்", + "VTLANG_GRUB2_MODE": "grub2 பயன்முறையில் துவக்கவும்", + "VTLANG_MEMDISK_MODE": "memdisk பயன்முறையில் துவக்கவும்", + + "VTLANG_RET_TO_LISTVIEW": "பட்டியல்பார்வை பக்கத்துக்குத் திரும்பு", + "VTLANG_RET_TO_TREEVIEW": "மரப்பார்வை பக்கத்துக்குத் திரும்பு", + + "VTLANG_NO_AUTOINS_SCRIPT": "தானியங்கி நிறுவல் டெம்ப்ளேட் இல்லாமல் துவக்கவும்", + "VTLANG_AUTOINS_USE": "துவக்கவும் இத்துடன்", + + "VTLANG_NO_PERSIST": "விடாமுயற்சி இல்லாமல் துவக்கவும்", + "VTLANG_PERSIST_USE": "துவக்கவும் இத்துடன்", + + "VTLANG_BROWER_RETURN": "திரும்பு", + + "VTLANG_ENTER_EXIT": "வெளியேற Enter விசையை அழுத்தவும்", + "VTLANG_ENTER_REBOOT": "மறுதொடக்கம் செய்ய Enter விசையை அழுத்தவும்", + "VTLANG_ENTER_CONTINUE": "தொடர Enter விசையை அழுத்தவும்", + + "VTLANG_CTRL_TEMP_SET": "தற்காலிக கட்டுப்பாட்டு அமைப்புகள்", + "VTLANG_WIN11_BYPASS_CHECK": "விண்டோஸ் 11 ஐ நிறுவும் போது CPU/TPM/SecureBoot சரிபார்பை புறக்கணிக்கவும்", + "VTLANG_WIN11_BYPASS_NRO": "விண்டோஸ் 11 ஐ நிறுவும் போது ஆன்லைன் கணக்கின் தேவையை புறக்கணிக்கவும்", + "VTLANG_LINUX_REMOUNT": "லினக்ஸை துவக்கிய பிறகு Hiperiso பகிர்வை ஏற்றவும்", + "VTLANG_SECONDARY_BOOT_MENU": "இரண்டாம் நிலை துவக்க பட்டியலைக் காட்டு", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/tr_TR.json b/src/grub2/grub/menu/tr_TR.json new file mode 100644 index 0000000..a9f448d --- /dev/null +++ b/src/grub2/grub/menu/tr_TR.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Turkish (Türkçe)", + + "VTLANG_STR_HOTKEY_LIST": "L:Dil F1:Yardım F2:Gözat F3:Liste Görünümü F4:Önyükleme Seçenekleri F5:Araçlar F6:Grub2 Menü", + "VTLANG_STR_HOTKEY_TREE": "L:Dil F1:Yardım F2:Gözat F3:Ağaç Görünümü F4:Önyükleme Seçenekleri F5:Araçlar F6:Grub2 Menü", + "VTLANG_RETURN_PREVIOUS": "Önceki menüye geri dön [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Önceki menüye geri dön", + + "VTLANG_MENU_LANG": "Menü Dili Seçimi", + + "VTLANG_LB_SBOOT_WINDOWS": "Windows'u bul ve Önyükle", + "VTLANG_LB_SBOOT_G4D": "Grub4dos'u bul ve Önyükle", + "VTLANG_LB_SBOOT_HDD1": "1. Yerel diskten Önyükleme yap", + "VTLANG_LB_SBOOT_HDD2": "2. Yerel diskten Önyükleme yap", + "VTLANG_LB_SBOOT_HDD3": "3. Yerel diskten Önyükleme yap", + "VTLANG_LB_SBOOT_X64EFI": "BOOTX64.EFI'yi bul ve Önyükleme yap", + "VTLANG_LB_SBOOT_IA32EFI": "BOOTIA32.EFI'yi bul ve Önyükleme yap", + "VTLANG_LB_SBOOT_AA64EFI": "BOOTAA64.EFI'yi bul ve Önyükleme yap", + "VTLANG_LB_SBOOT_XORBOOT": "XORBOOT'u bul ve Önyükleme yap", + + "VTLANG_FILE_CHKSUM": "Dosya Doğrulama", + "VTLANG_CHKSUM_MD5_CALC": "md5sum değerini hesapla", + "VTLANG_CHKSUM_SHA1_CALC": "sha1sum değerini hesapla", + "VTLANG_CHKSUM_SHA256_CALC": "sha256sum değerini hesapla", + "VTLANG_CHKSUM_SHA512_CALC": "sha512sum değerini hesapla", + "VTLANG_CHKSUM_MD5_CALC_CHK": "md5sum hesapla ve kontrol et", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "sha1sum hesapla ve kontrol et", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "sha256sum hesapla ve kontrol et", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "sha512sum hesapla ve kontrol et", + + "VTLANG_POWER": "Güç Seçenekleri", + "VTLANG_POWER_REBOOT": "Yeniden Başlat", + "VTLANG_POWER_HALT": "Bilgisayarı Kapat", + "VTLANG_POWER_BOOT_EFIFW": "EFI BIOS Ayarları ile Yeniden Başlat", + + "VTLANG_KEYBRD_LAYOUT": "Klavye düzenleri", + "VTLANG_HWINFO": "Donanım Bilgisi", + + "VTLANG_RESOLUTION_CFG": "Çözünürlük Yapılandırması", + "VTLANG_SCREEN_MODE": "Ekran Görüntüleme Modu", + "VTLANG_SCREEN_TEXT_MODE": "Metin Modu'nu Dene", + "VTLANG_SCREEN_GUI_MODE": "Grafik Modu'nu Dene", + + "VTLANG_THEME_SELECT": "Tema Seçimi", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI Utilities", + "VTLANG_UTIL_SHOW_EFI_DRV": "EFI Sürücülerini Göster", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Windows BlinitializeLibrary Hatasını Düzelt", + + "VTLANG_JSON_CHK_JSON": "json (hiperiso.json) Yapılandırma Dosyası Ayarlarını kontrol et", + "VTLANG_JSON_CHK_CONTROL": "(Global Control Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_THEME": "(Theme Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_AUTOINS": "(Auto Install Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_PERSIST": "(Persistence Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_MENU_ALIAS": "(Menu Alias Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_MENU_TIP": "(Menu Tip Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_MENU_CLASS": "(Menu Class Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_INJECTION": "(Injection Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "(Auto Memdisk Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_IMG_LIST": "(Image List Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_IMG_BLIST": "(Image Blacklist Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_CONF_REPLACE": "(Check Boot Conf Replace Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_DUD": "(Dud Plugin) yapılandırma ayarları", + "VTLANG_JSON_CHK_PASSWORD": "(Password Plugin) yapılandırma ayarları", + + "VTLANG_NORMAL_MODE": "NORMAL(ISO) Mod'da ÖnYükleme Yap", + "VTLANG_WIMBOOT_MODE": "WIMBOOT(WIM) Mod'da Önyükleme Yap", + "VTLANG_GRUB2_MODE": "GRUB2 Mod'da Önyükleme Yap", + "VTLANG_MEMDISK_MODE": "MEMDISK Modunda ÖnYükleme Yap", + + "VTLANG_RET_TO_LISTVIEW": "Liste Görünümü Moduna Geri Dön", + "VTLANG_RET_TO_TREEVIEW": "Ağaç Görünümü Moduna Geri Dön", + + "VTLANG_NO_AUTOINS_SCRIPT": "Otomatik yükleme şablonu(autoinstalltemplate.xml) olmadan Önyükleme yap", + "VTLANG_AUTOINS_USE": "ile Önyükleme Yap", + + "VTLANG_NO_PERSIST": "Kalıcı ayar dosyası(persistence.dat) olmadan Önyükleme Yap", + "VTLANG_PERSIST_USE": "ile Önyükleme Yap", + + "VTLANG_BROWER_RETURN": "Geri Dön", + + "VTLANG_ENTER_EXIT": "çıkmak için ENTER tuşuna basın", + "VTLANG_ENTER_REBOOT": "yeniden başlatmak için ENTER'a basın", + "VTLANG_ENTER_CONTINUE": "devam etmek için ENTER'a basın", + + "VTLANG_CTRL_TEMP_SET": "Geçici Kontrol Ayarları", + "VTLANG_WIN11_BYPASS_CHECK": "Windows11'i yüklerken, TPM/CPU/RAM kontrollerini atla", + "VTLANG_WIN11_BYPASS_NRO": "Windows11'i yüklerken, çevrimiçi hesap gereksinimini(OOBE) atla", + "VTLANG_LINUX_REMOUNT": "Linux sistemi önyükledikten sonra, Hiperiso bölümünü bağla", + "VTLANG_SECONDARY_BOOT_MENU": "İkincil önyükleme menüsünü göster", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/uk_UA.json b/src/grub2/grub/menu/uk_UA.json new file mode 100644 index 0000000..c1b645d --- /dev/null +++ b/src/grub2/grub/menu/uk_UA.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Ukrainian (Українська)", + + "VTLANG_STR_HOTKEY_LIST": "L:Мова F1:Довідка F2:Перегляд F3:Вид списком F4:Локальне завантаження F5:Інструменти F6:Вийти з меню", + "VTLANG_STR_HOTKEY_TREE": "L:Мова F1:Довідка F2:Перегляд F3:Вид деревом F4:Локальне завантаження F5:Інструменти F6:Вийти з меню", + "VTLANG_RETURN_PREVIOUS": "Повернутись до попереднього меню [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Повернутись до попереднього меню", + + "VTLANG_MENU_LANG": "Мова меню", + + "VTLANG_LB_SBOOT_WINDOWS": "Знайти та завантажити Windows", + "VTLANG_LB_SBOOT_G4D": "Знайти та завантажити Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Завантажити 1-й локальний диск", + "VTLANG_LB_SBOOT_HDD2": "Завантажити 2-й локальний диск", + "VTLANG_LB_SBOOT_HDD3": "Завантажити 3-й локальний диск", + "VTLANG_LB_SBOOT_X64EFI": "Знайти та завантажити BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Знайти та завантажити BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Знайти та завантажити BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Знайти та завантажити xorboot", + + "VTLANG_FILE_CHKSUM": "Контрольна сума файлу", + "VTLANG_CHKSUM_MD5_CALC": "Розрахувати md5", + "VTLANG_CHKSUM_SHA1_CALC": "Розрахувати sha1", + "VTLANG_CHKSUM_SHA256_CALC": "Розрахувати sha256", + "VTLANG_CHKSUM_SHA512_CALC": "Розрахувати sha512", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Розрахувати та перевірити md5", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Розрахувати та перевірити sha1", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Розрахувати та перевірити sha256", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Розрахувати та перевірити sha512", + + "VTLANG_POWER": "Живлення", + "VTLANG_POWER_REBOOT": "Перезавантажити", + "VTLANG_POWER_HALT": "Завершити роботу", + "VTLANG_POWER_BOOT_EFIFW": "Перезавантажитись до налаштувань UEFI/BIOS", + + "VTLANG_KEYBRD_LAYOUT": "Розкладка клавіатури", + "VTLANG_HWINFO": "Відомості про пристрій", + + "VTLANG_RESOLUTION_CFG": "Налаштування роздільної здатності", + "VTLANG_SCREEN_MODE": "Інтерфейс користувача", + "VTLANG_SCREEN_TEXT_MODE": "Перейти до текстового інтерфейсу", + "VTLANG_SCREEN_GUI_MODE": "Перейти до графічного інтерфейсу", + + "VTLANG_THEME_SELECT": "Теми", + + "VTLANG_UEFI_UTIL": "Утиліти Hiperiso UEFI", + "VTLANG_UTIL_SHOW_EFI_DRV": "Показати драйвери EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Виправити помилку Windows 'BlinitializeLibrary Failure'", + + "VTLANG_JSON_CHK_JSON": "Перевірити налаштування плагіну 'json' (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Перевірити налаштування плагіну 'global control'", + "VTLANG_JSON_CHK_THEME": "Перевірити налаштування плагіну 'theme'", + "VTLANG_JSON_CHK_AUTOINS": "Перевірити налаштування плагіну 'auto install'", + "VTLANG_JSON_CHK_PERSIST": "Перевірити налаштування плагіну 'persistence'", + "VTLANG_JSON_CHK_MENU_ALIAS": "Перевірити налаштування плагіну 'menu alias'", + "VTLANG_JSON_CHK_MENU_TIP": "Перевірити налаштування плагіну 'menu tip'", + "VTLANG_JSON_CHK_MENU_CLASS": "Перевірити налаштування плагіну 'menu class'", + "VTLANG_JSON_CHK_INJECTION": "Перевірити налаштування плагіну 'injection'", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Перевірити налаштування плагіну 'auto memdisk'", + "VTLANG_JSON_CHK_IMG_LIST": "Перевірити налаштування плагіну 'image list'", + "VTLANG_JSON_CHK_IMG_BLIST": "Перевірити налаштування плагіну 'image blacklist plugin'", + "VTLANG_JSON_CHK_CONF_REPLACE": "Перевірити налаштування плагіну 'boot conf replace'", + "VTLANG_JSON_CHK_DUD": "Перевірити налаштування плагіну 'dud'", + "VTLANG_JSON_CHK_PASSWORD": "Перевірити налаштування плагіну 'password'", + + "VTLANG_NORMAL_MODE": "Завантажити в нормальному режимі", + "VTLANG_WIMBOOT_MODE": "Завантажити в режимі wimboot", + "VTLANG_GRUB2_MODE": "Завантажити в режимі GRUB2", + "VTLANG_MEMDISK_MODE": "Завантажити в режимі MEMDISK", + + "VTLANG_RET_TO_LISTVIEW": "Повернутись до перегляду списком", + "VTLANG_RET_TO_TREEVIEW": "Повернутись до деревовидного перегляду", + + "VTLANG_NO_AUTOINS_SCRIPT": "Завантажити без шаблону авто-інсталяції", + "VTLANG_AUTOINS_USE": "Завантажити з", + + "VTLANG_NO_PERSIST": "Завантажити без збереження", + "VTLANG_PERSIST_USE": "Завантажити з ", + + "VTLANG_BROWER_RETURN": "Повернутись", + + "VTLANG_ENTER_EXIT": "натисніть Enter для виходу", + "VTLANG_ENTER_REBOOT": "натисніть Enter для перезавантаження", + "VTLANG_ENTER_CONTINUE": "натисніть Enter для продовження", + + "VTLANG_CTRL_TEMP_SET": "Різні налаштування", + "VTLANG_WIN11_BYPASS_CHECK": "Обійти перевірку CPU/TPM/SecureBoot під час інсталяції Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Обійти вимогу онлайн-аккаунту під час інсталяції Windows 11", + "VTLANG_LINUX_REMOUNT": "Монтувати розділ Hiperiso після завантаження Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Показувати вторинне меню завантаження", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/vi_VN.json b/src/grub2/grub/menu/vi_VN.json new file mode 100644 index 0000000..e451f95 --- /dev/null +++ b/src/grub2/grub/menu/vi_VN.json @@ -0,0 +1,99 @@ +{ + "VTLANG_LANGUAGE_NAME": "Vietnamese (Tiếng Việt)", + + "VTLANG_STR_HOTKEY_LIST": "L:Ngôn ngữ F1:Trợ giúp F2:Duyệt F3:ListView F4:Khởi động cục bộ F5:Công cụ F6:ExMenu", + "VTLANG_STR_HOTKEY_TREE": "L:Ngôn ngữ F1:Trợ giúp F2:Duyệt F3:TreeView F4:Khởi động cục bộ F5:Công cụ F6:ExMenu", + "VTLANG_RETURN_PREVIOUS": "Trở về menu trước [Esc]", + "VTLANG_RETURN_PRV_NOESC": "Trở về menu trước", + + "VTLANG_MENU_LANG": "Chọn ngôn ngữ menu", + + "VTLANG_LB_SBOOT_WINDOWS": "Tìm kiếm và khởi động Windows", + "VTLANG_LB_SBOOT_G4D": "Tìm kiếm và khởi động Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "Khởi động từ ổ đĩa thứ 1 ở trên máy", + "VTLANG_LB_SBOOT_HDD2": "Khởi động từ ổ đĩa thứ 2 ở trên máy", + "VTLANG_LB_SBOOT_HDD3": "Khởi động từ ổ đĩa thứ 3 ở trên máy", + "VTLANG_LB_SBOOT_X64EFI": "Tìm kiếm và khởi động BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "Tìm kiếm và khởi động BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "Tìm kiếm và khởi động BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "Tìm kiếm và khởi động xorboot", + + "VTLANG_FILE_CHKSUM": "Checksum tệp", + "VTLANG_CHKSUM_MD5_CALC": "Tính md5sum", + "VTLANG_CHKSUM_SHA1_CALC": "Tính sha1sum", + "VTLANG_CHKSUM_SHA256_CALC": "Tính sha256sum", + "VTLANG_CHKSUM_SHA512_CALC": "Tính sha512sum", + "VTLANG_CHKSUM_MD5_CALC_CHK": "Tính và kiểm tra md5sum", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "Tính và kiểm tra sha1sum", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "Tính và kiểm tra sha256sum", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "Tính và kiểm tra sha512sum", + + "VTLANG_POWER": "Nguồn điện", + "VTLANG_POWER_REBOOT": "Khởi động lại", + "VTLANG_POWER_HALT": "Tắt máy", + "VTLANG_POWER_BOOT_EFIFW": "Khởi động lại vào cài đặt UEFI", + + "VTLANG_KEYBRD_LAYOUT": "Bố cục bàn phím", + "VTLANG_HWINFO": "Thông tin phần cứng", + + "VTLANG_RESOLUTION_CFG": "Cấu hình độ phân giải", + "VTLANG_SCREEN_MODE": "Chế độ hiển thị", + "VTLANG_SCREEN_TEXT_MODE": "Bắt buộc giao diện văn bản", + "VTLANG_SCREEN_GUI_MODE": "Bắt buộc giao diện đồ hoạ", + + "VTLANG_THEME_SELECT": "Chọn chủ đề", + + "VTLANG_UEFI_UTIL": "Các tiện ích UEFI Hiperiso", + "VTLANG_UTIL_SHOW_EFI_DRV": "Hiển thị các driver EFI", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "Sửa lỗi BlinitializeLibrary của Windows", + + "VTLANG_JSON_CHK_JSON": "Kiểm tra cấu hình plugin json (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "Kiểm tra cấu hình plugin điều khiển toàn cục", + "VTLANG_JSON_CHK_THEME": "Kiểm tra cấu hình plugin chủ đề", + "VTLANG_JSON_CHK_AUTOINS": "Kiểm tra cấu hình plugin tự động cài đặt", + "VTLANG_JSON_CHK_PERSIST": "Kiểm tra cấu hình plugin persistence", + "VTLANG_JSON_CHK_MENU_ALIAS": "Kiểm tra cấu hình plugin alias menu", + "VTLANG_JSON_CHK_MENU_TIP": "Kiểm tra cấu hình plugin tip menu", + "VTLANG_JSON_CHK_MENU_CLASS": "Kiểm tra cấu hình plugin lớp menu", + "VTLANG_JSON_CHK_INJECTION": "Kiểm tra cấu hình plugin injection", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "Kiểm tra cấu hình plugin auto memdisk", + "VTLANG_JSON_CHK_IMG_LIST": "Kiểm tra cấu hình plugin danh sách ảnh đĩa", + "VTLANG_JSON_CHK_IMG_BLIST": "Kiểm tra cấu hình plugin danh sách đen ảnh đĩa", + "VTLANG_JSON_CHK_CONF_REPLACE": "Kiểm tra cấu hình plugin boot replace conf", + "VTLANG_JSON_CHK_DUD": "Kiểm tra cấu hình plugin dud", + "VTLANG_JSON_CHK_PASSWORD": "Kiểm tra cấu hình plugin mật khẩu", + + "VTLANG_NORMAL_MODE": "Khởi động ở chế độ bình thường", + "VTLANG_WIMBOOT_MODE": "Khởi động ở chế độ wimboot", + "VTLANG_GRUB2_MODE": "Khởi động ở chế độ GRUB2", + "VTLANG_MEMDISK_MODE": "Khởi động ở chế độ memdisk", + + "VTLANG_RET_TO_LISTVIEW": "Trở về ListView", + "VTLANG_RET_TO_TREEVIEW": "Trở về TreeView", + + "VTLANG_NO_AUTOINS_SCRIPT": "Khởi động không dùng mẫu cài đặt", + "VTLANG_AUTOINS_USE": "Khởi động với", + + "VTLANG_NO_PERSIST": "Khởi động không có persistence", + "VTLANG_PERSIST_USE": "Khởi động với", + + "VTLANG_BROWER_RETURN": "Trở về", + + "VTLANG_ENTER_EXIT": "nhấn Enter để thoát", + "VTLANG_ENTER_REBOOT": "nhấn Enter để khởi động lại", + "VTLANG_ENTER_CONTINUE": "nhấn enter để tiếp tục", + + "VTLANG_CTRL_TEMP_SET": "Cài đặt điều khiển tạm", + "VTLANG_WIN11_BYPASS_CHECK": "Bỏ qua kiểm tra CPU/TPM/SecureBoot khi cài đặt Windows 11", + "VTLANG_WIN11_BYPASS_NRO": "Bỏ qua yêu cầu tài khoản trực tuyến khi cài đặt Windows 11", + "VTLANG_LINUX_REMOUNT": "Gắn phân vùng Hiperiso sau khi khởi động GNU/Linux", + "VTLANG_SECONDARY_BOOT_MENU": "Hiện menu khởi động thứ cấp`", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/zh_CN.json b/src/grub2/grub/menu/zh_CN.json new file mode 100644 index 0000000..8061f1b --- /dev/null +++ b/src/grub2/grub/menu/zh_CN.json @@ -0,0 +1,98 @@ +{ + "VTLANG_LANGUAGE_NAME": "Chinese Simplified (简体中文)", + + "VTLANG_STR_HOTKEY_LIST": "L:语言 F1:帮助 F2:本地浏览 F3:列表模式 F4:本地启动 F5:工具 F6:扩展菜单", + "VTLANG_STR_HOTKEY_TREE": "L:语言 F1:帮助 F2:本地浏览 F3:树形模式 F4:本地启动 F5:工具 F6:扩展菜单", + "VTLANG_RETURN_PREVIOUS": "返回上一级菜单 [Esc]", + "VTLANG_RETURN_PRV_NOESC": "返回上一级菜单", + + "VTLANG_MENU_LANG": "菜单语言", + + "VTLANG_LB_SBOOT_WINDOWS": "搜索并启动 Windows", + "VTLANG_LB_SBOOT_G4D": "搜索并启动 Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "启动本地硬盘1中的系统", + "VTLANG_LB_SBOOT_HDD2": "启动本地硬盘2中的系统", + "VTLANG_LB_SBOOT_HDD3": "启动本地硬盘3中的系统", + "VTLANG_LB_SBOOT_X64EFI": "搜索并启动 BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "搜索并启动 BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "搜索并启动 BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "搜索并启动 xorboot", + + "VTLANG_FILE_CHKSUM": "文件校验", + "VTLANG_CHKSUM_MD5_CALC": "计算 MD5 校验值", + "VTLANG_CHKSUM_SHA1_CALC": "计算 SHA1 校验值", + "VTLANG_CHKSUM_SHA256_CALC": "计算 SHA256 校验值", + "VTLANG_CHKSUM_SHA512_CALC": "计算 SHA512 校验值", + "VTLANG_CHKSUM_MD5_CALC_CHK": "计算并检查 MD5 校验值", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "计算并检查 SHA1 校验值", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "计算并检查 SHA256 校验值", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "计算并检查 SHA512 校验值", + + "VTLANG_POWER": "电源", + "VTLANG_POWER_REBOOT": "重启", + "VTLANG_POWER_HALT": "关机", + "VTLANG_POWER_BOOT_EFIFW": "重启进入 UEFI 设置菜单", + + "VTLANG_KEYBRD_LAYOUT": "键盘布局", + "VTLANG_HWINFO": "硬件信息", + + "VTLANG_RESOLUTION_CFG": "屏幕分辨率", + "VTLANG_SCREEN_MODE": "显示模式", + "VTLANG_SCREEN_TEXT_MODE": "文本模式", + "VTLANG_SCREEN_GUI_MODE": "图形模式", + + "VTLANG_THEME_SELECT": "主题选择", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI 工具", + "VTLANG_UTIL_SHOW_EFI_DRV": "显示 UEFI 驱动", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "修复 Windows BlinitializeLibrary 错误", + + "VTLANG_JSON_CHK_JSON": "检查插件配置文件 (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "配置检查 —— 全局控制插件", + "VTLANG_JSON_CHK_THEME": "配置检查 —— 主题插件", + "VTLANG_JSON_CHK_AUTOINS": "配置检查 —— 自动安装插件", + "VTLANG_JSON_CHK_PERSIST": "配置检查 —— 持久化插件", + "VTLANG_JSON_CHK_MENU_ALIAS": "配置检查 —— 菜单别名插件", + "VTLANG_JSON_CHK_MENU_TIP": "配置检查 —— 菜单提示插件", + "VTLANG_JSON_CHK_MENU_CLASS": "配置检查 —— 菜单类型插件", + "VTLANG_JSON_CHK_INJECTION": "配置检查 —— 文件注入插件", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "配置检查 —— 自动内存盘模式插件", + "VTLANG_JSON_CHK_IMG_LIST": "配置检查 —— 文件列表插件(白名单)", + "VTLANG_JSON_CHK_IMG_BLIST": "配置检查 —— 文件列表插件(黑名单)", + "VTLANG_JSON_CHK_CONF_REPLACE": "配置检查 —— 启动配置替换插件", + "VTLANG_JSON_CHK_DUD": "配置检查 —— Driver Update Disk插件", + "VTLANG_JSON_CHK_PASSWORD": "配置检查 —— 密码插件", + + "VTLANG_NORMAL_MODE": "以正常模式启动", + "VTLANG_WIMBOOT_MODE": "以 wimboot 模式启动", + "VTLANG_GRUB2_MODE": "以 grub2 模式启动", + "VTLANG_MEMDISK_MODE": "以内存盘模式启动", + + "VTLANG_RET_TO_LISTVIEW": "返回到列表模式", + "VTLANG_RET_TO_TREEVIEW": "返回到树形模式", + + "VTLANG_NO_AUTOINS_SCRIPT": "不使用自动安装脚本", + "VTLANG_AUTOINS_USE": "使用", + + "VTLANG_NO_PERSIST": "不使用持久化数据文件", + "VTLANG_PERSIST_USE": "使用", + + "VTLANG_BROWER_RETURN": "返回", + + "VTLANG_ENTER_EXIT": "按回车键退出", + "VTLANG_ENTER_REBOOT": "按回车键重启", + "VTLANG_ENTER_CONTINUE": "按回车键继续", + + "VTLANG_CTRL_TEMP_SET": "控制变量设置", + "VTLANG_WIN11_BYPASS_CHECK": "安装 Windows 11 时绕过 TPM/安全启动 等硬件检查", + "VTLANG_WIN11_BYPASS_NRO": "安装 Windows 11 时绕过在线账户的要求", + "VTLANG_LINUX_REMOUNT": "启动 Linux 系统后挂载 Hiperiso 分区", + "VTLANG_SECONDARY_BOOT_MENU": "显示二级启动菜单", + "VTLANG_WIN_UEFI_RES_LOCK": "UEFI启动 Windows/WinPE 时锁定分辨率", + "VTLANG_UEFI_RES_LOCK_NONE": "不锁定", + "VTLANG_UEFI_RES_LOCK_MAX": "锁定最高分辨率", + "VTLANG_UEFI_RES_LOCK_1024_768": "锁定 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "锁定 1024 x 768 及以上", + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menu/zh_TW.json b/src/grub2/grub/menu/zh_TW.json new file mode 100644 index 0000000..3343712 --- /dev/null +++ b/src/grub2/grub/menu/zh_TW.json @@ -0,0 +1,98 @@ +{ + "VTLANG_LANGUAGE_NAME": "Chinese Traditional (正體中文)", + + "VTLANG_STR_HOTKEY_LIST": "L:語言 F1:說明 F2:瀏覽 F3:清單檢視 F4:本機啟動 F5:工具 F6:附加選單", + "VTLANG_STR_HOTKEY_TREE": "L:語言 F1:說明 F2:瀏覽 F3:樹狀檢視 F4:本機啟動 F5:工具 F6:附加選單", + "VTLANG_RETURN_PREVIOUS": "返回上一層選單 [Esc]", + "VTLANG_RETURN_PRV_NOESC": "返回上一層選單", + + "VTLANG_MENU_LANG": "選單語言", + + "VTLANG_LB_SBOOT_WINDOWS": "搜尋並啟動 Windows", + "VTLANG_LB_SBOOT_G4D": "搜尋並啟動 Grub4dos", + "VTLANG_LB_SBOOT_HDD1": "啟動本機硬碟1中的系統", + "VTLANG_LB_SBOOT_HDD2": "啟動本機硬碟2中的系統", + "VTLANG_LB_SBOOT_HDD3": "啟動本機硬碟3中的系統", + "VTLANG_LB_SBOOT_X64EFI": "搜尋並啟動 BOOTX64.EFI", + "VTLANG_LB_SBOOT_IA32EFI": "搜尋並啟動 BOOTIA32.EFI", + "VTLANG_LB_SBOOT_AA64EFI": "搜尋並啟動 BOOTAA64.EFI", + "VTLANG_LB_SBOOT_XORBOOT": "搜尋並啟動 xorboot", + + "VTLANG_FILE_CHKSUM": "校驗檔案", + "VTLANG_CHKSUM_MD5_CALC": "計算 MD5 檢查碼", + "VTLANG_CHKSUM_SHA1_CALC": "計算 SHA1 檢查碼", + "VTLANG_CHKSUM_SHA256_CALC": "計算 SHA256 檢查碼", + "VTLANG_CHKSUM_SHA512_CALC": "計算 SHA512 檢查碼", + "VTLANG_CHKSUM_MD5_CALC_CHK": "計算並檢查 MD5 檢查碼", + "VTLANG_CHKSUM_SHA1_CALC_CHK": "計算並檢查 SHA1 檢查碼", + "VTLANG_CHKSUM_SHA256_CALC_CHK": "計算並檢查 SHA256 檢查碼", + "VTLANG_CHKSUM_SHA512_CALC_CHK": "計算並檢查 SHA512 檢查碼", + + "VTLANG_POWER": "電源", + "VTLANG_POWER_REBOOT": "重新開機", + "VTLANG_POWER_HALT": "關機", + "VTLANG_POWER_BOOT_EFIFW": "重新開機進入 UEFI 設定選單", + + "VTLANG_KEYBRD_LAYOUT": "鍵盤設定", + "VTLANG_HWINFO": "硬體資訊", + + "VTLANG_RESOLUTION_CFG": "螢幕解析度", + "VTLANG_SCREEN_MODE": "顯示模式", + "VTLANG_SCREEN_TEXT_MODE": "強制文字模式", + "VTLANG_SCREEN_GUI_MODE": "強制圖形模式", + + "VTLANG_THEME_SELECT": "主題風格選擇", + + "VTLANG_UEFI_UTIL": "Hiperiso UEFI 實用程式", + "VTLANG_UTIL_SHOW_EFI_DRV": "顯示 UEFI 驅動", + "VTLANG_UTIL_FIX_BLINIT_FAIL": "修復 Windows BlinitializeLibrary 錯誤", + + "VTLANG_JSON_CHK_JSON": "檢查外掛程式設定檔 (hiperiso.json)", + "VTLANG_JSON_CHK_CONTROL": "設定檢查 —— 全域控制外掛程式", + "VTLANG_JSON_CHK_THEME": "設定檢查 —— 主題風格外掛程式", + "VTLANG_JSON_CHK_AUTOINS": "設定檢查 —— 自動安裝外掛程式", + "VTLANG_JSON_CHK_PERSIST": "設定檢查 —— 永久性外掛程式", + "VTLANG_JSON_CHK_MENU_ALIAS": "設定檢查 —— 功能表別名外掛程式", + "VTLANG_JSON_CHK_MENU_TIP": "設定檢查 —— 功能表提示外掛程式", + "VTLANG_JSON_CHK_MENU_CLASS": "設定檢查 —— 功能表分類外掛程式", + "VTLANG_JSON_CHK_INJECTION": "設定檢查 —— 檔注入外掛程式", + "VTLANG_JSON_CHK_AUTO_MEMDISK": "設定檢查 —— 自動 memdisk 模式外掛程式", + "VTLANG_JSON_CHK_IMG_LIST": "設定檢查 —— 映像檔清單外掛程式(白名單)", + "VTLANG_JSON_CHK_IMG_BLIST": "設定檢查 —— 映像檔清單外掛程式(黑名單)", + "VTLANG_JSON_CHK_CONF_REPLACE": "設定檢查 —— 啟動設定替換外掛程式", + "VTLANG_JSON_CHK_DUD": "設定檢查 —— Driver Update Disk外掛程式", + "VTLANG_JSON_CHK_PASSWORD": "設定檢查 —— 密碼外掛程式", + + "VTLANG_NORMAL_MODE": "以正常模式啟動", + "VTLANG_WIMBOOT_MODE": "以 wimboot 模式啟動", + "VTLANG_GRUB2_MODE": "以 grub2 模式啟動", + "VTLANG_MEMDISK_MODE": "以 memdisk 模式啟動", + + "VTLANG_RET_TO_LISTVIEW": "返回到清單檢視", + "VTLANG_RET_TO_TREEVIEW": "返回到樹狀檢視", + + "VTLANG_NO_AUTOINS_SCRIPT": "不使用自動安裝腳本", + "VTLANG_AUTOINS_USE": "使用", + + "VTLANG_NO_PERSIST": "不使用永久性資料檔案", + "VTLANG_PERSIST_USE": "使用", + + "VTLANG_BROWER_RETURN": "返回", + + "VTLANG_ENTER_EXIT": "按 Enter 鍵退出", + "VTLANG_ENTER_REBOOT": "按 Enter 鍵重新開機", + "VTLANG_ENTER_CONTINUE": "按 Enter 鍵繼續", + + "VTLANG_CTRL_TEMP_SET": "控制變數設定", + "VTLANG_WIN11_BYPASS_CHECK": "安裝 Windows 11 時繞過TPM/安全啟動等硬體檢查", + "VTLANG_WIN11_BYPASS_NRO": "安裝 Windows 11 時繞過登入帳戶的需求", + "VTLANG_LINUX_REMOUNT": "啟動 Linux 系統後掛載 Hiperiso 分區", + "VTLANG_SECONDARY_BOOT_MENU": "顯示次要啟動選單", + "VTLANG_WIN_UEFI_RES_LOCK": "Lock the resolution when UEFI boot Windows/WinPE", + "VTLANG_UEFI_RES_LOCK_NONE": "None", + "VTLANG_UEFI_RES_LOCK_MAX": "Highest", + "VTLANG_UEFI_RES_LOCK_1024_768": "Fixed 1024 x 768", + "VTLANG_UEFI_RES_LOCK_BE1024_768": "At least 1024 x 768", + + "MENU_STR_XXX": "" +} diff --git a/src/grub2/grub/menulang.cfg b/src/grub2/grub/menulang.cfg new file mode 100644 index 0000000..9b47ea3 --- /dev/null +++ b/src/grub2/grub/menulang.cfg @@ -0,0 +1,149 @@ +menuentry "Arabic (العربية)" --id="ar_AR" { + vt_init_menu_lang ar_AR + configfile ${prefix}/grub.cfg +} + +menuentry "Bengali (বাংলা)" --id="bn_BN" { + vt_init_menu_lang bn_BN + configfile ${prefix}/grub.cfg +} + +menuentry "Czech (Čeština)" --id="cs_CZ" { + vt_init_menu_lang cs_CZ + configfile ${prefix}/grub.cfg +} + +menuentry "German (Deutsch)" --id="de_DE" { + vt_init_menu_lang de_DE + configfile ${prefix}/grub.cfg +} + +menuentry "Greek (Ελληνικά)" --id="el_GR" { + vt_init_menu_lang el_GR + configfile ${prefix}/grub.cfg +} + +menuentry "English (English)" --id="en_US" { + vt_init_menu_lang en_US + configfile ${prefix}/grub.cfg +} + +menuentry "Spanish (Español)" --id="es_ES" { + vt_init_menu_lang es_ES + configfile ${prefix}/grub.cfg +} + +menuentry "Persian (فارسی)" --id="fa_IR" { + vt_init_menu_lang fa_IR + configfile ${prefix}/grub.cfg +} + +menuentry "French (Français)" --id="fr_FR" { + vt_init_menu_lang fr_FR + configfile ${prefix}/grub.cfg +} + +menuentry "Hindi (हिन्दी)" --id="hi_HI" { + vt_init_menu_lang hi_HI + configfile ${prefix}/grub.cfg +} + +menuentry "Croatian (Hrvatski)" --id="hr_HR" { + vt_init_menu_lang hr_HR + configfile ${prefix}/grub.cfg +} + +menuentry "Magyar (Hungarian)" --id="hu_HU" { + vt_init_menu_lang hu_HU + configfile ${prefix}/grub.cfg +} + +menuentry "Indonesian (Bahasa Indonesia)" --id="id_ID" { + vt_init_menu_lang id_ID + configfile ${prefix}/grub.cfg +} + +menuentry "Italiano (Italian)" --id="it_IT" { + vt_init_menu_lang it_IT + configfile ${prefix}/grub.cfg +} + +menuentry "Japanese (日本語)" --id="ja_JP" { + vt_init_menu_lang ja_JP + configfile ${prefix}/grub.cfg +} + +menuentry "Georgian (ქართული)" --id="ka_GE" { + vt_init_menu_lang ka_GE + configfile ${prefix}/grub.cfg +} + +menuentry "Korean (한국어)" --id="ko_KR" { + vt_init_menu_lang ko_KR + configfile ${prefix}/grub.cfg +} + +menuentry "English (English)" --id="lg_UG" { + vt_init_menu_lang lg_UG + configfile ${prefix}/grub.cfg +} + +menuentry "Polish (Poland)" --id="pl_PL" { + vt_init_menu_lang pl_PL + configfile ${prefix}/grub.cfg +} + +menuentry "Brazilian Portuguese (Português Brasileiro)" --id="pt_BR" { + vt_init_menu_lang pt_BR + configfile ${prefix}/grub.cfg +} + +menuentry "Portuguese (Português de Portugal)" --id="pt_PT" { + vt_init_menu_lang pt_PT + configfile ${prefix}/grub.cfg +} + +menuentry "Russian (Русский)" --id="ru_RU" { + vt_init_menu_lang ru_RU + configfile ${prefix}/grub.cfg +} + +menuentry "Slovenija (Slovenski)" --id="sl_si" { + vt_init_menu_lang sl_si + configfile ${prefix}/grub.cfg +} + +menuentry "Serbian Latin (Srpski)" --id="sr_RS" { + vt_init_menu_lang sr_RS + configfile ${prefix}/grub.cfg +} + +menuentry "Tamil (தமிழ்)" --id="ta_IN" { + vt_init_menu_lang ta_IN + configfile ${prefix}/grub.cfg +} + +menuentry "Turkish (Türkçe)" --id="tr_TR" { + vt_init_menu_lang tr_TR + configfile ${prefix}/grub.cfg +} + +menuentry "Ukrainian (Українська)" --id="uk_UA" { + vt_init_menu_lang uk_UA + configfile ${prefix}/grub.cfg +} + +menuentry "Vietnamese (Tiếng Việt)" --id="vi_VN" { + vt_init_menu_lang vi_VN + configfile ${prefix}/grub.cfg +} + +menuentry "Chinese Simplified (简体中文)" --id="zh_CN" { + vt_init_menu_lang zh_CN + configfile ${prefix}/grub.cfg +} + +menuentry "Chinese Traditional (正體中文)" --id="zh_TW" { + vt_init_menu_lang zh_TW + configfile ${prefix}/grub.cfg +} diff --git a/src/grub2/grub/mips64el-efi/command.lst b/src/grub2/grub/mips64el-efi/command.lst new file mode 100644 index 0000000000000000000000000000000000000000..1a5b7f83e3a1957175829b0b5e9f2d0056d8cdda GIT binary patch literal 1104 zcmV-W1h4!3H+ooF000E$*0e?f03iVu0001VFXf})3XcR1T>uprNM|#<9!Nj+Zg()P zOYTpqs)y26%O<-RnmV*q9FZv{Z`Y!METhsQp(&TTu(lfM1Ud@l$%d2(DaVj(JM-K? zdSI;JOzJS>ejmNJt+hL-U2YcQDf!h){(bOnLNUR>XF9pTD)(t43W3sb7Ch7$+U~?@FJR0?%=RBm-Td)&eu{8v`AirTS zwzTWm6T|CSD&*R6+dQ&OxN7s{ZrhH1b;BC0-i(6@shr10G&Dgrc-SQ&HutP0nRf-s zbu<9VNHXj{9QOm>B2%7|15+U^dx@BGRq4jk5<~J?9KvoNK&9pfoN&s~U=s$nq;a?y z$n-JX>ROg}U>0?)eQ2qaQj3(F&bv3`@-3HCXh3bBH~~$W=H_}K`8w% z-~^W8A&ps?`))!D3Lau<+~^!&h>?vDah9b7-n#ewg#RQnGjnJ@s;*ZzdyWC@%;KeT zZ`JK;v_v-r0aF83D6E%%lit34Jqty|vSrXQ>9tbkZ-~;W&Jttzp@hAX{quhhqdw!j z5$*7PLaBMYke`{i^@X%@MseSK1iIIJwTu``tWeM?aDg;{fSi_p|ZG$I8|I7KzQ75z=e4Zy2qx795 z*G#293*qlv#cz>IPJAUH3uWECb_ zn0^c$pR~Kk4Ku4Dd43xa?9H-%8OOeH2pBh-jaORp8DCM+PT zP}aJOK^C7LZ$9T-NIomBJsA%rqppTqzT-(HEeb_eJ{c+u6tZg$;3 zKjop0y|#jRe`eMe4o}ZB+>%q(i6(&pr{oIL9RF53TOZ9ry}K`k@7w7q2wQ-z zfaIV{)gH67yq*Rey-Zo)pD#KG|H)?bEWiT0000H2+TsnR|?Vq0jda) W6#xLMEf4Im#Ao{g000001X)@zoD#_Z literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/crypto.lst b/src/grub2/grub/mips64el-efi/crypto.lst new file mode 100644 index 0000000000000000000000000000000000000000..bd0a97c6fe74e6cd343242b32b1a8c5ee5d24729 GIT binary patch literal 424 zcmV;Z0ayP0H+ooF000E$*0e?f03iVu0001VFXf})1E&FJT>vQ(MQhLp$et@As?M9h zMhiJ)A7SZWg2V5uWvJl|@s`>N6!aP?W0VGWNB9`*%PH`)0sQ5c-0NlUiIHV{BG^`wSv8V}asZpZJ+_^%{-yrgPbb@mudMMj{ zFQwC@D&31<;P?rVn6L9FN?=l6ITn&&0URHDOWh~&qHVkLyTIush+c}BobhIbh@ zPz1)#CNdsU`#^rF@#d=_tqBNZ(LiV;AF1uzj;%#2JpcfkI~{&C8xZCI0fPgm2LJ#R S??I8V#Ao{g000001X)_UzQgnY literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/fdt.lst b/src/grub2/grub/mips64el-efi/fdt.lst new file mode 100644 index 0000000000000000000000000000000000000000..ea28d9e05f69d458ccfaf4aa985d30d366bfbc25 GIT binary patch literal 32 kcmexsUKJ6=z`*kC+7>qkAdtE5qA0)Zb1fr?!x9+<0JCTbcmMzZ literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/fs.lst b/src/grub2/grub/mips64el-efi/fs.lst new file mode 100644 index 0000000000000000000000000000000000000000..12c6c9d1b8e206e3c1c635931323b38df8f1b041 GIT binary patch literal 212 zcmV;_04x9fH+ooF000E$*0e?f03iVu0001VFXf})0NMbOT>vndtmX#zMDC?nb z`g%5@yAbxc%+@ab=t2MzhtdEnLkSs=RH*ZMB#2W$uMNC?oT2TiM@(Z@*`yif?UiHB zc#4GU8uEI&hcWTM?RISxo~DVQzn7KnjCpwe0002zWHk}347|($0j>et0RRA8*|aUO O#Ao{g000001X)@P*k5M= literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/moddep.lst b/src/grub2/grub/mips64el-efi/moddep.lst new file mode 100644 index 0000000000000000000000000000000000000000..427a4b025a462fa8c51947af3faa8bea7955501e GIT binary patch literal 1640 zcmV-u2ABE$H+ooF000E$*0e?f03iVu0001VFXf})5Ml->T>v{8NU&E;w$UC-OKqcU z+(>00*0s^6_Q>EIWlP5sf{cN=wwnjF2jm)n zN%C5S`vw*dL$(+J;1Arwu@YhvPRn;rvAjaRy=jQQ489PBTNO75(X`PrQMkNKI6)l+ z>|oD?57(4i<*;V9Mrj|6tTqtcCh`%Y^*fSBo!2~ML%bwM1_O3^xgBRJ(_#ka-}yH{ zu};7^v&s|X-ZT}#vMr?@!oGNMvBo(cQXnNwoqj2`Zg;1`g%2*d?3w*ExOg~0J9p`Z zG^uswh`9r&n?FKZ(gr2o69GE;fg+(DnT%ks#AA!9rcr%aXah^x_mgjy3*#yYrWReJ zQrE}C78ZC#LM1@STW%HK4@8LcG)J$gW_ZOUCxbu6?*I}d(^E8H$P>hBDRGS?L(EMp zO?(=GB{d2+lf~#)qlw>Eh+!Mkh~3Yk+xDzQP5D>2&F;WUl$_!$5t3?JuK22CO))o- zNfcPL;O_h^a6z8e?$}203d5kja-wZj_e&@;2TqV07&U+6eR#j8>?F1UU|y}@!=Y`U zp2M>bKGYv18(E6eSrgMU-;lTRM*GhtZ~aY@=G<`1iBP-C&cq4J6g zleq{wQ8BmoL+9xW_;R$VH@riXVeogVJ{DKpYESE$j{cn1vVF-zI)4)J^y8(Y-AC>i zpfZQ5_|_*X;Swn*aI-A9s*=d^=F&851aMS7?uLL=Xa`cNtjj-s?zJU-sO?K$3XR6K zTyGk#dqP0bX-Wx(S7gVx5BP4R=;QgO#B-RUl)E~FBNn%`plB$NLoU1M+92NR!$Pz8 z?aXBja?E?>+YB*7;^@7xxEc`yQndK%;M;|o&Wai(7%}vs)-X{tL+%Teb}Lz`P3a@5 zSvJPQQ;H*!x$&ww(X+;Z{!`|zgn(w7BG=eroPCx?)NHUw(YSQLI^F#l+*TVUeZR{> z0*vX%VraRs1Bpemvg~T%X3p4rQK%m=JFASV(UM4t_PEn%za*4N3r-uKw)sVURE4BG z4M~RsV+VgIhm+zJXz>13)t701_2T>~RmgLp!q@6UnR|8J?g}eyHaK=zEiV0KCo`7= z0lvB$*Yq$TR`7KS;8tDh-qj<}jCW)juy9=7EUMNF4%g*15yGI&K-k|D9!j1TO@sKt z;jYHW`v`84i4trkuRX=`l;p59KP&js2|@LO39{4lSGz_bx=+8sM1pgvhpJ9y-7?kV zJ`8m1V*b}h@U09HNfuN+P+3z=DWp-jwD}u59USRu#C(n9+u}(#kTAWtdMpJJnNrX6 zYYZ!xFkOwJyrfP{s3sM}k7usqW$i}L*zIGtMprFq}enPEtR3fCF@+ zUa8}Yb0k?hx4bKJ8B*xDX*J0{X81+4mY?0&|Yie*NcUG9(>dh1=Qrjf(`a64| zDf?aDbU*mEr{w(YldbSWF20-kb)~CqYjk)Y+xySCc$GlR6Lj%G!z0D9c{_%$4baAr zY(c&HDxuGRi%|o})0A?-cqtr>Gerj=mF2IglF8}+!|;0p;&ad6yak}J;T;K$CNxtZ z7`#Ao{g000001X)@TZ653Z literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/partmap.lst b/src/grub2/grub/mips64el-efi/partmap.lst new file mode 100644 index 0000000000000000000000000000000000000000..720c55e3213349a71bd192e631c77f86bfb4c897 GIT binary patch literal 124 zcmV-?0E7SiH+ooF000E$*0e?f03iVu0001VFXf})0B!(1T>v;3N~|EGB#XD|B&a{= z*a6u1XU~$MS1iuZ`l;{Mud$4Oyk0H1Pi2T}RSq^21Q0O1_p)_{ill=83b~RQ}TR7>U31zw Zp6kX8jGBT*Tm^jc+dkJaf+ScXqX1_96!!oC literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/terminal.lst b/src/grub2/grub/mips64el-efi/terminal.lst new file mode 100644 index 0000000000000000000000000000000000000000..0f853df051d21d0b1c7ab372166bf08e9ccf6492 GIT binary patch literal 104 zcmV-u0GI#$H+ooF000E$*0e?f03iVu0001VFXf})07C#PT>vzjN<+ez|E0Y^k&=@0H7w)1@f K000001X)@vAt%ZJ literal 0 HcmV?d00001 diff --git a/src/grub2/grub/mips64el-efi/video.lst b/src/grub2/grub/mips64el-efi/video.lst new file mode 100644 index 0000000000000000000000000000000000000000..ad1dbd09a4ea46d29febbb1cacd7613f954589d7 GIT binary patch literal 64 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

J!LTiMxUFJzm{kRVm~Xf0wvm=9%hC5k zrYq^_Mv0TP@r9Vh-TO_)0)^2t>a@V*l>nQx!mji-9b#?V5^>6~y$?5uoBX-k5%{Nw zh;I(tzNy0p!@^to>$tXM+n`(gB*~@+n_sU;@){M_m(f8jWOdq|mH}L$#wWMp#^B8U zmEwj6o1a&Ti~66*+Q-9oZ$EUm>^ai8kIU~2l``w}Z6r-H?MUR=R`}CgpOyojqg7IhO2 z^+;|VRasTpUt0uBfF~e6Gz#V8&)z=Ue@18`th|zld;iL=F(5F-)-oJ^`xcT3unk#w zN1rB4tww8c7Q9rC*=UaU3ru@|o)BkY&a@Xd)1&oc6#M!94-X3}Rt_CTm_Npvl|yNm z3iXgiG_va>agykbpWnksIL%Da11XP28=j}-r7#7V`5$bebP>x^oOOl?$#+cadx+~k zhyTebJ&EkqooQmo@yTU^E7LG4%{*6!_^Av`!+pjSus$NgFIW?Q$yt?XCUoI00Q_Zc@@G6djx3F`zK z80IfJ578cth!~UJ_O(%lL_$$x{`64bIsiU9%?c;h+mR24PbO!vtAQ_8>k?a(4{~T3 z9|NcH9GftX@v~sXF>^vK^yL6GD?}hO&X+1HSGsHioiJyi$xr>Qj0L_NEO^jPE+-T^yWG0GXDLtPyzSF zqs-g_J3$b*h8iK3sJeq6!CB*B8XI<@OKlZK9ljg+osx;<1RloWHnND0Gp236#S%X7 zNYe_kOq<~XucpbeM-7CDZXu6QShqeJT|BsV3}B@yirQJJ%hlxJc?Y?0k)iDQDyZR&KONVM3#l8I4z%#&YM6x*Z ztrA;qix9~W$^YO0h*O4urzoIBgV6)3O@V84(DN77zBJJRVh7Xoz-yg^#D}cVyoFTQ zhcoI0#wA=QR`LLp0)^Yx=EeZ~HTIEX{r<}r=ArC`GHwXqkenmRKNJ=T=CcIZ9wGhIT3DufMTn3N~&?wrGy*A7%_g7C7 zVLIdk{@zbghqIekU^vt|bqD${xeFvh?WN9Kp;vx=mI1C0uqSyklZp2yXtWS<-{W8A zZ)7y*w#cvHj84MiWZ|{2IwGSnbSEmCAsw3M17J7UqKUE#eegYH=6ed zAPQ|2fQOC}%ce2Z%@_~DpA^l6>(PV`ZO5R?jI<&E2Li1};GYAJXkBqsXQ54c4ah*% zL^LQN@H+qvzrAXK{S7yJb8CAJl9YigSiH+WLUR&zK2PljqsqzR&V2* z^yu!DF_IxIpiioJB)a|af`-wjA_0I3IK9b71lLX)UIb4*pV3F|(ng)45EW{@0H}y} zi`5pIJ0 z1+Y<73$*~>1BvRKlX_g<9AL^0rk0gE(jVV}lh;d!FJ(mj_@18zJNM1p zV*m2g5&#D>PGEE+P6lJhi|9;nYT{dI_k_c1-@iMoi@bR z|CA|+6{uX*jG((o1$Slvw6>WVK;>m4ao_*DT|c7Svf+u@J&xjLRKrMFGq zZcP?{;SjCX>|4$P@1nAIg^zbyPS_4Vtdamq6x@Wi^baeldDjkvW*8w^vAmt8;PF0H zJd6cu$~Pk|0u;1Ca84}>R4B#* z(idL++c@^$Qs74C+jjX<8F`>%yQi27pNNA7pJv#w#3Foebc9Jymw#o6Q|cN9CwB`< zij|s`?m+o&+K!hIu2g+I=M^Czzt;w-lDUs6g-W+zAF&$Y&lZP=v&d_;y!|r^hcPl@ zCJfNeKIIV8;lr~ljvHxgXwF@rh69P=l5htCYmcKCQdt}?l+?{yB?b^WPNhMX5rKXF zC@%6$Ta_eVxU);RYfGsgzH-#gwpI-2ol4K|{!#lh9w0yG0%gf1NyC?Ky}Fhp^ApP( z=vaD%Y%RNPBydtzp7SVz>9N_RlG~nO-Azp!IW*W7*57+On58Z2=C>5dbi{FQc6CMX zpyK<^Guik43vx&9-6f938Cyt4@^qT7XFj6I)I~o%_amS@S}d1i$s>)CJ~Sxe{@7dZ zqg1J+HKd^ar#ZH;_1)}uTto^NtJAQdv7ET`AhJOes_y#>p4LawXW>)&+SYpG;_goK z1HVdZTsQN6a3jPDUPH;F??;z%1MucF*8X9DsE4-$DgCW%2E5K25rI7zdHdqZQs}!) zo2Bpq$$~DHi@5gCb3CRNmS6zTUU(nE6Mo(p^RwT|l}Lpy?yJ{=s&ooP91_)h3uU|@ z%>Y&D>=blYwbFh`BzumErFedx{y6WyKBK5i7Tk0CxY6k?7{F0kFw2)%VY`)u+cw`m zm3gVlLL*)Qm`UM=5EB2tsr`2AFcUEFat_UMbb2Ci?FEhT(U-TuT-l`{d9LA39`4+I zipY5SLjDBa3P41XP2foIDy+P(`=tJa_Pm~x4DTntyCV(|_QXK)1+oYb9E=xZW+*L0 zB)~|qPN{Dvfx?gM@JleGHPf4C=< z(+Z;n%^R~{)%cf^(Gn1Bdgj(_<@ww9+qiY*#Xw3&8<4I(h8Mj`#tePDuYI?*Z&rBd z+6>(#uV!sbf8eXusZd#E)4erB-;#D&M@y=F<;&7R$Kl!+HF3obwf_?@d_c(_JY2>Y zpZ!3<;dGTE_S|_H)u91P2nxz-qgX4 z5f_=swU6^l;s3PxDWIvSpy!i2FLtSEV;nR^_CYL+QpfI${J=0d@M|(e?ei zXH^SWL(>Tp(CeX%L-7rSttz26@0hYP4_C$-tl@s}d$Y|<<3lQOwEO#+aa%?BBY9AP z1}2@WpC3{r4U#+%wxU~XMrL1ZwcsmGJwP$Q@*Dl^ya|8lyF!#bn@fa5u;|gnaTJu4 zgV0HHY%GhTKtOmax|1?(S%?3^*}53|4eSozp`CY$%V0zXH|WtX)NOycwYsI=+TxO}@;S$t8JWAeM%aX_ z5_hUnt|twuH8wf*R$BejgCNNCKP)YQzUJ>ut3*w$vmy=oLtShZ*3g`RiHtCht5S%; zEtC|mqR*3e56JkIi~V)=t;UtTill|gr%BpOs1f`OHAH#gCk}yF+zp(j-e8fIwRc-DHO|S}% zw=H{c!;Z@waEwpt>*o9F6ja{rK?LsAqm=(@*%WzCR`PkzHN`^ud7!A2C(TVW9=!N< zl8?Rs0*WkVbAbM0U*>Ktg5(s*`jaN}rsYOF^?Oi<-wWm{_lYw~6Li$+tqW`!oDeB9 zwoP9r$#`cjQ2*X1MJ~KeNYRV$@KO>oF=~6fc6qfq)REAR>y_aIwAp{Z$Vg~WGIWkO zE)Sh$v}FA%HwfvuHf_WyQ|DUpg&5#6knv`-@L*$g@B$FB z3Y%xX&uO9x*Zub?nGf70RW6xAx|~*joPl8($>y;Gv(>M$ilmum)px0r=FDthlCaWM zyMd90e_gEVQPJsXCY@SD%~NwdWU)swb7JU!nz^niKj zn$F2`H|IZQes!Y~9?>j0GUqP8%kQ z)X2|gjBHY@&r0UXF_A3Pqc}D!e~^I^o|GBfaoTp~1j-QDcZ2yCu*IM!z1obcDq8u^ zL-&Y=Bb%p5JWvAQ(yM9*czGLwkt1ALZtRvJ`n1IBCPe|IX?I1>+tQr%vu)r;t_MG# z`4JLLph<(5HTCa{kGL`$aW5~Pmi8@}K!m86;$GvYPB0@h*#YNg&eJ!;A@z(As=jex zKVujJ^e<~1*AtwL=^<4QT&L3{YEokDjVY&endDO$^4*xDk-f(cb7WetO!syx1-UxD zb|sKUSSvl}o+^(OtzlH;?kaC>be~H9zcG9&aW)ua1SdUh`^LJB8UfIOORNF)moMA( zJH2cc119#lU+qQJyNF3L-hYnFls;qFyP?MZF6sJNQn|_hEYE4GJteeuL;A%|agwBN zSqk;fu#U_S^_eJiCO`S7Q$pvyW%tyzO#+i_FyxBOp@tx8)Ed71@fj7MQW`;57%p%bSa^o7ygzBx{oAG+^-8Y(-5mcjSiGNosR=b z(nOpP8ph+BKI0svEs=E4$+s1h@Ivp`wSPH428hgWY0nEIe%R0`v?%aUc#E**e51!^ zt4ES`LXH}b5=_L&KuyYzKIZZ2Wv7%93GVXo>wf*jf|R36-eGnHfqGuz3vVV%d0-IK zu2#v%Rw3RZ0ZrW7hYUz59Po<_P?_Fo495ocO;de*P2iMRei?b z$iO{qqh7jKz&H5G_>4Jl?)Hwa_*oa`q*RQ4R|V>Ollkwwk0;f~p5h-Xe_e@KKn5vC z&glQ0o_jpfFBjBOvT7dFG!OdjyQXPTKSw>Ju@8jx8L?rATTR3I2Mshg=Eb25@lv*? zYgT(=$6sTk?+FqM7OWi{#Xk|jXQpXoFO0wCvfLtU{f?u!InQzeCFOAO}FwpKvDf1)l1vWH5odU9q&M3PT z2#n=Nz(fwiHG3}eJN3i~asNl6FT=<_uHt|aLGvxMM{m8x%-pv~pFJi#7@H~9TtVlS zzm)=Vgw^Q>JSWeVnVqtA?EXca)4mav^W}TBvKTKgtTvMV#`~H|4CoAl!9)Yu#li{A@ew3pCU;tBM{6qKaT5~HL+I1{eLPrcx5xI@H~9-gM9Hb#5Qz(> z7^$9n@`A{{3%|?lSK@kXf9@tg#_m;CD}h+%h2qh$F%!3J(Ia?TPESBhka)#k+xyWk zWxqN}pQg|>Y_!;arXffs#)$UDMx{ z{s@}%V=}kElxSWKWJAc6AiPPfMvtt4?qL8j)5*hu&ydEZ6%z}O$ux_0ObT$@(3fh% zlZVx;`>g>md_4`Cf~FACNcAV~;5629Mh5xAAhSfHQqGHeOWJPiyFw%Ae1ogcQ2JC2 zSe=ZE=2=qy0d7#FZbq`YNm{h$*fgft+@6S>7Ml!xY`?G_DinIibs$_+Ns}c8uX;C) zENF;cE{#fw75R!Ov>bd`ZuFC}K9?KT2|<+m=cn@`4&hUMKh>*&*L}AlIHlzqXch1C zq7R0zp~=pZ-`?)8{pUYfVT)B~#66Qv-%&!C^>F8EZT93KtEw{%t0{Q}`{+se&fp8J zXvS4AVp;@xuI=RDza%LLQvFRrZHadeZ}ks3Exe*-IU9I0K`SEs^x8Q9-raI?@>Zq# z>5uY0kWN1B;vpK0XWECH*kv}bA2hEW&e}%))lzwtk*U|c`sA}Gb2JbSl!Y45sS1&0 z1xV&qe?DLdrWq1S3l*l8{T@b|rwbA$X>yTR)U9-Qmz!?U-+w>I% z_5e#J9qtCS~E}Q%v870D*KYn7_x!zyaJG_ZJ2Q$L-_NP7Yg%D7_32 zle=DAX*^5*6*GcrQ&}mxWe{x&^B6RoY zse42bt7>O*D3mZ9&GWRDY4Sbz0RgF|DP;}$LBGq-7AUz%wbB3W2f_APFuj&x%9G*D z!mS4ou)RrLuElfXV;iTqu+&E5duQ+I--u{lq=qQTl^WZEQdn8d!bB)U#Q%(8fAp}1 zL@jWo0oDPEbp=+&oN)(3KH(b&98l0VV<@RyX~z9!7KFiet@$+!5jfMy8e04uln@06 zRQew7Hi`mVE|MMQ13Qqx239)mQ0f^;@JIu>F>l42DdBBF9q+=hTe=}8*mnCw*B;Jr zu2_gW{#mn@^0duV^sV2V(a>(O*)5mmB3vJs+xNZQv*ZlgTXFi)fo36VfJOFjCir4> z4T10LrqAKANfQ3zt)Bh6g1)0I<-3Pc9jQl41+=?b&g=BepSM!HVzzKgG3bYyRL)xU z=KZbvxA^!#@^KKAJPgDsba7Pz)!m}#eh^@q)&l6w~Gh0h$m8tM;cTZbKp3)t{J zx-=SW1wwLw<9p|hFXTOw0=4sWVz0Gmx*nC`gC*9Srp?*Cvf;$t29bTk?U^VGaPY7a#VhjP`0yyp+(n5XzpG>V5wRm961YnZhFzNbP}k>jGMkhSVZaVr2|tnnBX^dklk-S3AZ_Ew z`F)FrI(xi~iGv-;R&FzxoxS{pkgaU3g|3N~kvY{op*Agdz#BIeGJH>L(axOCmNb_o zZV@xCj-t+4ok+WBof1vbmT}uOSV#Xh2w+Ka?QC`Y#hrE6UQLzK8R(F(_m zzHV(&`+4_%w(Q{Xxb~nX6hhh zYAWAnjiif?>UHb7>@OPw!qn6wwgA?|k|u6Y)`KKu!QxbL+S^pf6Fv*KK*6NSE3&pT zd*sIsjs1Ps+2OAsk8!30nhL0M*&96(6M!oLTaMH9JkM>16~{ zL}$z9cV2i*pvcM}7t$pm&<}z=)gL z@e?vtx%&AURsZe@NtY43+6O24`{$TUS8@53q=ACj zo*r|6DkK;|2yajj_sTdmYqEK}|HV(01$4V!`ijG~#~7yfWNL=?H<6_albg?i&#VB7 ziREvib+T!aHg4eCnS8kf?BnD5=PdNG8bf*xU{rT-4LTyYJbH*@0p10zylDJ+G#dye zJ(qV4JqdY``=GK1_r}DlzXX2ZmpW}xWQQmInx5W$pq{dwn0@(sJsN^7fFeXT*a(Wb zPR+ENT@iH*V3Sk8W63A0+gbV*QryiNxp7VL>NWn(cli%X)8OnU{>}`)rrTBJ_I!B5 z$RfjY!$dBF(y*`GInUg_Kx3*Xr9O?;xPd9>YR4u$0sogknP}B?D(8n=7kL>u^^qeT zCa(K>b@Xn@4;M{84NI~ZsCyGWx>TB!_%K8n_Qq!fUly`v5{n;4Ld?8G>=#1Iu3^>5 zA^chlDCIOiCNDDZ-H;7$M0(dP@gqkXk^PXp%c=L?!p}JjbP+dxdB2c3((yU-ZyC%h z_nfrRjnOAR#;%sCFH>@Xe2rF=`Icg;*7R#|xLuwfS8xSB#b-4Kumsjbno}04wX`H> zF~qJt4Qt{y(+U>zjXtbxURmIp4P+XhYCPw+YgEHKH{brVS^f4zEGG zIGl+Jp_4>eWiLMi9`@t_2PdEt%+boyrRAAob{8~!!u=#WjpKzZA8?dooZESVg1xo* z!_XQOoW3~iWg^3G=SBQ++nH}!kpg1yfoC85`C9V{2Riu|Z|?kz6O-e>MZUrvXb5?E zlD7KOpR|k(XQutPDGeeYmvsqjLx&m7iS?X7Fr*nA$xCuPbk>3ijBVEjof1Mn;4U~8 z!i}~|8N95++m{YMUZdOoZu9+}0)yMJA%G1dtQqrC`L|&4+UJq87S(HSFSymyH?~V( zvU%*xvTw#Um=_v5SKKX}35FHI6MhPfPTVnx+5$-iDuG8;L)J?opf zIW+?e{yM>KxMDe`jMxw&e-!Me>0M+^{c*xDi#Ri@2=_TiAhgzgN2iM>wJ@rHQR-#F zK7N_!;^0e8mCD^I%i}=kvMh)U>~36gVRG2D2XdgQxwt~<>3>`_fqU6J3-~& z?iRZR7J*BKS%U>i|7Ya>tKh+HwcND*d1ed)6J`KNnbxG)L|EuOwOkpj#-8#~@7@$u zW-@%;b(R@~N3c$QRCn9d;Fi)B1Ei}e=cE(=qTm3v(qsT5JQ@EfPRanbt;Kt%ke1Ct zVX#uew-)m`bOLwQoWs7P0_P8B+aKpWpSvD6?ZvqvZTSwY7%VrPAy*nvw&fK26D`Hs zj1d;@8-_ldS^Bp7{0lE7vgQ>R5DT@4L}~)+ZZsJP&;!!Imq{_#|5L&79TZ*R9<$#p z%!*rS=@N6XFZ%B5{V~Q+_k8weADJ@>Z?6o=&dWKMScy?y&9w)JF^4xTaG4c7K2A5Y zl(nAHCp28>ce>Zt`g*2`CvlEyi{-xkn&+)Xs_w013YW0rPiq^NgBx2Hl4jA}Zt7)r z0zc)x&C&f7_l_UgfIYWQpRKaKPOys4v5j6tPrk@MuZ4C}A$ZCP%lO+1CM!NXD(mH6 z^Csc-SXjjQkfkd6tFkr=u?06uG~xBqXDdy%j#Uf8R7+s&29ACC`^>+vCj!4$?1Q2q7(*`(R90Sso0@K6l7bN^zMZPAStF4Ok9P{aO6Y? zrO!2pbS~%he9ucxug_!eCIbCm;?seRG&m(?-N{KM$G0%9q+?@OrxF(Pbp82(v$cw) z)f@i?KTtPHG<0|T0bfs$P$!Lz+2{R7pT!Gy@lszf#9@BKu8r5pbl@_pyuu(I%1E`z z368rD^LoMli1!F4+7dmfgFxQ?QIv-H(njHKfNV59t}V#oqxVI=T*v%P=*mGMfwkNrkjh)U1IDfeA%-K!rrO$N$3X^^OV}A9`YXTJxF_EfE3U%& z7br>)Y~-HpQtCBUl@K-Odw+xEZ+){I*AOOcS(=+7_Vn-mml|62yZ~(Gl+YJ-SqMUs z09{J;bF?c6XdAXR_(=EWh#b|(}kN3z26Ins3R$@Vxw+K z`3ktQ?)BRSi6#Iz?36J)6)B{asQV7vq&c#nY_D9oEs3@G91?$^VT>Q}_Dug(Ki~vD zRs_4elcD=EIK~|U9=U^%`cvo3%|e-m|KsSaADVjqHhyo67}BADl!W9* zTImf%N=j;=z)(a&x_bu<1ZhD)fuVGpbPPpNKtNDYsVSYKb8OGP&p)tV&d#~-_w~N6 z*Cn{eoZNX9ZFfLUx+!W*a<9}dE}ibf1RguIbeXmc#XbD?g!%Y;z$tCAR(Q9H0p7=?uC-qb8s>J$7 z>m@JL*q3P~wuL_uGW)^(aXi5Gm~#8{)N`|S;rxgW4_sF)a`3{ZgeCr>E?N4%x?hg` z3bw9K&prHp6S|p?yEyHXhxRUkAcPSyO=%?`l1b=91XK#rW&o8dlZ~x{)Oa z)ERaOQ3glX&!t7tlcL5IstP}BHtlNb%5vKnLq1Wwcijp57a|I@;6zUERR)1K#%7w= z6om*jEe<5~)oW7vtHu0(8^%qobimkcF=d?uOU)TJ9y1wa%ALk zL_|)t{43t{P)~d{eelio=X7C&>_W%7)7MJ%^)u3np{ zv_+oo*2WLhw5j%cg>-8JZ)>ciD^#&vjdQhH`+FY8Nn<*rl{N@t3jW2s&`a}!aT$C& zJY$jS4k8-Ot@x!m(@Tz=CR<5CY8Od+hw|~MF*bx~H!V2=)kIUT)P5ng^znY!mQWGq z8`WKMLk@v%G-W&tp(N8bS^n8}L#x$vxx7tlVp}TfDDitb?x-E4Tu=XwQBqCKrD0K- ziS1nOGwD{a+n)E0^G?~uSbb72_`nQeyPyxJ%Wg z>?jOwP?$uSI~JLsnfpU=VYaXm7n4$!f|MV_>g^{YZKo@JO-*Tq0PA5g6_#-)kVJi` zcMrMZw1j%RGEFhWeFY31)4F2k#P~}}?|Pcnl-^s6+n%Bx;c#0R+z!Ssoh|VQzNbTr zT&c+LcBGg9DF-X9Mg-(6KQ|d%LbxQ{^w~SwIcIAe7M?;l`=QnM_8hfE!Iv8}*Kd2X&(OV9Y z5PkSLiNg+qQ?aX{B6{Mx}GcOn`zEenL6V0`O$;40b zFG+H@OSIzocQs%aNf1BB-Z*Kyl`a=EABOnI;xf27SubqJn6Aa&F5=Gk$9+rgW&6$U z#*2YXPYoNFD|Lm|N3&=V_38?;O2z@Lck+5e-ww?SZ|m~x$rYly?emB)y3rGe60M6a z2Jn)IM17ae_@J_|2dKujc_T!{Xi6sCkBv|Xf|qmDCePBt?X0RVK&WR(6zJ{~=f!~o< zDn4aSJE{upNjEngsd~?CVtuWS>O1&GFk@k+HrV{R)Pyj|U`**JeFq^XNr^T3k$p2$ zk+AED$)hIr^tFd>V98-|!H+WM_em3XJc>J>`yb<1BWAC4DrQRxw<+br(#p zqzd*BRe{()Ye;hMX?WpCP?myO!j754YcgR%pO;^}FFkN6HYLVtLDm`k|E=pf3l?C| z7dq+Ci|X6CW7DefXz`zk!2ikXJ0c-pq&{20Ar1A!<7u63G;`uBqbq{L3{Y z|9^BrJ=?MsPk8Q!Da!H62JbT9WP0ZxiJ64LC%Jny6wZvwl*HU*!j>ycg zpEOU`^H0GKS2b$${R28%B1JQRiYK-g_nnCa2_d$1G)p;^Fl;VGcjMCL_QcDlq(bH} zQWOc&Uj7%JjC!$Y1g+S`>>$_pJwACkcp}w^c=%L>D7h8!O=rGOx_mVjsnThFA&#BK+b}GT@9W3c;S>3!XVgI#y z_n4*V=l3{wacV(Z>`Bkg$bJ=i0!wnee&58%tiyWyYlZmR7OdCJ*sq@vznuhgR#{{3 zi92E?`2Z2g=x-Mk-A)XGFVNDT8)L3hoxi1|&THe^=`!VFZY5c@3asBC%bbPyPC%e2 zveqj7??hVIi^xS6hqot;?u}Ub)73b`>oX}B&TVs8(NZtZy~R%oKXwNL5=#8@Jrg(a za;FRO0|IZVxrCkzgJRiBG7&VvS2rZuVkqrS!V$kKKM0S_;MNb)|(3%X|^oGI9~ zPowQr#5XOJ0g*aLB@a$PEClMWlWXj|#o@R8<(&@W@2>bInLs_473iYNTw|1A>+;B= zqT>g{8=`asV67%gO<06t(k#hjf>Ej21=Sw`(pkr zBQhy#Q)E`xO8>Oaf~4sJ-HMbkxq+s@3{=am(U@;V&g0D~UYwmz4C2FST%m z_w+A;;63)iH@cG(XWl(+(X2v}!Euwk!4m-2TkJ? zHMcIq(J`#iMarki1Zm{RrHGH04u5e1L2wvYC|8RBn(}a*Cb_x`-+SmefceoJ2CZf6 z>H}$D=8}C7`ZTCKWI+zZAfh__>_GY(Uk7NA3~k~T3GJ2X|LuU~9a#qIr@ zBKy%OhUD^!L$B?&zAn7ayli@Bps5UV2fXSr8QX5484;cN3hQLJ7p8{CFWVg)Fvs#j zp`1tjNFsC1+lkTf(KiVF?AE~`>sh`o?X|0I?0PF=ON(W7648%e^yxUPQ@TTq0eNW} zJ2kt!)uu`8ghTZuTRQ3cmH{T+l;YZck!*k4$Q)YSO!`AuBmn7bywFW%rJB^mmzn2` zTy*Y;Sk$%++d0t&=H>1b)M**?-^x4_xaHLe8M=X2g{dFSV2U>2D`FhYk3yrw$PZ`e z+UT0J_TBk!#^VeQVdNbY+2S{FZGS4V(g_~?xlBl5o@0fzWo zo?B8y$LDwv67v2v>Q92BW0Py)MM>jlHTGDt4Cpk$E8|#o-`8&oN#z1FX^z_r#1PKi z!OmaKXyusQ13N4Ivfe1sC)(aDvs}_9gg<)osshpZR3Y{AiA~%czIRvON9y&ghIgwhUE!yqOsij)l!hwo)#w>E=r>bY%gsz z>+4>g)eyZx%%KKgWfIy|&Y1QPR&C~qz4sAyLfS_SvO^@%Ca-#Tp!4OFQ<#A+(Vj^H z)4yJ4vae<7H2ZQeaLj$IWTyR*f0@z2(yNl=da(OjnRk6Hkg{W62qU&&ZTWOAA++DH z)sLE*baKh;No(VzK#2sJaR~GIL6Sd#x~M*^TYW68@!klfOJgwTOvacbb4g?%%+J<; zS?y zzWZ{d#3tezaE2}yPRzuyuMmZMcDmFV2!eqz`b)4$*r&Xn!M4~Z3Ue_vr75piV(+RF z?vZR5(`laDl@lfq>Uabt#QhMM;tq0f8lS8dUM)Bec?F?9M49 z6r8MGzNhK>fDO8pz8l>=(ugr>eDv8Z`%(vUa9xE!=z5q)#wWk*578SMy{Y|WDfd-x zLJF;ap_U?OUAlcT7&D;d(~}}@<%@(>W934=Z*K~jv+M^{(Tb(gvI%c1%$D|A<5wNt zj*Z>kY0ka8?mj1_JGj?)cylp}Q9`lm?cFM~0cvL(?q`AMB2&D|sTIZPU}e!f#mVC^ z4s}!afESM_^kL0mhHj4%zC$h*zcT>)>rbv@h+RzrhX34_x>}f4cC>iWCv-X;zX18$ z;#3Nm4_5Vp@&%Db*mQ`9Oj@Ed9k{ipNsF`kc%_)-i$qu*^#sfQzIE zJ;Z9Hx}*0m+$i9d_AAoYdtdE~-$$xY|zLl9tm5voV)Va8#2f&r&^5;z-r5;AL?d2Y^Uc5KM(9tR*ierC0ozp4c z>cauBxQ@%^sELN(S(QJPKkuhDbWwhbOix@<&Rjijb)qonwqhwhDV|OQ3Vm&;((``NRfi>HL7_U&-4a%N2oC>&hs{OO6)l40zwY z?gWuoMH+JZO7@}3Q_^1Z*j?sFJxL3eMI3BcucWfZgj4p++Cb{Jrla(kqv7;BA6gZsTjZHTJCDX=5 z&2*_MmlF(+)Nq|apG?s$v<)ghaTyEyHE6Pe9Edq~xLz+jnmwCo@}f1h8i5WGq($DP zGlvbSBS)U;$g&DcHRGC0f1~b9F_$tH^&CS<_AL!dTflNcB#?B`?a>S^NIudlo!*@M zi%t9z+if0>%8bV*lTJSuw#EtUcZCheI`9`7nJO~va1Z+X7_sljg|OEVPEwrU&GDev zKJxox%ORV4h(9`T=h^%t-8NQ?G0@HdfyK>p*$c_d%%S zY&vzADIESD!*tg@?rq_tqga1h_0;-G$JAWpqN7!mbIMOCE~0@bft7MW5=JC>)7KmG zD~^rw(!3Oh6VZhturk>WCjTGXyaYq*E~Zcr$Y*?6l~)3YJ)@GSN7RmkX%uCe^9DWo z{rSgtbqoFA4((684Kckx5CEbw6rL3}VSnInmvLui>B=qsDcHS@4w(I?18dHN2AIc{ z*_#`_pEUm3=b0-u#LzJM=~f3?;>Rl=9$#c7c{oZ%FKJog-7@J_-&`7_+g84R*D8!d zHCHsMM|mmKLOJdpygDL<=yD^z?Wu1%p|i|OH(Z&gvcVjzUwC-B3Wg?fC_K*>X9A9f zQ1JMh}d3m9~g!0u^H1EM_pOW zc%duHn4Wo3V6#nR00&SJjiCQ*lkq3VdwQuwjz|f~iLe3V8SsMcaWQD_q=?LiA zoVMcJb)V_H;#YIqgDic)=;yw>wi>M^Y(vz{SB1SB?L7Gg;#~H%fj`ui#xK`k#bWBk zw(3~yC1q|S?yoH~hwtvtPPvR=zY7+3i5g`dI7WhP7mcj1dwovUftV4SM$}rs{kL9= z{w}^I1Y&Dl?P)cXJysc_n9(RqUu%ui>MM0gd-`Mo@ufe~eLjJTBSdfeA;3#||$Cw89Kw7(<%+T6ZPI-itw z1@j;L>Y>th5mJf+4@@qNlMiCZQ`z5i*RNzR)2{8y4~$2`UZr9Ec=?A4n>zFQEC~4i z6ekL4QNbLpr~_rgJXnmx&?)eZ0`4^W!IP~jS z^f|n-gq79Vrtz}g``C6vOdWNpp=DOkUkVgDGgq3m<`^0}+epwQ#;rLj;;qzrCk=Vl zKg3)#WF~0;+7rKq!^{maDJm>Je65pSd9{k+(>1A?>45hg>CY07QyaM1z-PUP7S5tR zV{2g%B;CrL6`boM-h0x>bi!6rUO`Ubi1a((H_D?|xFYK24+aG9)y?E$Y0E)Lxzw0twvKlygvfO(8=x`8a=Wt0oXMS*VE#`FLHOtz*;-*KQUOd)ql`&tH6OxCvF4zgnhlx=z3;Vc$!_w@&xtt zH*IlTb+ngcxciZ2n&Hwfsd{+!5q3jk$mgoC`Nxxh(TU>lj|D2YYMJ68yWq~lFZy_3 z9z09epmU*&QV+3=NT3Fc0T6`a>~g<(Xp)YtSzkHfTiZ4+{UZ@^m)A&(xTlAa3=9&b zp=lDhhzlD0==*{+Ax~;r_c`gR7-&-!SvxU9>tWv#A{S$8C%;5bVZ1IFG=7_GI%(sc z&NRdoV$U#&lmNN`6aEtc=BCIZYs$JiXqNQiV>}WJ`YQXpR5=#YTU350w0uRq7p9zj zSD#JyIUIci|EzKWzo%iW@b#EBP?aPbyTN#WVHo1f5iUY@NIu!jl;E!1r?7rsvd-zA zsP)x6AKPX1pH;)0VlaQnz!o^i?Y=girmr(2gMwqs9BmCOVkK`p2cJ79Zli*9Z&f%_ zx_mshv0ILrC6{5eBAJ1Ee_Qrh3-eX0r>75X5v^jPWE%a<`rYi9M0ZtA*UFjL#VdOF z+3lL><5`1#L2gZB`gyOD>PKuy-K}ZIi>Xt5`pFAj8K>t29`c7vBv1? z8e10T+mToLTY-PZbjnvEBr5)ib6Z5+8>apmrv)e7&`u&F8xa!mw zSC5deq8YE9fsptHxr{QRQSnc?qkqZ;Ttz0__O@^$|IKcZBD{=K@FC;ADARkX7kT|8 z#)k-xTep6rVCOi^%GiNeKXtZ~oO6MCfTGUpF^C=}ABdhnBNXeOI@9f^{eTZyuw_r( z2){DYRQJ@P95ik9F~?r>QfyRc#RUAj7l1qraa7no0IMXbx3!`mLrn6LirJ7g7g$i= z{iLBx|KUrpB=()(r=1{MfuKW}z3~w7=_?zdlC|JUDHvKqvreiGS;u>}3RdJxc(oXQ z83{sGNiTL;x+}hDUI{Dy@6Yf*`MA_OaW+YbBd8yzw*y=>Y2GmtO=Y!t(LVI(H>|faHf$C1ZFuXy#hR~4G@}MZdWac!7+07XnrkxojK31@EbK+JlsljB zmi@fB5X&24CJTkJK5ccc7iZMm+6Yw7K-`e46wNQW$w*gQd=y%!lJ|BP(%;4MU^?@&I~@OnrhkD zp4sgikBKfUqNX3PD-+XO9*6T~zh}D$bA`2yN*|0aop>Xwu{0V#>(2^14_o?HCwhCR zp((a%5-7TPLC%I;D!~;!A>Dz15Z;Num0SXXt*E_UJFDY=W*d`w$(-xe8k$xoCUI2v zXYB9y3|k?=uI?;e6OyOBu^I~!#Mo&cl01P&5bdKUs)T-Nv8i{3Incq^LWc?ciKt1; zn^$*IVxiu}qLs~Xi@Cb=oB7Gajc|HEJ+49!mJ+{8Oz`ThTZ!&A{3MBe63QUtu}|vy)yN= z_dO;BgDCBf$v3s;a-@O!uOdet8hO|(Hd(?@`#niC%=UJHQCu})+GIu(_FJy`AMeB2 z^Md=Wf6!z9#T}arPtkNyf~m}rR||m|=3n}?#jRb)CK7LD6<$Z9m?-mpIZsE8_6->` zSFNZCmu$f^0Vj)~LHA5=NpO33$0TOxxbtbGVw7%mLksip)ZFIer>E>F$e(j344Z2b z@XpJn!36YY!6!O0v2l^e5?O`c$s6`+V1&1joIn0B~L;)=$FwkKD0!`Y?hlkV2#CSv%;6%JcaU zHx(8f|NX`xgKk91dSW6oTP9c#udK+2;n+hMN+s{VQb+V_NX!czCD#E#2|0 zZmb-e#J{*70@{-3S1fY$;T#Q_)Acv$8EIJ(*teJ&e)z$QB;z+b#N9=N5_=VB+F=Qda@Skr?)A`Q6qR_)X-3QQdw~?+1DAZ! z7jQ?FyP9Si1meoTx&=!Rpm4)pa`6tkEvOO3tytQ!!3~NF{I!hO8Uc5*wwyeq7b5w! z5XLTfZrfgKJx^i*sUAA^m(se>!3`qU*fv{Z4qrueM;lz!@O)7eStb_##CwrPLAZHz z+Ia87O1LfSx_sVSX0(nUiW6>f@+`3qLFnD(O1CiZRmmhEAL<*`H0Zs{&y*%zYqu17 zoT(%uM*HE`tJv(~DdWA7$U`je4-DN~FMbPp8Z_qR`$zGy#};uhwgW?7U{Zi@6#;JE z%XK^EcvYSu5~rI8;$saCjCm9{(`Lb0q~d{)Xf}}>{n!KmQAlBXYQMw+%oef-axc};FXUy>!=R4^bIwl+W!JvXD(P{i^=Dh1GqZ>IjM{JyESRqPWbjB8P5tHd;Qd zV!N_8H%n=zDP>xNm1r}|uBPMicKHM?iL92)Ky#mMa*rFLepy|k1c)13*8YnUU#jOG zVE4JC0IDqajk(Zz%};3iBvDu!&G8MZsCmu>Rq``a96X_;F3O_920F=Sk9F-bBh>^* zWN+Q!fYoW|-nf6Sb#jZ*#B5$##JorbHsEki`SLE_2Ykh1h6%-Ul}dJ?h=yECxVDEH zb2fY-vDo>HV(XR2yb$S}s1QaUjpKf@Dn_0lvo%SbuNA{+zAUhTS1&uBIaimCSfw$>ME!cNyA5_J|1Yk zR)E&h=Q_Ql;BM#&T~6@E^Tg5KvQ@U(nlxi4%dnz4BX&KKijuJKg*s6p?bT-srd7Ye|}G*kw(uId;|VVcc3|J=iQk8;z=DT=}tU-GWZC z3wyo8Y=g;&V%$@qNy1Bn;e}<~UB)$O%VcPDZ z&qMnE!dOzsuG;TkvDKXcT6HJ>t&}17^FbtZv-5H|h(f z0NOS%(U9IAD-c7yBmr6;l9RS$cZ5Tg%dRUp_3-m&)cG~0F?^G7EXj!rm}FW_i%Y4Fq&*9FIxh`08AJpVO?S_cPgR zHS%e$K*Sfk3z)+^2&}aNt5))AS6)UZj{2KSqA$@$EcRY~g?jCPDe;Z3t z8Y-6!QbM97%*aCxS;y6H+Hmfgv~$RpWnpLOl~YLByautbxW97?VN@13J$W8Z7)$81 za3hpeK=tnnwmSDO65B7|yqCmeaG(eGxP~Y=u!W(~^|zq;V>uXFjJ5Ah2|kmS2Mg~| z{SPX;n@kRRM!p9x5(EC7ijs7z@d2n$a|Da5iNXGX`qbamv)p!)1{E*Iqu5G#(=|Ud zG6(8#J$+GQd+TS8lLN*UyxDo|b))Peq0K?|y;qb?$@|_zG-+O-WU%1mf zFPSqjWA%@|53U_=6GQi=E)8^W+%iTE6(peOZY5fv<=l2SUirKHb%|4s3Kq0My6}Sw z2JCI;6|}y|J|(TRJ~3Qk0%l4sHo`qB&O=<;o3QG~BAU>&cG|_i7Z}OR`fAKokWHMN z@gruU%D-_=5UV5jy&aJ}@M5xFkH$iV9-l3g%@}6mTCc6U6yj`~MON!NRoqhFY&P|z z@iOB&hDn_M-kaGN=N6RQ0r`&l{-6zz^P$wmwQ>oP{!Q9@-gP*w`*}Rg11DzcPSAw$ zNHPq!@K!8>=tc!Ip#{)UE=F@T8{mUDmKMr$r%d+(;in-^APyPPcCwKG2V%@sH^ui2 zBf;4e@?CThr_dET8VR?!PZZ?(4ZMYOFvwpn&xV1dUt!B?r#Ays=vN3-Cz>DPxMxov zjN8f`a=C8ThlzKxuHXwng358hndki|R(KjyBZKm~DSUtW&|m%qGZU9s)#Qh0=!(F; zl2tv(@!dvrAl~oeN4q6Ak~5d3p3sMXJdQtF5WI_or5iPD3$j@2X9a3!rIurd%K*d- zL0D@U5)W*w<<|oY9We%){_tve5X{F_Xjwbjv&In|i?T%k?$$-ke@4f_EyPpJH2!LePCh|>}FX7I>@f{8@@k^IpK}&`37<>*aj0!vAB`mpM zV5xY(w#Mx8RE=P2@a=Mp`<7Zli>ue|)vf*(`yM1zjh_4g_oKUoJKf+gq2)0x$8L8S z^o#8jbW3G`!SQ9e`HQcU^+g!9aRzp1h-;FU{z!Zc3<0 z64O%rtJWd=2rJ3M1taP|EHk$8`FdPh5d{C}JG zO%gONPF3;TQaQ3h1{;F?gHQx?4mI4LYNNT01%mQ>jOmxYC_zZT4RpmR-~d5>xG=3n z8CgIv!O1_PaoLV}01 zG%96U;NdZT*v}7|w4#aw9p0g|SpJG|~0#8?6B)nEXt5f$EMv$3}v?=XuBB%uXjT!bCC0s@(Oc!RaX9o`kD&5vc z8@`k#9G!>O{5F;9;wh<3##i@!3wUkc%RWa-#m;pesQlYQCF<%f8&6t5<;`PRvs-TE zE*BYpB;Tv2UFzUf7H#1>v(@+FxDeYX39+{CYh`GI8fi=RGGKh@zSt?ghbP3+w?!eY z8^_Bk=)klXscgPH-gPx3Lc(6x9WKBtO@k|P(sO6YLY*=yi4De z;&A@5;chkS{xe|H#g@6ih*2sUGkls$&p+p8!@JYs{lOPT$vB7uXzQ<0w{Vm}x@4_= zMn&4AQ>DQs=&29&xyM!NMT%@#7d@Ch&%U&HLVv3T@FLXD3Z4d>T_HXWq|<>9od^3Ezu28V_5=~AOhTDRtW5DZ zt>0MrwCK;pt#KU^wwU6(+mpp23$HloPhfFv#~v>g-+0>-YB)Bn>C!^C�ktL>f@# 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 literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/menu_ne.png b/src/grub2/grub/themes/hiperiso/menu_ne.png new file mode 100644 index 0000000000000000000000000000000000000000..87578685f0736f620f9998c5465e2478b3dca478 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR42?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4x>JbJzPA}j12vXj73-8*eU~6F?hQAxvX2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR42?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR42?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4? zcvs!sLQ#34@brhXG}`aP3S4GP3Hfj>w5GPxa(NTy`epg^?dA9W+FHI>l!4*@xi!D$ z+SX5hSGRuF@im*(85s(ugx1E}mfBWxFfbhd{F#xVMF41{Vv9V31II&l1_7rZgFq-@ rSDfDNXVq`_&9`M^Xn6c))_V1pAkmxWuh#>Eg@M7-)z4*}Q$iB}$sb}! literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/slider_c.png b/src/grub2/grub/themes/hiperiso/slider_c.png new file mode 100644 index 0000000000000000000000000000000000000000..7d630fdfa7194e93383a61732ad17fc963404094 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W-!3HGz;^n6SDJ@SI#}J9B$te!ZX0PL~8UIVq xa1cMv_RrYJM21r&-$g80$xT@^;e#{>!%1Iujvq?0Z-BZOJYD@<);T3K0RR~Q7=Qo( literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/slider_n.png b/src/grub2/grub/themes/hiperiso/slider_n.png new file mode 100644 index 0000000000000000000000000000000000000000..41482c90f8dcd21814c8b161ef44945a8f2ec822 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W+!3HFM&b|K@NVR&pIEH9UOiox}lyF2nbN9Qg zf9sFc^Y#3fV3h!Zf5w0RANVo<<$;F^7n@b2Gd90_TIt5d#++01Us6I(hEvG=h}!X% ztEt)XUmqLsyy9ZMy>EKY!0JE6|Dfpcp4^WcZgy;g~^8 o*2W4+A;u$&K3gLWPY_~Ya86MC(CGPFALt+kPgg&ebxsLQ076SkFaQ7m literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/slider_s.png b/src/grub2/grub/themes/hiperiso/slider_s.png new file mode 100644 index 0000000000000000000000000000000000000000..17adc2abe5383c078c08c81fc85b35a8fa5039d5 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W+!3HFM&b|K@NY#6~IEH9UOipoNHhUd^&G=t> zhJ*NVwtvP(CNi8N`7UC~N^Z)U4Bd_Y?FH7$2J5yp{{OczU*VcXPL?5$jhN1l2@mZL zGac$njwsNH_@L;>EGZ!&vF~rH?t$zV^=+*8|7{XWn4EOvImhi%{XhSW4Hjgiq$JEJ hu<%GywyO~=zI zOpGiD!GyXnv2~y;6D&xGg+GAQpHR+eoHCGFI^TPz=Xu`Gd)3@}I6rrDj^ns_d(&*O zeT^-C_6qx-JpTQfZ8xaZrERi9GdIE9x=(r-*rB_NTiEsYpMAwE95-_-=yYk2NX##^J7$|~L^+Z$y%c_7BRI8)= zKoXG*MHwQwiX=@`HKc&?$1`tXRaGcTP?D+) zQBC(F>gLrbT`Uz$oO($R(||;vP;`4_NOhh?dX_>MPh_KXTqag9n7c7Vf>@+f0v+dK zXc$h=DQ)5Nc>gP$cJ^ZoTR0`d#AA)ySu9+|nvr0alB7e(URlLvpHPzaNem1F+}REy zpJeIX5!`V!J4&e=dDu2}o(Tv+;A@g0tCorswYDT8WXbD_WHwB3*=SgnxzVVXT$6ai z5J$A+`sduGsoY``!kBqBaS}Yo{zgJVFv?g9rpF>r)f;pD>9N$Nav=)_7JdDv&*c>x zp2D0=Ejvu+9!G506E@XHPYw^+i?D2Sy_5g?^Sx5xz}4gT!Rgy??!v`Wle0S15{{3-G!FAO)No{xOk(q12k+qwH<8XwDIOk z_z1p$2NO*+-ZXJ9K7dz!1g9*p9>gZo`OW0}zTe+@-R(Rs9+VC^jw@QHMvv{c+2Z$a zvH!E?^UrL%OWOl_M#eOCV$3x?GQz+LoC)q>$6LJkf*TySchBz+=)iuWx+D;t93y5y z#Mm6yIL;!+onZ<_c;bf||Lfg*9{8TdpUbvnM>?MRr^^_hEjxX8Idc_{KYj!nnaTtL zOdXH~7h$4i8o$z2nVnxl9;_gArt#N74eTz^NsNIk%7QDQDyS(Ul2Nse9)PlhDp0CG zR1r{Fl@t}pVEysTTkMV1o?)(iv6IG6DUDPJ(=-*+ib&!KM2ez7sSL|yfgyxs5mF}; z!sKwHVBo}!{fPP`1i7L!B6F(oEYj-~f@munChIb>g2Bv*AQGiKr47)w{|^mxbb1`DpK_rJCwwILM}E{>`n#%CS|HblL17Ura@VOic;Z- zN;-;|n^&T=JX5ep>Lo$U0vdrr(cP!VOc!~irzwQ-TsBIlW#R>cxf??y$wf*tpyT`> z8isRp$~xpM-hT?G-BCKn+b6lO}dmG&8pZQQbyAuje%)`J9|Oo z(=1(^z#RwMQOexNBetcBTtEr}AIk<(jrzK(RqHZBP1R^1!!#O-Wwu%dGR+y+qTX>x zA~xgtXWZ&SZZQdA%spEq37!zYmCz7OGRDE;SkOYfDc4^di?Walc`&f(>tB7InfUM& z$NALq%Y5!h#D_iMQ~kVLe#2kHhHV+${L7C|OC>?Rbk4vJf6)Q1-~4*}>RZ{ae|Y&~ l`PFLw_sR0){hTiC&sX}w@@Q$}hWRZkOm=g}I%)Ku{sBQABoF`q literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/terminal_box_ne.png b/src/grub2/grub/themes/hiperiso/terminal_box_ne.png new file mode 100644 index 0000000000000000000000000000000000000000..9e26959bbba3b01838af0d3f2573caa33f967de5 GIT binary patch literal 1115 zcmaJ=TSyd97#`Ei4AX8rknMCzaQZLa<*h5AH6+r|&*co%Rhqi$;=fd}W|M&mrKWAE+ zx0e*JEhY$}B)&sP;JM5hMTPiZ`F&c#(;5^_q1~_xWh4_24GQc8WL%TFK>|oh|G{S< zND%q!)np2##3o*bnp<)(Zd)@jn;?Sqwjs$q0Fj-bTh&9Tv`fgU-aQ1#o$pv_|e4IqiMwO-xg?GQDi%j30kOjG0x1oecdKc-S*3mJhX zAUQYZk{Q-V`U7s3V|{h(7ShA8UYhaJtk=bQcqYKJ969?@IGU++@d+U|8w>A3R2m_J zr|C>4AOK4?RRgI|Cmltp6ZWAHg`NIM zK{MuLb!)avxL~v`88qu=oRqRaQT#tt)8^0?N`QI4{}i^8{RW^Dz=D0Ij4!UM$_Zug z5fexVnn?(IvsG+KLj3d~qFGjLJlL}3B9sw#ZIS69bG znc9Gli?M9f8;(VM;cx@Tuu&$$M7>$A0OdXn=qSro=DGfyT&EK>14kBssU8AK%!C>_ zlQFO6_TtN_H_KIWd*O0&X>5je?)9&G&K}|Bah7vki#Kz94|Lq@ChqFgmM2sAMNGtn zhNS&=%qY#rIY&}oEXT1lkZCI?HUg++=V7f)9jH)1t-~# zSBpw7u3UHN_$KPW>kIzFV_P4zRgO=zofmE$JzE}ZYg|~-eJ65xV>!8X|IpKTq4}%# z14sLfybCwK9={zN%O4I^Jia^Cm=N|)FBqyBd9&ASFH4;&Y*#k?@CZw<Tm_$EcU<@@yJ+K!LkqMwWE4;QQ^ Xs$Vu)t&2yWJI_5HZ5FPFI|hFPzQk-R literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/terminal_box_nw.png b/src/grub2/grub/themes/hiperiso/terminal_box_nw.png new file mode 100644 index 0000000000000000000000000000000000000000..5c3cba87cd5c602cc5d5201384067985adc6d5fd GIT binary patch literal 1094 zcmaJ=Ur5w&93P1qlBiiy7By#-hPU1BpKf@`dGqwh$#Gt3MB&_idPBG0+95Ya>Umeoo05JF;P&`a2hMD55;Y=UTRu?s%#&E=_s43{Hk|=K9y1vsc(W&Nk;-e8~A8=-BKgcJ<-;SI!?X7ZpMY`_*)O zq4cqP3!)~3ccCNp)%L~W+185Ag-z#*e_kx77uy!5_f;J@F~dK)f9I*aQeP-{{(4CC zRGg^W`NdPT>*JOEmwe;)*`+gn@C^_nlbM1~iSe?6s+G!7=~m^-$@a{i6#DbgZUferCtDC&IzW to7*x|gXyK}rpvb<6h%JVSbobi7w#Y^Zo6FjF(x{7MBBQAyRCf_e*k~AW>WwF literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/terminal_box_s.png b/src/grub2/grub/themes/hiperiso/terminal_box_s.png new file mode 100644 index 0000000000000000000000000000000000000000..85a8901dc36bd3b201fa9ed53cc8bfa213838e89 GIT binary patch literal 963 zcmaJ=zi-n(6m~#DsG=$(Fu>ssr4sS^5+{w1m^QT&YJo$QMrxKyIQBKM((@VnLY%N5 zHuy6b7+FDLU}1rg5wWu%F(7u%X_7J!EcxEu>HEI-v9Hi1qdN@uo0WdA-9A*fAfuF_CIM>k?p7w?|sU^~aAtk*Xw}zZtYUyyHB;9;1qz zVU(0cf-Ona?KE<|0pXxadO>K&Ki_|lLEszmVaZXQ$Rzz>ZxWM(Nwe)u2A=NA+jl`V z#X^7*?t+w_gb7X!d8&)WKD&l8m_qo#kWYi^IQzh4F##o|l=oDmfh}D@C8Sl*ZBS5A z5voOqig{GPs*X_!%syFoi~VEVvKljA;$+Bu&La%rXf#qrMTNyZh;&_tY5^7sd4b3$ z)K1|l<3KmJcIEZ+_LXauCT{h%~EFwKkfkq42FqxG}6bztR9IM@yo?uH(*EkhOpN)Y%M>AR&`xnSyASw*N`tW?U4%9f^Ss@5=3tvu&i%o|b? z@;TQ(<629(Strm)c(zC!JRyD~W)w^_#=-JfYD@KITz`2iyGyxH1Ou~o{p+3QSE6~c z?V@YNVbS*_6wMxsu0Hy_@l;Gi#kOkg^y`l=xm8KMbgqW)|7Ja0zVU72$~)B#U*6eV kn@&!)>O) zicWoT3gUw+=!+Z9H+>Mi4FpBO7eU4p5f#A)FME*rq9?PRK3D@M=fd}W|M&mrKc~A> zI~qLA9)chmk~_sTp4Ymgz7GGr^FL)gHKDF7>V^HNAX|WlsW1n~q%IGDG?3MiBacCZ zAeL{^GFgYrKFv^J!QQ+Gmn1%E*hn@MkQAd77N9jv<%M{c7-ADb zxGj|6xUOJa48`I?Ah<1&5Zi^0K$R;(Wk?4Gs&dsoT(KtC?F8M#kwsu>!$3_~P$w5N z=C#^hVm0+DT(!2Bcug*Y%`oo0{&mmQBiuaha;a-J%dp%!nG*5nbzW-3mL`!l1@@8$r_^SMiuV%*@->`S4*ppj- zAbk7G`1N9XY-057#&T(zT2}l)#G2nNoQO3x9Y3C0@y36jX!iHe2fb4-+!vngN{Q3) GzS1w8%5Wk8 literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/terminal_box_sw.png b/src/grub2/grub/themes/hiperiso/terminal_box_sw.png new file mode 100644 index 0000000000000000000000000000000000000000..67c600c82301cfa647aed1e727f3e0f71a529fb7 GIT binary patch literal 1107 zcmaJ=%WD%s9G*0oN^PNnuNKsCt5P4?M;@)aG}<+WoKrzY(w z2#vP%Ab3>7ig*+&c=8oRq$-H$LGcgpAcCTx-r{U+st4o3>^%6s@Av(F^PB0xf&EPl ztqlNxrewdIqI0u1RtD&Q^S6phrxudPkRy1Q9Oq%KlN+DIB7<-1g0Pt@y z(ixIb4oMm|S=Ga^1=FT%0J`=SY*iaY1ZL5QVa1rwcONp)&|}Q;sKP6D9OaDuNe3O7 z97t=EqnfBQ`}V@FfoEMD_@~VTc#P93SR{a8L+IyeJ7#xb!hJnxhX(DY$V z#`tu#ii0^!u$#j+jK^X7al_Ja-rcbXR}?8}xkR-zl$2u(6<`fRmwMunM7T2%5hKw) zK}du}p<_=XB8NIfG29`Dkt$cl+PH}tFX=J)+IyEtk8NZkGEVS+v<5+SOO?_tn!Ev5=H|(uMa~ zeQ1au?p|@Jr5_w>TvK+#6 z#W%%wmoom$ocd_y#?yw6t;u_V?k3-g%XRC~w!P5EOJ3Y_ye%^;}=VfL0;V#E<6}xTq*uKXWfA*13PplxQAVT@#Y(@bKK6Opg*7k=S1^JD7Xbi$itYi zIj(-3$F4WS6pZjBh;;tfmn$9wzRsU3j_AZDo(An@f=`#7zPFrts?Q%k2lZTI0wJa@ z$is^$)pDI*>1xa_t|1Rr5IWQO>!1cs7nmf$KoOLxC!#}eqzXtuhc)yJNFtJ=c;+qf$6C*7t$neR&QB?gH3+jT6EayK$pj)*RiP+BNvbkLHC;s1&8ty* zP%2nB^^zc_0f|7N=#I#o>O70|I)yOa$VTb9OsrrqcVmbIu}G-|I?n&0VYor3w1;ov z{ikr+U&I*pa7yNh#~L?2C|t#wnP8Waq)*62S;g*@P?Anb3``R|J`WrIIcC1gv@bV8m?;&FV literal 0 HcmV?d00001 diff --git a/src/grub2/grub/themes/hiperiso/theme.txt b/src/grub2/grub/themes/hiperiso/theme.txt new file mode 100644 index 0000000..492a159 --- /dev/null +++ b/src/grub2/grub/themes/hiperiso/theme.txt @@ -0,0 +1,97 @@ + +desktop-image: "background.png" +title-text: " " +title-color: "#ffffff" +message-color: "#f2f2f2" + +terminal-box: "terminal_box_*.png" + ++ boot_menu { + left = 10% + width = 80% + top = 30% + height = 50% + + menu_pixmap_style = "menu_*.png" + + item_color = "#ffffff" + item_height = 30 + + item_spacing = 1 + item_padding = 1 + + selected_item_color= "#f2f2f2" + selected_item_pixmap_style = "select_*.png" + + item_icon_space = 0 + + scrollbar = true + scrollbar_width = 10 + scrollbar_thumb = "slider_*.png" +} + + + ++ progress_bar { + id = "__timeout__" + text = "@TIMEOUT_NOTIFICATION_SHORT@" + + left = 90% + width = 10% + top = 90% + + text_color = "red" + bar_style = "*" + highlight_style = "*" +} + ++ hbox{ + left = 28% + top = 95% + width = 10% + height = 25 + + label {text = "@HISO_HOTKEY_TIP@" color = "blue" align = "left"} +} + + ++ hbox{ + left = 30% + top = 95%-25 + width = 10% + height = 25 + + label {text = "@HISO_MEM_DISK@" color = "red" align = "left"} +} + + ++ hbox{ + left = 30% + top = 95%-50 + width = 10% + height = 25 + + label {text = "@HISO_ISO_RAW@" color = "red" align = "left"} +} + + ++ hbox{ + left = 30%+200 + top = 95%-50 + width = 10% + height = 25 + + label {text = "@HISO_GRUB2_MODE@" color = "red" align = "left"} +} + ++ hbox{ + left = 30%+200 + top = 95%-25 + width = 10% + height = 25 + + label {text = "@HISO_WIMBOOT_MODE@" color = "red" align = "left"} +} + ++ hbox{ + left = 90% + top = 55 + width = 10% + height = 25 + + label {text = "@HISO_ISO_UEFI_DRV@" color = "red" align = "left"} +} diff --git a/src/grub2/grub/x86_64-efi/command.lst b/src/grub2/grub/x86_64-efi/command.lst new file mode 100644 index 0000000..96cba29 --- /dev/null +++ b/src/grub2/grub/x86_64-efi/command.lst @@ -0,0 +1,203 @@ +*acpi: acpi +*all_functional_test: functional_test +*background_image: gfxterm_background +*bls_import: blscfg +*blscfg: blscfg +*cat: cat +*cpuid: cpuid +*crc: hashsum +*cryptomount: cryptodisk +*echo: echo +*extract_syslinux_entries_configfile: syslinuxcfg +*extract_syslinux_entries_source: syslinuxcfg +*file: file +*functional_test: functional_test +*fwconnect: fwload +*fwload: fwload +*gettext: gettext +*hashsum: hashsum +*hdparm: hdparm +*hello: hello +*help: help +*hexdump: hexdump +*inb: iorw +*inl: iorw +*inw: iorw +*keystatus: keystatus +*kfreebsd: bsd +*knetbsd: bsd +*kopenbsd: bsd +*list_env: loadenv +*load_env: loadenv +*loopback: loopback +*ls: ls +*lsacpi: lsacpi +*lspci: lspci +*md5sum: hashsum +*menuentry: normal +*pcidump: pcidump +*probe: probe +*rdmsr: rdmsr +*read_byte: memrw +*read_dword: memrw +*read_word: memrw +*regexp: regexp +*save_env: loadenv +*search: search +*serial: serial +*set_keyboard_layout: setkey +*setkey: setkey +*setpci: setpci +*sha1sum: hashsum +*sha256sum: hashsum +*sha512sum: hashsum +*sleep: sleep +*smbios: smbios +*submenu: normal +*syslinux_configfile: syslinuxcfg +*syslinux_source: syslinuxcfg +*terminfo: terminfo +*test_blockarg: test_blockarg +*testspeed: testspeed +*tr: tr +*trust: pgp +*verify_detached: pgp +*xnu_splash: xnu +*zfskey: zfscrypt +.: configfile +[: test +appleloader: appleldr +authenticate: normal +background_color: gfxterm_background +backtrace: backtrace +badram: mmap +blocklist: blocklist +boot: boot +break: normal +cat: minicmd +cbmemc: cbmemc +chainloader: chain +clear: normal +cmp: cmp +configfile: configfile +continue: normal +coreboot_boottime: cbtime +cutmem: mmap +date: date +distrust: pgp +dump: minicmd +eval: eval +exit: minicmd +export: normal +extract_entries_configfile: configfile +extract_entries_source: configfile +extract_legacy_entries_configfile: legacycfg +extract_legacy_entries_source: legacycfg +fakebios: loadbios +false: true +fix_video: fixvideo +fwsetup: efifwsetup +gptsync: gptsync +halt: halt +help: minicmd +hexdump_random: random +initrd16: linux16 +initrd: linux +initrdefi: linux +keymap: keylayouts +kfreebsd_loadenv: bsd +kfreebsd_module: bsd +kfreebsd_module_elf: bsd +knetbsd_module: bsd +knetbsd_module_elf: bsd +kopenbsd_ramdisk: bsd +legacy_check_password: legacycfg +legacy_configfile: legacycfg +legacy_initrd: legacycfg +legacy_initrd_nounzip: legacycfg +legacy_kernel: legacycfg +legacy_password: legacycfg +legacy_source: legacycfg +linux16: linux16 +linux: linux +linuxefi: linux +list_trusted: pgp +loadbios: loadbios +loadfont: font +lscoreboot: cbls +lsefi: lsefi +lsefimmap: lsefimmap +lsefisystab: lsefisystab +lsfonts: font +lsmmap: lsmmap +lsmod: minicmd +lssal: lssal +macppcbless: macbless +mactelbless: macbless +module2: multiboot2 +module: multiboot +multiboot2: multiboot2 +multiboot: multiboot +nativedisk: nativedisk +net_add_addr: net +net_add_dns: net +net_add_route: net +net_bootp: net +net_del_addr: net +net_del_dns: net +net_del_route: net +net_dhcp: net +net_get_dhcp_option: net +net_ipv6_autoconf: net +net_ls_addr: net +net_ls_cards: net +net_ls_dns: net +net_ls_routes: net +net_nslookup: net +normal: normal +normal_exit: normal +outb: iorw +outl: iorw +outw: iorw +parttool: parttool +password: password +password_pbkdf2: password_pbkdf2 +play: play +read: read +reboot: reboot +return: normal +rmmod: minicmd +search.file: search_fs_file +search.fs_label: search_label +search.fs_uuid: search_fs_uuid +setparams: normal +shift: normal +source: configfile +terminal_input: terminal +terminal_output: terminal +test: test +testload: testload +time: time +true: true +usb: usbtest +videoinfo: videoinfo +videotest: videotest +vt_img_extra_initrd_append: linux +vt_img_extra_initrd_reset: linux +vt_set_boot_opt: linux +vt_unset_boot_opt: linux +write_byte: memrw +write_dword: memrw +write_word: memrw +wrmsr: wrmsr +xnu_devprop_load: xnu +xnu_kernel64: xnu +xnu_kernel: xnu +xnu_kext: xnu +xnu_kextdir: xnu +xnu_mkext: xnu +xnu_ramdisk: xnu +xnu_resume: xnu +xnu_uuid: xnu_uuid +zfs-bootfs: zfsinfo +zfsinfo: zfsinfo diff --git a/src/grub2/grub/x86_64-efi/crypto.lst b/src/grub2/grub/x86_64-efi/crypto.lst new file mode 100644 index 0000000..77d9efc --- /dev/null +++ b/src/grub2/grub/x86_64-efi/crypto.lst @@ -0,0 +1,45 @@ +RIJNDAEL: gcry_rijndael +RIJNDAEL192: gcry_rijndael +RIJNDAEL256: gcry_rijndael +AES128: gcry_rijndael +AES-128: gcry_rijndael +AES-192: gcry_rijndael +AES-256: gcry_rijndael +ADLER32: adler32 +CRC64: crc64 +ARCFOUR: gcry_arcfour +BLOWFISH: gcry_blowfish +CAMELLIA128: gcry_camellia +CAMELLIA192: gcry_camellia +CAMELLIA256: gcry_camellia +CAST5: gcry_cast5 +CRC32: gcry_crc +CRC32RFC1510: gcry_crc +CRC24RFC2440: gcry_crc +DES: gcry_des +3DES: gcry_des +DSA: gcry_dsa +IDEA: gcry_idea +MD4: gcry_md4 +MD5: gcry_md5 +RFC2268_40: gcry_rfc2268 +AES: gcry_rijndael +AES192: gcry_rijndael +AES256: gcry_rijndael +RIPEMD160: gcry_rmd160 +RSA: gcry_rsa +SEED: gcry_seed +SERPENT128: gcry_serpent +SERPENT192: gcry_serpent +SERPENT256: gcry_serpent +SHA1: gcry_sha1 +SHA224: gcry_sha256 +SHA256: gcry_sha256 +SHA512: gcry_sha512 +SHA384: gcry_sha512 +TIGER192: gcry_tiger +TIGER: gcry_tiger +TIGER2: gcry_tiger +TWOFISH: gcry_twofish +TWOFISH128: gcry_twofish +WHIRLPOOL: gcry_whirlpool diff --git a/src/grub2/grub/x86_64-efi/fdt.lst b/src/grub2/grub/x86_64-efi/fdt.lst new file mode 100644 index 0000000..e69de29 diff --git a/src/grub2/grub/x86_64-efi/fs.lst b/src/grub2/grub/x86_64-efi/fs.lst new file mode 100644 index 0000000..0acd240 --- /dev/null +++ b/src/grub2/grub/x86_64-efi/fs.lst @@ -0,0 +1,37 @@ +affs +afs +bfs +btrfs +cbfs +cpio +cpio_be +exfat +ext2 +f2fs +fat +hfs +hfsplus +iso9660 +jfs +minix +minix2 +minix2_be +minix3 +minix3_be +minix_be +newc +nilfs2 +ntfs +odc +procfs +reiserfs +romfs +sfs +squash4 +tar +udf +ufs1 +ufs1_be +ufs2 +xfs +zfs diff --git a/src/grub2/grub/x86_64-efi/moddep.lst b/src/grub2/grub/x86_64-efi/moddep.lst new file mode 100644 index 0000000..11eda45 --- /dev/null +++ b/src/grub2/grub/x86_64-efi/moddep.lst @@ -0,0 +1,270 @@ +videotest: font video gfxmenu +odc: archelp +loopback: extcmd +setkey: extcmd +macho: +gcry_des: crypto +memrw: extcmd +terminfo: extcmd +f2fs: fshelp +part_gpt: +romfs: fshelp +read: +lsefimmap: +aout: +gcry_arcfour: crypto +tftp: net priority_queue +newc: archelp +minix2_be: +elf: +videotest_checksum: font functional_test video_fb +password_pbkdf2: crypto gcry_sha512 pbkdf2 normal +gcry_seed: crypto +pcidump: extcmd +bsd: elf serial crypto gcry_md5 verifiers extcmd aout video boot cpuid relocator mmap +sfs: fshelp +reiserfs: fshelp +part_sunpc: +zstd: +gfxmenu: video_colors trig bitmap_scale gfxterm font normal video bitmap +backtrace: +jfs: +help: extcmd normal +configfile: normal +cbls: cbtable +gfxterm_menu: font functional_test procfs normal video_fb +gcry_idea: crypto +tr: extcmd +shift_test: functional_test +ohci: cs5536 usb boot +afs: fshelp +spkmodem: terminfo +usb_keyboard: keylayouts usb +xzio: crypto +syslinuxcfg: extcmd normal +search_fs_file: +wrmsr: +usbms: scsi usb +test_blockarg: extcmd normal +true: +affs: fshelp +iso9660: fshelp +smbios: extcmd +exfat: fshelp +setjmp_test: setjmp functional_test +gfxterm: font video +efinet: net +disk: +appleldr: boot +xfs: fshelp +testspeed: extcmd normal +cpio_be: archelp +functional_test: btrfs extcmd video video_fb +bswap_test: functional_test +sleep: extcmd normal +memdisk: +gcry_rijndael: crypto +mdraid09_be: diskfilter +gettext: +gcry_sha1: crypto +hfspluscomp: gzio hfsplus +cmp: +random: hexdump +offsetio: +file: elf macho extcmd offsetio +usbserial_usbdebug: serial usb usbserial_common +video_colors: +morse: +hashsum: crypto extcmd normal +usb: +halt: acpi +gfxterm_background: video_colors bitmap_scale gfxterm extcmd video bitmap +search_fs_uuid: +gcry_dsa: pgp mpi +keystatus: extcmd +linux: hiperiso verifiers video boot relocator mmap +geli: cryptodisk crypto gcry_sha512 pbkdf2 gcry_sha256 +cmdline_cat_test: font functional_test normal procfs video_fb +rdmsr: extcmd +part_sun: +cbtable: +pbkdf2_test: functional_test pbkdf2 gcry_sha1 +video_bochs: video video_fb +verifiers: +bufio: +usbserial_ftdi: serial usb usbserial_common +legacy_password_test: functional_test legacycfg +cpuid: extcmd +blscfg: extcmd normal +hdparm: extcmd hexdump +bfs: fshelp +gcry_blowfish: crypto +test: +nilfs2: fshelp +gcry_rsa: pgp mpi +cryptodisk: crypto extcmd procfs +nativedisk: +minicmd: +signature_test: functional_test procfs +ata: scsi +udf: fshelp +gzio: gcry_crc +xnu_uuid: gcry_md5 +uhci: usb +pata: ata +mul_test: functional_test +adler32: crypto +terminal: +shim_lock: verifiers +div: +ehci: cs5536 usb boot +crypto: +part_bsd: part_msdos +cs5536: +hiperiso: ext2 fshelp elf btrfs crypto font gcry_md5 exfat udf datetime div extcmd normal video gcry_sha1 mmap iso9660 +gcry_sha512: crypto +password: crypto normal +fshelp: +sleep_test: functional_test datetime +iorw: extcmd +xnu: macho bitmap_scale random verifiers extcmd boot video bitmap relocator mmap +mmap: +exfctest: functional_test +zfsinfo: zfs +ldm: part_gpt diskfilter part_msdos +eval: normal +part_dvh: +lssal: +blocklist: +ext2: fshelp +net: priority_queue bufio datetime boot +part_acorn: +videoinfo: video +btrfs: zstd lzopio raid6rec gzio +lsmmap: mmap +strtoull_test: functional_test +bitmap: +ntfs: fshelp +multiboot: net linux video boot relocator mmap +tpm: verifiers +gcry_crc: crypto +png: bufio bitmap +jpeg: bufio bitmap +macbless: disk +div_test: functional_test div +regexp: extcmd normal +parttool: normal +usbserial_pl2303: serial usb usbserial_common +cpio: archelp +gcry_rmd160: crypto +fat: fshelp +ufs1_be: +archelp: +http: net +zfs: gzio +raid6rec: diskfilter +lsefisystab: +minix2: +lsacpi: extcmd acpi +datehook: datetime normal +loadenv: disk extcmd +bitmap_scale: bitmap +probe: extcmd +minix3: +tar: archelp +loadbios: +hfs: fshelp +procfs: archelp +boot: +keylayouts: +progress: normal +kernel: +usbtest: usb +relocator: mmap +acpi: extcmd mmap +tga: bufio bitmap +reboot: +fwload: extcmd +serial: extcmd terminfo +zfscrypt: crypto pbkdf2 extcmd zfs gcry_sha1 gcry_rijndael +efi_uga: video video_fb +dm_nv: diskfilter +cmp_test: functional_test +luks: cryptodisk crypto pbkdf2 +font: bufio video +raid5rec: diskfilter +crc64: crypto +datetime: +efifwsetup: +ctz_test: functional_test +video: +cbmemc: cbtable normal terminfo +hfsplus: fshelp +gcry_cast5: crypto +extcmd: +squash4: fshelp zstd lzopio zfs xzio gzio +part_plan: +minix_be: +gcry_whirlpool: crypto +gcry_tiger: crypto +fixvideo: +search: search_fs_uuid search_fs_file extcmd search_label +lspci: extcmd +cbtime: cbtable +video_fb: +minix3_be: +trig: +msdospart: disk parttool +priority_queue: +gcry_twofish: crypto +part_dfly: +xnu_uuid_test: functional_test +diskfilter: +testload: +part_apple: +hexdump: extcmd +date: datetime normal +pbkdf2: crypto +gcry_sha256: crypto +ls: extcmd normal +usbserial_common: serial usb +ntfscomp: ntfs +mouse: +lzopio: crypto +video_cirrus: video video_fb +hello: extcmd +scsi: +linux16: linux boot video relocator mmap +cat: extcmd +ahci: ata boot +pgp: crypto verifiers extcmd mpi gcry_sha1 +normal: terminal crypto verifiers bufio extcmd boot gettext +ufs1: +mdraid09: diskfilter +lvm: diskfilter +chain: net efinet boot +cbfs: archelp +ufs2: +time: +setpci: extcmd +gptsync: disk +search_label: +setjmp: +multiboot2: linux net video boot relocator acpi mmap +gcry_rfc2268: crypto +mdraid1x: diskfilter +mpi: crypto +legacycfg: crypto password gcry_md5 normal +play: +part_amiga: +efi_gop: video video_fb +minix: +echo: extcmd +lsefi: +gcry_serpent: crypto +gcry_md4: crypto +gcry_md5: crypto +part_msdos: +gcry_camellia: crypto +at_keyboard: keylayouts boot +all_video: efi_gop efi_uga video_bochs video_cirrus diff --git a/src/grub2/grub/x86_64-efi/partmap.lst b/src/grub2/grub/x86_64-efi/partmap.lst new file mode 100644 index 0000000..761233a --- /dev/null +++ b/src/grub2/grub/x86_64-efi/partmap.lst @@ -0,0 +1,11 @@ +part_acorn +part_amiga +part_apple +part_bsd +part_dfly +part_dvh +part_gpt +part_msdos +part_plan +part_sun +part_sunpc diff --git a/src/grub2/grub/x86_64-efi/parttool.lst b/src/grub2/grub/x86_64-efi/parttool.lst new file mode 100644 index 0000000..68b4b5c --- /dev/null +++ b/src/grub2/grub/x86_64-efi/parttool.lst @@ -0,0 +1 @@ +msdos: msdospart diff --git a/src/grub2/grub/x86_64-efi/terminal.lst b/src/grub2/grub/x86_64-efi/terminal.lst new file mode 100644 index 0000000..9afb9bd --- /dev/null +++ b/src/grub2/grub/x86_64-efi/terminal.lst @@ -0,0 +1,10 @@ +iat_keyboard: at_keyboard +imouse: mouse +iserial: serial +iserial_*: serial +oaudio: morse +ocbmemc: cbmemc +ogfxterm: gfxterm +oserial: serial +oserial_*: serial +ospkmodem: spkmodem diff --git a/src/grub2/grub/x86_64-efi/video.lst b/src/grub2/grub/x86_64-efi/video.lst new file mode 100644 index 0000000..ae9ba23 --- /dev/null +++ b/src/grub2/grub/x86_64-efi/video.lst @@ -0,0 +1,4 @@ +efi_gop +efi_uga +video_bochs +video_cirrus diff --git a/src/grub2/hiperiso.c b/src/grub2/hiperiso.c new file mode 100644 index 0000000..3cb1a95 --- /dev/null +++ b/src/grub2/hiperiso.c @@ -0,0 +1,655 @@ +/****************************************************************************** + * hiperiso.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_MACHINE_EFI +#include +#include +#endif +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +int g_hiperiso_debug = 0; +static int g_efi_os = 0xFF; +grub_uint32_t g_hiperiso_plat_data; + +#ifdef GRUB_MACHINE_EFI +static HISO_SHIM *g_hiso_shim = NULL; +#endif + +void hiperiso_debug(const char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); +} + +void hiperiso_str_tolower(char *str) +{ + while (*str) + { + *str = grub_tolower(*str); + str++; + } +} + +void hiperiso_str_toupper(char *str) +{ + while (*str) + { + *str = grub_toupper(*str); + str++; + } +} + +char *hiperiso_str_last(char *str, char ch) +{ + char *pos = NULL; + char *last = NULL; + + if (!str) + { + return NULL; + } + + for (pos = str; *pos; pos++) + { + if (*pos == ch) + { + last = pos; + } + } + + return last; +} + +int hiperiso_str_all_digit(const char *str) +{ + if (NULL == str || 0 == *str) + { + return 0; + } + + while (*str) + { + if (*str < '0' || *str > '9') + { + return 0; + } + str++; + } + + return 1; +} + +int hiperiso_str_all_alnum(const char *str) +{ + if (NULL == str || 0 == *str) + { + return 0; + } + + while (*str) + { + if (!grub_isalnum(*str)) + { + return 0; + } + } + + return 1; +} + +int hiperiso_str_len_alnum(const char *str, int len) +{ + int i; + int slen; + + if (NULL == str || 0 == *str) + { + return 0; + } + + slen = grub_strlen(str); + if (slen <= len) + { + return 0; + } + + for (i = 0; i < len; i++) + { + if (!grub_isalnum(str[i])) + { + return 0; + } + } + + if (str[len] == 0 || grub_isspace(str[len])) + { + return 1; + } + + return 0; +} + +char * hiperiso_str_basename(char *path) +{ + char *pos = NULL; + + pos = grub_strrchr(path, '/'); + if (pos) + { + pos++; + } + else + { + pos = path; + } + + return pos; +} + +int hiperiso_str_chrcnt(const char *str, char c) +{ + int n = 0; + + if (str) + { + while (*str) + { + if (*str == c) + { + n++; + } + str++; + } + } + + return n; +} + +int hiperiso_strcmp(const char *pattern, const char *str) +{ + while (*pattern && *str) + { + if ((*pattern != *str) && (*pattern != '*')) + break; + + pattern++; + str++; + } + + return (int)(grub_uint8_t)*pattern - (int)(grub_uint8_t)*str; +} + +int hiperiso_strncmp (const char *pattern, const char *str, grub_size_t n) +{ + if (n == 0) + return 0; + + while (*pattern && *str && --n) + { + if ((*pattern != *str) && (*pattern != '*')) + break; + + pattern++; + str++; + } + + return (int)(grub_uint8_t)*pattern - (int)(grub_uint8_t)*str; +} + +grub_err_t hiperiso_env_int_set(const char *name, int value) +{ + char buf[16]; + + grub_snprintf(buf, sizeof(buf), "%d", value); + return grub_env_set(name, buf); +} + +void hiperiso_debug_dump_guid(const char *prefix, grub_uint8_t *guid) +{ + int i; + + if (!g_hiperiso_debug) + { + return; + } + + debug("%s", prefix); + for (i = 0; i < 16; i++) + { + grub_printf("%02x ", guid[i]); + } + grub_printf("\n"); +} + +int hiperiso_is_efi_os(void) +{ + if (g_efi_os > 1) + { + g_efi_os = (grub_strstr(GRUB_PLATFORM, "efi")) ? 1 : 0; + } + + return g_efi_os; +} + +void * hiperiso_alloc_chain(grub_size_t size) +{ + void *p = NULL; + + p = grub_malloc(size); +#ifdef GRUB_MACHINE_EFI + if (!p) + { + p = grub_efi_allocate_any_pages(GRUB_EFI_BYTES_TO_PAGES(size)); + } +#endif + + return p; +} + +void hiperiso_memfile_env_set(const char *prefix, const void *buf, unsigned long long len) +{ + char name[128]; + char val[64]; + + grub_snprintf(name, sizeof(name), "%s_addr", prefix); + grub_snprintf(val, sizeof(val), "0x%llx", (ulonglong)(ulong)buf); + grub_env_set(name, val); + + grub_snprintf(name, sizeof(name), "%s_size", prefix); + grub_snprintf(val, sizeof(val), "%llu", len); + grub_env_set(name, val); + + return; +} + +#ifdef GRUB_MACHINE_EFI +static void hiperiso_get_uefi_version(char *str, grub_size_t len) +{ + grub_efi_uint8_t uefi_minor_1, uefi_minor_2; + + uefi_minor_1 = (grub_efi_system_table->hdr.revision & 0xffff) / 10; + uefi_minor_2 = (grub_efi_system_table->hdr.revision & 0xffff) % 10; + grub_snprintf(str, len, "%d.%d", (grub_efi_system_table->hdr.revision >> 16), uefi_minor_1); + if (uefi_minor_2) + grub_snprintf(str, len, "%s.%d", str, uefi_minor_2); +} + +static void hiperiso_get_pi_version(char *str, grub_size_t len) +{ + grub_uint32_t data = 0; + grub_efi_uintn_t i = 0; + grub_efi_guid_t dxest = + { 0x05ad34ba, 0x6f02, 0x4214, {0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 } }; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) + { + if (grub_memcmp(&dxest, &grub_efi_system_table->configuration_table[i].vendor_guid, 16) == 0) + { + grub_memcpy(&data, (char *)grub_efi_system_table->configuration_table[i].vendor_table + 8, 4); + break; + } + } + + grub_snprintf(str, len, "%d.%d", (data >> 16) & 0xFFFF, (data & 0xFFFF) / 10); +} + +int hiperiso_set_sb_policy(void) +{ + const char *env = NULL; + static int set_once = 0; + + /* no need when SecureBoot is disabled */ + if (g_sys_sb == 0) + { + return 0; + } + + /* can only set once */ + if (set_once > 0) + { + return 0; + } + set_once = 1; + + /* HISO_SECURE_BOOT_POLICY only take affect once during init */ + env = grub_env_get("HISO_SECURE_BOOT_POLICY"); + if (env) + { + g_sb_policy = (grub_uint8_t)(env[0] - '0'); + } + + if (g_sb_policy == HISO_SB_POLICY_BYPASS) + { + if (g_hiso_shim && g_hiso_shim->ByPassSB) + { + g_hiso_shim->ByPassSB(); + } + } + else if (g_sb_policy == HISO_SB_POLICY_CHECK) + { + if (g_hiso_shim && g_hiso_shim->CheckSB) + { + g_hiso_shim->CheckSB(); + } + } + + return 0; +} + +static void hiperiso_get_uefi_sb(void) +{ + grub_uint8_t secure_boot = 0; + grub_uint8_t setup_mode = 0; + grub_uint8_t *var = NULL; + grub_size_t size = 0; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + var = grub_efi_get_variable("SecureBoot", &global, &size); + if (var && size == 1 && *var == 1) + { + secure_boot = 1; + } + grub_check_free(var); + + size = 0; + var = grub_efi_get_variable("SetupMode", &global, &size); + if (var && size == 1 && *var == 1) + { + setup_mode = 1; + } + + if (secure_boot == 1 && setup_mode == 0) + { + g_sys_sb = 1; + } + + grub_check_free(var); +} + +static int hiperiso_secure_boot_init(void) +{ + grub_efi_guid_t ProtGuid = HISO_SHIM_POLICY_GUID; + + hiperiso_get_uefi_sb(); + + if (g_sys_sb == 0) + { + return 0; + } + + + /* + * When SecureBoot enabled, Hiperiso grub must be launched by Hiperiso Shim. + * Currently only x86_64 support this feature. + */ + if (g_hiperiso_plat_data == HISO_PLAT_X86_64_UEFI) + { + g_hiso_shim = grub_efi_locate_protocol(&ProtGuid, NULL); + if (g_hiso_shim == NULL || g_hiso_shim->ByPassSB == NULL || + g_hiso_shim->CheckSB == NULL || g_hiso_shim->Launched == NULL) + { + grub_cls(); + grub_printf(HISO_WARNING"\n"); + grub_printf(HISO_WARNING"\n"); + grub_printf(HISO_WARNING"\n\n\n"); + + grub_printf("Hiperiso grub is not launched by Hiperiso shim.\n\n"); + grub_refresh(); + + hiperiso_prompt_end(); + } + + g_hiso_shim->Launched(); + } + + return 0; +} + + +#endif + +static int hiperiso_arch_mode_init(void) +{ + #ifdef GRUB_MACHINE_EFI + + if (grub_strcmp(GRUB_TARGET_CPU, "i386") == 0) + { + g_hiperiso_plat_data = HISO_PLAT_I386_UEFI; + grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "ia32"); + } + else if (grub_strcmp(GRUB_TARGET_CPU, "arm64") == 0) + { + g_hiperiso_plat_data = HISO_PLAT_ARM64_UEFI; + grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "aa64"); + } + else if (grub_strcmp(GRUB_TARGET_CPU, "mips64el") == 0) + { + g_hiperiso_plat_data = HISO_PLAT_MIPS_UEFI; + grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "mips"); + } + else + { + g_hiperiso_plat_data = HISO_PLAT_X86_64_UEFI; + grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "uefi"); + } +#else + g_hiperiso_plat_data = HISO_PLAT_X86_LEGACY; + grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "legacy"); +#endif + + return 0; +} + +static int hiperiso_calc_totalmem(grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, void *data) +{ + grub_uint64_t *total_mem = (grub_uint64_t *)data; + + (void)addr; + (void)type; + + *total_mem += size; + + return 0; +} + +static int hiperiso_hwinfo_init(void) +{ + char str[256]; + grub_uint64_t total_mem = 0; + + grub_machine_mmap_iterate(hiperiso_calc_totalmem, &total_mem); + + grub_snprintf(str, sizeof(str), "%ld", (long)(total_mem / HISO_SIZE_1MB)); + hiperiso_env_export("grub_total_ram", str); + +#ifdef GRUB_MACHINE_EFI + hiperiso_get_uefi_version(str, sizeof(str)); + hiperiso_env_export("grub_uefi_version", str); + + hiperiso_get_pi_version(str, sizeof(str)); + hiperiso_env_export("grub_pi_version", str); +#else + hiperiso_env_export("grub_uefi_version", "NA"); + hiperiso_env_export("grub_pi_version", "NA"); +#endif + + return 0; +} + +static global_var_cfg g_global_vars[] = +{ + { "gfxmode", "1024x768", NULL }, + { hiperiso_left_key, "5%", NULL }, + { hiperiso_top_key, "95%", NULL }, + { hiperiso_color_key, "#0000ff", NULL }, + { NULL, NULL, NULL } +}; + +static const char * hiperiso_global_var_read_hook(struct grub_env_var *var, const char *val) +{ + int i; + + for (i = 0; g_global_vars[i].name; i++) + { + if (grub_strcmp(g_global_vars[i].name, var->name) == 0) + { + return g_global_vars[i].value; + } + } + + return val; +} + +static char * hiperiso_global_var_write_hook(struct grub_env_var *var, const char *val) +{ + int i; + + for (i = 0; g_global_vars[i].name; i++) + { + if (grub_strcmp(g_global_vars[i].name, var->name) == 0) + { + grub_check_free(g_global_vars[i].value); + g_global_vars[i].value = grub_strdup(val); + break; + } + } + + return grub_strdup(val); +} + +int hiperiso_global_var_init(void) +{ + int i; + + for (i = 0; g_global_vars[i].name; i++) + { + g_global_vars[i].value = grub_strdup(g_global_vars[i].defval); + hiperiso_env_export(g_global_vars[i].name, g_global_vars[i].defval); + grub_register_variable_hook(g_global_vars[i].name, hiperiso_global_var_read_hook, hiperiso_global_var_write_hook); + } + + return 0; +} + +static ctrl_var_cfg g_ctrl_vars[] = +{ + { "HISO_WIN11_BYPASS_CHECK", "1" }, + { "HISO_WIN11_BYPASS_NRO", "1" }, + { "HISO_LINUX_REMOUNT", "0" }, + { "HISO_SECONDARY_BOOT_MENU", "1" }, + { "HISO_WIN_UEFI_RES_LOCK", "3" }, + { NULL, "" } +}; + +static const char * hiperiso_ctrl_var_read_hook(struct grub_env_var *var, const char *val) +{ + int i; + + for (i = 0; g_ctrl_vars[i].name; i++) + { + if (grub_strcmp(g_ctrl_vars[i].name, var->name) == 0) + { + return g_ctrl_vars[i].szval; + } + } + + return val; +} + +static char * hiperiso_ctrl_var_write_hook(struct grub_env_var *var, const char *val) +{ + int i; + + for (i = 0; g_ctrl_vars[i].name; i++) + { + if (grub_strcmp(g_ctrl_vars[i].name, var->name) == 0) + { + if (val && grub_isdigit(val[0]) && val[1] == 0) + { + g_ctrl_vars[i].szval[0] = val[0]; + return grub_strdup(val); + } + else + { + g_ctrl_vars[i].szval[0] = '0'; + return grub_strdup("0"); + } + } + } + + return grub_strdup(val); +} + +int hiperiso_ctrl_var_init(void) +{ + ctrl_var_cfg *cfg = g_ctrl_vars; + + while (cfg->name) + { + hiperiso_env_export(cfg->name, cfg->szval); + grub_register_variable_hook(cfg->name, hiperiso_ctrl_var_read_hook, hiperiso_ctrl_var_write_hook); + cfg++; + } + + return 0; +} + +GRUB_MOD_INIT(hiperiso) +{ + hiperiso_hwinfo_init(); + hiperiso_env_init(); + hiperiso_arch_mode_init(); + +#ifdef GRUB_MACHINE_EFI + hiperiso_secure_boot_init(); +#endif + + hiperiso_register_all_cmd(); +} + +GRUB_MOD_FINI(hiperiso) +{ + hiperiso_unregister_all_cmd(); +} + diff --git a/src/grub2/hiperiso.h b/src/grub2/hiperiso.h new file mode 100644 index 0000000..515169b --- /dev/null +++ b/src/grub2/hiperiso.h @@ -0,0 +1,331 @@ +/****************************************************************************** + * hiperiso.h + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#ifndef __HIPERISO_H__ +#define __HIPERISO_H__ + +#define COMPILE_ASSERT(a, expr) extern char __compile_assert##a[(expr) ? 1 : -1] + +#define HIPERISO_COMPATIBLE_STR "HIPERISO COMPATIBLE" +#define HIPERISO_COMPATIBLE_STR_LEN 17 + +#define HIPERISO_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }} + +typedef enum hiperiso_fs_type +{ + hiperiso_fs_exfat = 0, /* 0: exfat */ + hiperiso_fs_ntfs, /* 1: NTFS */ + hiperiso_fs_ext, /* 2: ext2/ext3/ext4 */ + hiperiso_fs_xfs, /* 3: XFS */ + hiperiso_fs_udf, /* 4: UDF */ + hiperiso_fs_fat, /* 5: FAT */ + hiperiso_fs_btrfs, /* 6: BTRFS */ + + hiperiso_fs_max +}hiperiso_fs_type; + +typedef enum hiperiso_chain_type +{ + hiperiso_chain_linux = 0, /* 0: linux */ + hiperiso_chain_windows, /* 1: windows */ + hiperiso_chain_wim, /* 2: wim */ + + hiperiso_chain_max +}hiperiso_chain_type; + +#pragma pack(1) + +typedef struct hiperiso_guid +{ + grub_uint32_t data1; + grub_uint16_t data2; + grub_uint16_t data3; + grub_uint8_t data4[8]; +}hiperiso_guid; + + +typedef struct hiperiso_image_disk_region +{ + grub_uint32_t image_sector_count; /* image sectors contained in this region (in 2048) */ + grub_uint32_t image_start_sector; /* image sector start (in 2048) */ + grub_uint64_t disk_start_sector; /* disk sector start (in 512) */ +}hiperiso_image_disk_region; + +typedef struct hiperiso_image_location +{ + hiperiso_guid guid; + + /* image sector size, 2048/512 */ + grub_uint32_t image_sector_size; + + /* disk sector size, normally the value is 512 */ + grub_uint32_t disk_sector_size; + + grub_uint32_t region_count; + + /* + * disk region data (region_count) + * If the image file has more than one fragments in disk, + * there will be more than one region data here. + * + */ + hiperiso_image_disk_region regions[1]; + + /* hiperiso_image_disk_region regions[2~region_count-1] */ +}hiperiso_image_location; + + +typedef struct hiperiso_os_param +{ + hiperiso_guid guid; // HIPERISO_GUID + grub_uint8_t chksum; // checksum + + grub_uint8_t hiso_disk_guid[16]; + grub_uint64_t hiso_disk_size; // disk size in bytes + grub_uint16_t hiso_disk_part_id; // begin with 1 + grub_uint16_t hiso_disk_part_type; // 0:exfat 1:ntfs other: reserved + char hiso_img_path[384]; // It seems to be enough, utf-8 format + grub_uint64_t hiso_img_size; // image file size in bytes + + /* + * Hiperiso will write a copy of hiperiso_image_location data into runtime memory + * this is the physically address and length of that memory. + * Address 0 means no such data exist. + * Address will be aligned by 4KB. + * + */ + grub_uint64_t hiso_img_location_addr; + grub_uint32_t hiso_img_location_len; + + /* + * These 32 bytes are reserved by hiperiso. + * + * hiso_reserved[0]: hiso_break_level + * hiso_reserved[1]: hiso_debug_level + * hiso_reserved[2]: hiso_chain_type 0:Linux 1:Windows 2:wimfile + * hiso_reserved[3]: hiso_iso_format 0:iso9660 1:udf + * hiso_reserved[4]: hiso_windows_cd_prompt + * hiso_reserved[5]: hiso_linux_remount + * hiso_reserved[6]: hiso_vlnk + * hiso_reserved[7~10]: hiso_disk_sig[4] used for vlnk + * hiso_reserved[11]: hiso_win_uefi_max_res + * + */ + grub_uint8_t hiso_reserved[32]; // Internal use by hiperiso + + grub_uint8_t hiso_disk_signature[4]; + + grub_uint8_t reserved[27]; +}hiperiso_os_param; + + +typedef struct hiperiso_windows_data +{ + char auto_install_script[384]; + char injection_archive[384]; + grub_uint8_t windows11_bypass_check; + + grub_uint32_t auto_install_len; + + grub_uint8_t windows11_bypass_nro; + + grub_uint8_t reserved[255 - 5]; + + /* auto_intall file buf */ + /* ...... + auto_install_len */ +}hiperiso_windows_data; + + +typedef struct hiperiso_secure_data +{ + grub_uint8_t magic1[16]; /* HIPERISO_GUID */ + grub_uint8_t diskuuid[16]; + grub_uint8_t Checksum[16]; + grub_uint8_t adminSHA256[32]; + grub_uint8_t reserved[4000]; + grub_uint8_t magic2[16]; /* HIPERISO_GUID */ +}hiperiso_secure_data; + + +typedef struct hiperiso_vlnk +{ + hiperiso_guid guid; // HIPERISO_GUID + grub_uint32_t crc32; // crc32 + grub_uint32_t disk_signature; + grub_uint64_t part_offset; // in bytes + char filepath[384]; + grub_uint8_t reserved[96]; +}hiperiso_vlnk; + +#pragma pack() + +// compile assert check : sizeof(hiperiso_os_param) must be 512 +COMPILE_ASSERT(1,sizeof(hiperiso_os_param) == 512); +COMPILE_ASSERT(2,sizeof(hiperiso_secure_data) == 4096); +COMPILE_ASSERT(3,sizeof(hiperiso_vlnk) == 512); + + + + + + + +#pragma pack(4) + +typedef struct hiperiso_chain_head +{ + hiperiso_os_param os_param; + + grub_uint32_t disk_drive; + grub_uint32_t drive_map; + grub_uint32_t disk_sector_size; + + grub_uint64_t real_img_size_in_bytes; + grub_uint64_t virt_img_size_in_bytes; + grub_uint32_t boot_catalog; + grub_uint8_t boot_catalog_sector[2048]; + + grub_uint32_t img_chunk_offset; + grub_uint32_t img_chunk_num; + + grub_uint32_t override_chunk_offset; + grub_uint32_t override_chunk_num; + + grub_uint32_t virt_chunk_offset; + grub_uint32_t virt_chunk_num; +}hiperiso_chain_head; + +typedef struct hiperiso_image_desc +{ + grub_uint64_t disk_size; + grub_uint64_t part1_size; + grub_uint8_t disk_uuid[16]; + grub_uint8_t disk_signature[4]; + grub_uint32_t img_chunk_count; + /* hiperiso_img_chunk list */ +}hiperiso_image_desc; + + + +typedef struct hiperiso_img_chunk +{ + grub_uint32_t img_start_sector; // sector size: 2KB + grub_uint32_t img_end_sector; // included + + grub_uint64_t disk_start_sector; // in disk_sector_size + grub_uint64_t disk_end_sector; // included +}hiperiso_img_chunk; + + +typedef struct hiperiso_override_chunk +{ + grub_uint64_t img_offset; + grub_uint32_t override_size; + grub_uint8_t override_data[512]; +}hiperiso_override_chunk; + +typedef struct hiperiso_virt_chunk +{ + grub_uint32_t mem_sector_start; + grub_uint32_t mem_sector_end; + grub_uint32_t mem_sector_offset; + grub_uint32_t remap_sector_start; + grub_uint32_t remap_sector_end; + grub_uint32_t org_sector_start; +}hiperiso_virt_chunk; + +#define DEFAULT_CHUNK_NUM 1024 +typedef struct hiperiso_img_chunk_list +{ + char *buf; + grub_uint32_t last_off; + grub_uint32_t err_code; + + grub_uint32_t max_chunk; + grub_uint32_t cur_chunk; + hiperiso_img_chunk *chunk; +}hiperiso_img_chunk_list; + +#pragma pack() + +#define hiperiso_filt_register grub_file_filter_register + +#pragma pack(1) + +#define HISO_MAX_CONF_REPLACE 2 +#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF +#define GRUB_IMG_REPLACE_MAGIC 0x1259BEEF + +typedef const char * (*grub_env_get_pf)(const char *name); +typedef int (*grub_env_set_pf)(const char *name, const char *val); +typedef int (*grub_env_printf_pf)(const char *fmt, ...); + +typedef struct hiperiso_grub_param_file_replace +{ + grub_uint32_t magic; + char old_file_name[4][256]; + grub_uint32_t old_name_cnt; + grub_uint32_t new_file_virtual_id; +}hiperiso_grub_param_file_replace; + +typedef struct hiperiso_grub_param +{ + grub_env_get_pf grub_env_get; + grub_env_set_pf grub_env_set; + hiperiso_grub_param_file_replace file_replace; + hiperiso_grub_param_file_replace img_replace[HISO_MAX_CONF_REPLACE]; + grub_env_printf_pf grub_env_printf; +}hiperiso_grub_param; + +#pragma pack() + +#define HISO_CHUNK_BUF_SIZE (4 * 1024 * 1024) + +typedef enum hiso_chunk_err +{ + HISO_CHUNK_ERR_NONE = 0, + HISO_CHUNK_ERR_MULTI_DEV, + HISO_CHUNK_ERR_RAID, + HISO_CHUNK_ERR_COMPRESS, + HISO_CHUNK_ERR_NOT_FLAT, + HISO_CHUNK_ERR_OVER_FLOW, + HISO_CHUNK_ERR_MAX +}hiso_chunk_err; + +int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, hiperiso_img_chunk_list *chunk_list); +int grub_btrfs_get_file_chunk(grub_uint64_t part_start, grub_file_t file, hiperiso_img_chunk_list *chunk_list); +int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, hiperiso_img_chunk_list *chunk_list); +void grub_iso9660_set_nojoliet(int nojoliet); +int grub_iso9660_is_joliet(void); +grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file); +grub_uint64_t grub_iso9660_get_last_file_dirent_pos(grub_file_t file); +grub_uint64_t grub_udf_get_file_offset(grub_file_t file); +grub_uint64_t grub_udf_get_last_pd_size_offset(void); +grub_uint64_t grub_udf_get_last_file_attr_offset +( + grub_file_t file, + grub_uint32_t *startBlock, + grub_uint64_t *fe_entry_size_offset +); +int hiperiso_is_efi_os(void); +void hiperiso_memfile_env_set(const char *prefix, const void *buf, unsigned long long len); + +#endif /* __HIPERISO_H__ */ + diff --git a/src/grub2/hiperiso_browser.c b/src/grub2/hiperiso_browser.c new file mode 100644 index 0000000..a56fa1d --- /dev/null +++ b/src/grub2/hiperiso_browser.c @@ -0,0 +1,652 @@ +/****************************************************************************** + * hiperiso_browser.c + * + * Copyright (c) 2022, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define BROWSER_MENU_BUF 65536 + +static const char *g_hiso_dev = NULL; +static grub_fs_t g_menu_fs = NULL; +static char *g_menu_device = NULL; +static grub_device_t g_menu_dev = NULL; +static char g_menu_path_buf[1024]; +static int g_menu_path_len = 0; +static browser_node *g_browser_list = NULL; + +static int hiperiso_browser_strcmp(char *str1, char *str2) +{ + char *s1, *s2; + int c1 = 0; + int c2 = 0; + + for (s1 = str1, s2 = str2; *s1 && *s2; s1++, s2++) + { + c1 = *s1; + c2 = *s2; + + if (0 == g_sort_case_sensitive) + { + if (grub_islower(c1)) + { + c1 = c1 - 'a' + 'A'; + } + + if (grub_islower(c2)) + { + c2 = c2 - 'a' + 'A'; + } + } + + if (c1 != c2) + { + break; + } + } + + return (c1 - c2); +} + +static int hiperiso_browser_mbuf_alloc(browser_mbuf *mbuf) +{ + grub_memset(mbuf, 0, sizeof(browser_mbuf)); + mbuf->buf = grub_malloc(BROWSER_MENU_BUF); + if (!mbuf->buf) + { + return 0; + } + + mbuf->pos = 0; + mbuf->max = BROWSER_MENU_BUF; + return 1; +} + +static inline void hiperiso_browser_mbuf_free(browser_mbuf *mbuf) +{ + if (mbuf) + grub_check_free(mbuf->buf) +} + +static inline int hiperiso_browser_mbuf_extend(browser_mbuf *mbuf) +{ + if (mbuf->max - mbuf->pos <= HISO_SIZE_1KB) + { + mbuf->max += BROWSER_MENU_BUF; + mbuf->buf = grub_realloc(mbuf->buf, mbuf->max); + } + + return 0; +} + +static browser_node * hiperiso_browser_find_top_node(int dir) +{ + browser_node *node = NULL; + browser_node *sel = NULL; + + for (node = g_browser_list; node; node = node->next) + { + if (node->dir == dir) + { + if (sel) + { + if (hiperiso_browser_strcmp(sel->filename, node->filename) > 0) + { + sel = node; + } + } + else + { + sel = node; + } + } + } + + return sel; +} + +static int hiperiso_browser_iterate_partition(struct grub_disk *disk, const grub_partition_t partition, void *data) +{ + char partname[64]; + char title[256]; + grub_device_t dev; + grub_fs_t fs; + char *Label = NULL; + browser_mbuf *mbuf = (browser_mbuf *)data; + + (void)data; + + if (partition->number == 1 && g_hiso_dev && grub_strcmp(disk->name, g_hiso_dev) == 0) + { + return 0; + } + + grub_snprintf(partname, sizeof(partname) - 1, "%s,%d", disk->name, partition->number + 1); + + dev = grub_device_open(partname); + if (!dev) + { + return 0; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + grub_device_close(dev); + return 0; + } + + fs->fs_label(dev, &Label); + + if (hiperiso_check_file_exist("(%s)/.hiperisoignore", partname)) + { + return 0; + } + + if (g_tree_view_menu_style == 0) + { + grub_snprintf(title, sizeof(title), "%-10s (%s,%s%d) [%s] %s %s", + "DISK", disk->name, partition->msdostype == 0xee ? "gpt" : "msdos", + partition->number + 1, (Label ? Label : ""), fs->name, + grub_get_human_size(partition->len << disk->log_sector_size, GRUB_HUMAN_SIZE_SHORT)); + } + else + { + grub_snprintf(title, sizeof(title), "(%s,%s%d) [%s] %s %s", + disk->name, partition->msdostype == 0xee ? "gpt" : "msdos", + partition->number + 1, (Label ? Label : ""), fs->name, + grub_get_human_size(partition->len << disk->log_sector_size, GRUB_HUMAN_SIZE_SHORT)); + } + + if (hiperiso_get_fs_type(fs->name) >= hiperiso_fs_max) + { + browser_ssprintf(mbuf, "menuentry \"%s\" --class=hisodisk {\n" + " echo \"unsupported file system type!\" \n" + " hiperiso_pause\n" + "}\n", + title); + } + else + { + browser_ssprintf(mbuf, "menuentry \"%s\" --class=hisodisk {\n" + " vt_browser_dir %s,%d 0x%lx /\n" + "}\n", + title, disk->name, partition->number + 1, (ulong)fs); + } + + hiperiso_browser_mbuf_extend(mbuf); + + return 0; +} + +static int hiperiso_browser_iterate_disk(const char *name, void *data) +{ + grub_disk_t disk; + + if (name[0] != 'h') + { + return 0; + } + + disk = grub_disk_open(name); + if (disk) + { + grub_partition_iterate(disk, hiperiso_browser_iterate_partition, data); + grub_disk_close(disk); + } + + return 0; +} + +static int hiperiso_browser_valid_dirname(const char *name, int len) +{ + if ((len == 1 && name[0] == '.') || + (len == 2 && name[0] == '.' && name[1] == '.')) + { + return 0; + } + + if (!hiperiso_img_name_valid(name, len)) + { + return 0; + } + + if (g_filt_trash_dir) + { + if (0 == grub_strncmp(name, ".trash-", 7) || + 0 == grub_strcmp(name, ".Trashes")) + { + return 0; + } + } + + if (name[0] == '$') + { + if (0 == grub_strncmp(name, "$RECYCLE.BIN", 12) || + 0 == grub_strncasecmp(name, "$Extend", 7)) + { + return 0; + } + } + + if (len == 25 && grub_strncmp(name, "System Volume Information", 25) == 0) + { + return 0; + } + + return 1; +} + +static int hiperiso_browser_valid_filename(const char *filename, int len, int *type) +{ + if (len < 4) + { + return 0; + } + + if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso")) + { + *type = img_type_iso; + } + else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim"))) + { + *type = img_type_wim; + } + else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") || + (len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx")))) + { + *type = img_type_vhd; + } + #ifdef GRUB_MACHINE_EFI + else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi")) + { + *type = img_type_efi; + } + #endif + else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img")) + { + if (len == 18 && grub_strncmp(filename, "hiperiso_", 7) == 0) + { + if (grub_strncmp(filename + 7, "wimboot", 7) == 0 || + grub_strncmp(filename + 7, "vhdboot", 7) == 0) + { + return 0; + } + } + *type = img_type_img; + } + else if (FILE_FLT(HISO) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".hiso")) + { + *type = img_type_hiso; + } + else + { + return 0; + } + + if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_') + { + return 0; + } + + return 1; +} + +static int hiperiso_browser_check_ignore(const char *device, const char *root, const char *dir) +{ + grub_file_t file; + char fullpath[1024] = {0}; + + grub_snprintf(fullpath, 1023, "(%s)%s/%s/.hiperisoignore", device, root, dir); + file = grub_file_open(fullpath, GRUB_FILE_TYPE_NONE); + if (!file) + { + grub_errno = 0; + return 0; + } + else + { + grub_file_close(file); + return 1; + } +} + +static int hiperiso_browser_iterate_dir(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + int type; + int len; + browser_node *node; + + (void)data; + + len = grub_strlen(filename); + + if (info->dir) + { + if (!hiperiso_browser_valid_dirname(filename, len)) + { + return 0; + } + + if (hiperiso_browser_check_ignore(g_menu_device, g_menu_path_buf, filename)) + { + return 0; + } + + node = grub_zalloc(sizeof(browser_node)); + if (!node) + { + return 0; + } + + node->dir = 1; + grub_strncpy(node->filename, filename, sizeof(node->filename)); + + if (g_tree_view_menu_style == 0) + { + grub_snprintf(node->menuentry, sizeof(node->menuentry), + "menuentry \"%-10s [%s]\" --class=hisodir {\n" + " vt_browser_dir %s 0x%lx \"%s/%s\"\n" + "}\n", + "DIR", filename, g_menu_device, (ulong)g_menu_fs, g_menu_path_buf, filename); + } + else + { + grub_snprintf(node->menuentry, sizeof(node->menuentry), + "menuentry \"[%s]\" --class=hisodir {\n" + " vt_browser_dir %s 0x%lx \"%s/%s\"\n" + "}\n", + filename, g_menu_device, (ulong)g_menu_fs, g_menu_path_buf, filename); + } + } + else + { + grub_uint64_t fsize = info->size; + + if (!hiperiso_browser_valid_filename(filename, len, &type)) + { + return 0; + } + + if (grub_file_is_vlnk_suffix(filename, len)) + { + return 0; + } + + node = grub_zalloc(sizeof(browser_node)); + if (!node) + { + return 0; + } + + if (fsize == 0) + { + struct grub_file file; + + grub_memset(&file, 0, sizeof(file)); + file.device = g_menu_dev; + grub_snprintf(node->menuentry, sizeof(node->menuentry), "%s/%s", g_menu_path_buf, filename); + if (g_menu_fs->fs_open(&file, node->menuentry) == GRUB_ERR_NONE) + { + fsize = file.size; + g_menu_fs->fs_close(&file); + } + } + + node->dir = 0; + grub_strncpy(node->filename, filename, sizeof(node->filename)); + + if (g_tree_view_menu_style == 0) + { + grub_snprintf(node->menuentry, sizeof(node->menuentry), + "menuentry \"%-10s %s\" --class=%s {\n" + " vt_set_fake_vlnk \"(%s)%s/%s\" %s %llu\n" + " %s_common_menuentry\n" + " vt_reset_fake_vlnk\n" + "}\n", + grub_get_human_size(fsize, GRUB_HUMAN_SIZE_SHORT), filename, g_menu_class[type], + g_menu_device, g_menu_path_buf, filename, g_menu_prefix[type], (ulonglong)fsize, + g_menu_prefix[type]); + } + else + { + grub_snprintf(node->menuentry, sizeof(node->menuentry), + "menuentry \"%s\" --class=%s {\n" + " vt_set_fake_vlnk \"(%s)%s/%s\" %s %llu\n" + " %s_common_menuentry\n" + " vt_reset_fake_vlnk\n" + "}\n", + filename, g_menu_class[type], + g_menu_device, g_menu_path_buf, filename, g_menu_prefix[type], (ulonglong)fsize, + g_menu_prefix[type]); + } + } + + node->prev = NULL; + node->next = g_browser_list; + if (g_browser_list) + { + g_browser_list->prev = node; + } + g_browser_list = node; + + return 0; +} + +static grub_err_t hiperiso_browser_iso_part(void) +{ + char cfgfile[64]; + char *buffer = NULL; + int pos = 0; + int buflen = 0; + int cfglen = 0; + + cfglen = g_tree_script_pos - g_tree_script_pre; + buflen = cfglen + 512; + buffer = grub_malloc(buflen); + if (!buffer) + { + return 1; + } + + if (g_tree_view_menu_style == 0) + { + pos = grub_snprintf(buffer, buflen, "menuentry \"%-10s [../]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n", "<--"); + } + else + { + pos = grub_snprintf(buffer, buflen, "menuentry \"[../]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n"); + } + + grub_memcpy(buffer + pos, g_tree_script_buf + g_tree_script_pre, cfglen); + pos += cfglen; + + grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%lx:size:%d", (ulong)buffer, pos); + grub_script_execute_sourcecode(cfgfile); + + grub_free(buffer); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_browser_dir(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + grub_fs_t fs; + grub_device_t dev; + char cfgfile[64]; + browser_node *node; + browser_mbuf mbuf; + + (void)ctxt; + (void)argc; + + if (args[2][0] == '/' && args[2][1] == 0) + { + grub_snprintf(cfgfile, sizeof(cfgfile), "(%s)", args[0]); + if (grub_strcmp(cfgfile, g_iso_path) == 0) + { + return hiperiso_browser_iso_part(); + } + } + + if (!hiperiso_browser_mbuf_alloc(&mbuf)) + { + return 1; + } + + fs = (grub_fs_t)grub_strtoul(args[1], NULL, 16); + if (!fs) + { + debug("Invalid fs %s\n", args[1]); + return 1; + } + + dev = grub_device_open(args[0]); + if (!dev) + { + debug("Failed to open device %s\n", args[0]); + return 1; + } + + g_menu_fs = fs; + g_menu_device = args[0]; + g_menu_dev = dev; + g_browser_list = NULL; + + if (args[2][0] == '/' && args[2][1] == 0) + { + g_menu_path_len = 0; + g_menu_path_buf[0] = 0; + fs->fs_dir(dev, "/", hiperiso_browser_iterate_dir, NULL); + } + else + { + g_menu_path_len = grub_snprintf(g_menu_path_buf, sizeof(g_menu_path_buf), "%s", args[2]); + fs->fs_dir(dev, g_menu_path_buf, hiperiso_browser_iterate_dir, NULL); + } + grub_device_close(dev); + + if (g_tree_view_menu_style == 0) + { + browser_ssprintf(&mbuf, "menuentry \"%-10s [(%s)%s/..]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n", "<--", args[0], g_menu_path_buf); + } + else + { + browser_ssprintf(&mbuf, "menuentry \"[(%s)%s/..]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n", args[0], g_menu_path_buf); + } + + for (i = 1; i >= 0; i--) + { + while (1) + { + node = hiperiso_browser_find_top_node(i); + if (node) + { + browser_ssprintf(&mbuf, "%s", node->menuentry); + hiperiso_browser_mbuf_extend(&mbuf); + + if (node->prev) + { + node->prev->next = node->next; + } + if (node->next) + { + node->next->prev = node->prev; + } + + if (node == g_browser_list) + { + g_browser_list = node->next; + } + grub_free(node); + } + else + { + break; + } + } + } + g_browser_list = NULL; + + grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%lx:size:%d", (ulong)mbuf.buf, mbuf.pos); + grub_script_execute_sourcecode(cfgfile); + + hiperiso_browser_mbuf_free(&mbuf); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_browser_disk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char cfgfile[64]; + browser_mbuf mbuf; + + (void)ctxt; + (void)argc; + (void)args; + + if (!hiperiso_browser_mbuf_alloc(&mbuf)) + { + return 1; + } + + g_hiso_dev = grub_env_get("hisodev"); + + if (g_tree_view_menu_style == 0) + { + browser_ssprintf(&mbuf, "menuentry \"%-10s [%s]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n", "<--", + hiperiso_get_vmenu_title("VTLANG_BROWER_RETURN")); + } + else + { + browser_ssprintf(&mbuf, "menuentry \"[%s]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n}\n", + hiperiso_get_vmenu_title("VTLANG_BROWER_RETURN")); + } + + grub_disk_dev_iterate(hiperiso_browser_iterate_disk, &mbuf); + + grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%lx:size:%d", (ulong)mbuf.buf, mbuf.pos); + grub_script_execute_sourcecode(cfgfile); + + hiperiso_browser_mbuf_free(&mbuf); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + diff --git a/src/grub2/hiperiso_cmd.c b/src/grub2/hiperiso_cmd.c new file mode 100644 index 0000000..b787655 --- /dev/null +++ b/src/grub2/hiperiso_cmd.c @@ -0,0 +1,7335 @@ +/****************************************************************************** + * hiperiso_cmd.c + * + * Copyright (c) 2021, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_MACHINE_EFI +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" +#include "miniz.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint8_t g_check_mbr_data[] = { + 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D, +}; + +initrd_info *g_initrd_img_list = NULL; +initrd_info *g_initrd_img_tail = NULL; +int g_initrd_img_count = 0; +int g_valid_initrd_count = 0; +int g_default_menu_mode = 0; +int g_filt_dot_underscore_file = 0; +int g_filt_trash_dir = 1; +int g_sort_case_sensitive = 0; +int g_tree_view_menu_style = 0; +static grub_file_t g_old_file; +static int g_hiperiso_last_entry_back; + +char g_iso_path[256]; +char g_img_swap_tmp_buf[1024]; +img_info g_img_swap_tmp; +img_info *g_hiperiso_img_list = NULL; + +int g_hiperiso_img_count = 0; + +grub_device_t g_enum_dev = NULL; +grub_fs_t g_enum_fs = NULL; +int g_img_max_search_level = -1; +img_iterator_node g_img_iterator_head; +img_iterator_node *g_img_iterator_tail = NULL; + +grub_uint8_t g_hiperiso_break_level = 0; +grub_uint8_t g_hiperiso_debug_level = 0; +grub_uint8_t g_hiperiso_chain_type = 0; + +grub_uint8_t *g_hiperiso_cpio_buf = NULL; +grub_uint32_t g_hiperiso_cpio_size = 0; +cpio_newc_header *g_hiperiso_initrd_head = NULL; +grub_uint8_t *g_hiperiso_runtime_buf = NULL; + +int g_plugin_image_list = 0; + +hiperiso_grub_param *g_grub_param = NULL; + +hiperiso_guid g_hiperiso_guid = HIPERISO_GUID; + +hiperiso_img_chunk_list g_img_chunk_list; + +int g_wimboot_enable = 0; +hiperiso_img_chunk_list g_wimiso_chunk_list; +char *g_wimiso_path = NULL; +grub_uint32_t g_wimiso_size = 0; + +int g_vhdboot_enable = 0; + +grub_uint64_t g_svd_replace_offset = 0; + +int g_conf_replace_count = 0; +grub_uint64_t g_conf_replace_offset[HISO_MAX_CONF_REPLACE] = { 0 }; +conf_replace *g_conf_replace_node[HISO_MAX_CONF_REPLACE] = { NULL }; +grub_uint8_t *g_conf_replace_new_buf[HISO_MAX_CONF_REPLACE] = { NULL }; +int g_conf_replace_new_len[HISO_MAX_CONF_REPLACE] = { 0 }; +int g_conf_replace_new_len_align[HISO_MAX_CONF_REPLACE] = { 0 }; + +int g_hiperiso_disk_bios_id = 0; +hiperiso_gpt_info *g_hiperiso_part_info = NULL; +grub_uint64_t g_hiperiso_disk_size = 0; +grub_uint64_t g_hiperiso_disk_part_size[2]; + +char *g_tree_script_buf = NULL; +int g_tree_script_pos = 0; +int g_tree_script_pre = 0; + +static char *g_list_script_buf = NULL; +static int g_list_script_pos = 0; + +static char *g_part_list_buf = NULL; +static int g_part_list_pos = 0; +static grub_uint64_t g_part_end_max = 0; + +static int g_video_mode_max = 0; +static int g_video_mode_num = 0; +static hiperiso_video_mode *g_video_mode_list = NULL; + +static int g_enumerate_time_checked = 0; +static grub_uint64_t g_enumerate_start_time_ms; +static grub_uint64_t g_enumerate_finish_time_ms; +int g_hiso_file_flt[HISO_FILE_FLT_BUTT] = {0}; + +static char g_iso_vd_id_publisher[130]; +static char g_iso_vd_id_prepare[130]; +static char g_iso_vd_id_application[130]; + +static int g_pager_flag = 0; +static char g_old_pager[32]; + +const char *g_menu_class[img_type_max] = +{ + "hisoiso", "hisowim", "hisoefi", "hisoimg", "hisovhd", "hisohiso" +}; + +const char *g_menu_prefix[img_type_max] = +{ + "iso", "wim", "efi", "img", "vhd", "hiso" +}; + +static const char *g_lower_chksum_name[HISO_CHKSUM_NUM] = { "md5", "sha1", "sha256", "sha512" }; +static int g_lower_chksum_namelen[HISO_CHKSUM_NUM] = { 3, 4, 6, 6 }; +static int g_chksum_retlen[HISO_CHKSUM_NUM] = { 32, 40, 64, 128 }; + +static int g_hiso_secondary_need_recover = 0; + +static int g_hiso_load_prompt = 0; +static char g_hiso_prompt_msg[64]; + +static char g_json_case_mis_path[32]; + +static hiperiso_vlnk_part *g_vlnk_part_list = NULL; + +int hiperiso_get_fs_type(const char *fs) +{ + if (NULL == fs) + { + return hiperiso_fs_max; + } + else if (grub_strncmp(fs, "exfat", 5) == 0) + { + return hiperiso_fs_exfat; + } + else if (grub_strncmp(fs, "ntfs", 4) == 0) + { + return hiperiso_fs_ntfs; + } + else if (grub_strncmp(fs, "ext", 3) == 0) + { + return hiperiso_fs_ext; + } + else if (grub_strncmp(fs, "xfs", 3) == 0) + { + return hiperiso_fs_xfs; + } + else if (grub_strncmp(fs, "udf", 3) == 0) + { + return hiperiso_fs_udf; + } + else if (grub_strncmp(fs, "fat", 3) == 0) + { + return hiperiso_fs_fat; + } + else if (grub_strncmp(fs, "btrfs", 5) == 0) + { + return hiperiso_fs_btrfs; + } + + return hiperiso_fs_max; +} + +static int hiperiso_string_check(const char *str, grub_char_check_func check) +{ + if (!str) + { + return 0; + } + + for ( ; *str; str++) + { + if (!check(*str)) + { + return 0; + } + } + + return 1; +} + + +static grub_ssize_t hiperiso_fs_read(grub_file_t file, char *buf, grub_size_t len) +{ + grub_memcpy(buf, (char *)file->data + file->offset, len); + return len; +} + +static int hiperiso_control_get_flag(const char *key) +{ + const char *val = hiperiso_get_env(key); + + if (val && val[0] == '1' && val[1] == 0) + { + return 1; + } + return 0; +} + +static grub_err_t hiperiso_fs_close(grub_file_t file) +{ + grub_file_close(g_old_file); + grub_free(file->data); + + file->device = 0; + file->name = 0; + + return 0; +} + +static int hiperiso_video_hook(const struct grub_video_mode_info *info, void *hook_arg) +{ + int i; + + (void)hook_arg; + + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + { + return 0; + } + + for (i = 0; i < g_video_mode_num; i++) + { + if (g_video_mode_list[i].width == info->width && + g_video_mode_list[i].height == info->height && + g_video_mode_list[i].bpp == info->bpp) + { + return 0; + } + } + + g_video_mode_list[g_video_mode_num].width = info->width; + g_video_mode_list[g_video_mode_num].height = info->height; + g_video_mode_list[g_video_mode_num].bpp = info->bpp; + g_video_mode_num++; + + if (g_video_mode_num == g_video_mode_max) + { + g_video_mode_max *= 2; + g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(hiperiso_video_mode)); + } + + return 0; +} + +static int hiperiso_video_mode_cmp(hiperiso_video_mode *v1, hiperiso_video_mode *v2) +{ + if (v1->bpp == v2->bpp) + { + if (v1->width == v2->width) + { + if (v1->height == v2->height) + { + return 0; + } + else + { + return (v1->height < v2->height) ? -1 : 1; + } + } + else + { + return (v1->width < v2->width) ? -1 : 1; + } + } + else + { + return (v1->bpp < v2->bpp) ? -1 : 1; + } +} + +static int hiperiso_enum_video_mode(void) +{ + int i, j; + grub_video_adapter_t adapter; + grub_video_driver_id_t id; + hiperiso_video_mode mode; + + g_video_mode_num = 0; + g_video_mode_max = 1024; + g_video_mode_list = grub_malloc(sizeof(hiperiso_video_mode) * g_video_mode_max); + if (!g_video_mode_list) + { + return 0; + } + + #ifdef GRUB_MACHINE_PCBIOS + grub_dl_load ("vbe"); + #endif + + id = grub_video_get_driver_id (); + + FOR_VIDEO_ADAPTERS (adapter) + { + if (!adapter->iterate || + (adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE || + adapter->init() != GRUB_ERR_NONE))) + { + continue; + } + + adapter->iterate(hiperiso_video_hook, NULL); + + if (adapter->id != id) + { + adapter->fini(); + } + } + + /* sort video mode */ + for (i = 0; i < g_video_mode_num; i++) + for (j = i + 1; j < g_video_mode_num; j++) + { + if (hiperiso_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0) + { + grub_memcpy(&mode, g_video_mode_list + i, sizeof(hiperiso_video_mode)); + grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(hiperiso_video_mode)); + grub_memcpy(g_video_mode_list + j, &mode, sizeof(hiperiso_video_mode)); + } + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_pre_parse_data(char *src, int size) +{ + char c; + char *pos = NULL; + char buf[256]; + + if (size < 20 || grub_strncmp(src, "hiperiso_left_top_color", 21)) + { + return 0; + } + + pos = src + 21; + while (*pos && *pos != '\r' && *pos != '\n') + { + pos++; + } + + c = *pos; + *pos = 0; + + if (grub_strlen(src) > 200) + { + goto end; + } + + grub_snprintf(buf, sizeof(buf), + "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"", + hiperiso_left_key, hiperiso_top_key, hiperiso_color_key, src); + + grub_script_execute_sourcecode(buf); + +end: + *pos = c; + return 0; +} + +static grub_file_t hiperiso_wrapper_open(grub_file_t rawFile, enum grub_file_type type) +{ + int len; + grub_file_t file; + static struct grub_fs hiso_fs = + { + .name = "hiso", + .fs_dir = 0, + .fs_open = 0, + .fs_read = hiperiso_fs_read, + .fs_close = hiperiso_fs_close, + .fs_label = 0, + .next = 0 + }; + + if (type != 52) + { + return rawFile; + } + + file = (grub_file_t)grub_zalloc(sizeof (*file)); + if (!file) + { + return 0; + } + + file->data = grub_malloc(rawFile->size + 4096); + if (!file->data) + { + return 0; + } + + grub_file_read(rawFile, file->data, rawFile->size); + hiperiso_pre_parse_data((char *)file->data, (int)rawFile->size); + len = hiperiso_fill_data(4096, (char *)file->data + rawFile->size); + + g_old_file = rawFile; + + file->size = rawFile->size + len; + file->device = rawFile->device; + file->fs = &hiso_fs; + file->not_easily_seekable = 1; + + return file; +} + +static int hiperiso_check_decimal_var(const char *name, long *value) +{ + const char *value_str = NULL; + + value_str = grub_env_get(name); + if (NULL == value_str) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name); + } + + if (!hiperiso_is_decimal(value_str)) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str); + } + + *value = grub_strtol(value_str, NULL, 10); + + return GRUB_ERR_NONE; +} + +grub_uint64_t hiperiso_get_hiso_partsize(int part) +{ + grub_uint64_t sectors; + + if (grub_strncmp(g_hiperiso_part_info->Head.Signature, "EFI PART", 8) == 0) + { + sectors = g_hiperiso_part_info->PartTbl[part].LastLBA + 1 - g_hiperiso_part_info->PartTbl[part].StartLBA; + } + else + { + sectors = g_hiperiso_part_info->MBR.PartTbl[part].SectorCount; + } + + return sectors * 512; +} + +static int hiperiso_load_efiboot_template(char **buf, int *datalen, int *direntoff) +{ + int len; + grub_file_t file; + char exec[128]; + char *data = NULL; + grub_uint32_t offset; + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/hiperiso/hiperiso_efiboot.img.xz", hiperiso_get_env("hiso_efi_part")); + if (file == NULL) + { + debug("failed to open file <%s>\n", "hiperiso_efiboot.img.xz"); + return 1; + } + + len = (int)file->size; + + data = (char *)grub_malloc(file->size); + if (!data) + { + return 1; + } + + grub_file_read(file, data, file->size); + grub_file_close(file); + + grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len); + grub_script_execute_sourcecode(exec); + + file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD); + offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file); + grub_file_close(file); + + grub_script_execute_sourcecode("loopback -d efiboot"); + + *buf = data; + *datalen = len; + *direntoff = offset + 2; + + return 0; +} + +static int hiperiso_set_check_result(int ret, const char *msg) +{ + char buf[32]; + + grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF)); + grub_env_set("HISO_CHKDEV_RESULT_STRING", buf); + grub_env_export("HISO_CHKDEV_RESULT_STRING"); + + if (ret) + { + grub_cls(); + grub_printf(HISO_WARNING"\n"); + grub_printf(HISO_WARNING"\n"); + grub_printf(HISO_WARNING"\n\n\n"); + + grub_printf("This is NOT a standard Hiperiso device and is NOT supported (%d).\n", ret); + grub_printf("Error message: <%s>\n\n", msg); + grub_printf("You should follow the instructions in https://www.hiperiso.net to use Hiperiso.\n"); + grub_refresh(); + } + + return ret; +} + +static int hiperiso_check_official_device(grub_device_t dev) +{ + int workaround = 0; + grub_file_t file; + grub_uint64_t offset; + char devname[64]; + grub_fs_t fs; + grub_uint8_t mbr[512]; + grub_disk_t disk; + grub_device_t dev2; + char *label = NULL; + struct grub_partition *partition; + + if (dev->disk == NULL || dev->disk->partition == NULL) + { + return hiperiso_set_check_result(1 | 0x1000, "Internal Error"); + } + + if (0 == hiperiso_check_file_exist("(%s,2)/EFI/hiperiso/initramfs.cpio.gz", dev->disk->name) || + 0 == hiperiso_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) || + 0 == hiperiso_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name)) + { + #ifndef GRUB_MACHINE_EFI + if (0 == hiperiso_check_file_exist("(hiperisodisk)/EFI/hiperiso/initramfs.cpio.gz", dev->disk->name)) + { + return hiperiso_set_check_result(2 | 0x1000, "File EFI/hiperiso/initramfs.cpio.gz missing in HISOEFI partition"); + } + else if (0 == hiperiso_check_file_exist("(hiperisodisk)/grub/localboot.cfg", dev->disk->name)) + { + return hiperiso_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in HISOEFI partition"); + } + else if (0 == hiperiso_check_file_exist("(hiperisodisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name)) + { + return hiperiso_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in HISOEFI partition"); + } + else + { + workaround = 1; + } + #endif + } + + /* We must have partition 2 */ + if (workaround) + { + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", "(hiperisodisk)/EFI/hiperiso/initramfs.cpio.gz"); + } + else + { + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(%s,2)/EFI/hiperiso/initramfs.cpio.gz", dev->disk->name); + } + if (!file) + { + return hiperiso_set_check_result(3 | 0x1000, "File EFI/hiperiso/initramfs.cpio.gz open failed in HISOEFI partition"); + } + + if (NULL == grub_strstr(file->fs->name, "fat")) + { + grub_file_close(file); + return hiperiso_set_check_result(4 | 0x1000, "HISOEFI partition is not FAT filesystem"); + } + + partition = dev->disk->partition; + if (partition->number != 0 || partition->start != 2048) + { + return hiperiso_set_check_result(5, "Hiperiso partition is not start at 1MB"); + } + + if (workaround) + { + if (grub_strncmp(g_hiperiso_part_info->Head.Signature, "EFI PART", 8) == 0) + { + hiperiso_gpt_part_tbl *PartTbl = g_hiperiso_part_info->PartTbl; + if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 || + (PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536) + { + grub_file_close(file); + return hiperiso_set_check_result(6, "Disk partition layout check failed."); + } + } + else + { + hiperiso_part_table *PartTbl = g_hiperiso_part_info->MBR.PartTbl; + if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount || + PartTbl[1].SectorCount != 65536) + { + grub_file_close(file); + return hiperiso_set_check_result(6, "Disk partition layout check failed."); + } + } + } + else + { + offset = partition->start + partition->len; + partition = file->device->disk->partition; + if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start)) + { + grub_file_close(file); + return hiperiso_set_check_result(7, "Disk partition layout check failed."); + } + } + + grub_file_close(file); + + if (workaround == 0) + { + grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name); + dev2 = grub_device_open(devname); + if (!dev2) + { + return hiperiso_set_check_result(8, "Disk open failed"); + } + + fs = grub_fs_probe(dev2); + if (!fs) + { + grub_device_close(dev2); + return hiperiso_set_check_result(9, "FS probe failed"); + } + + fs->fs_label(dev2, &label); + if ((!label) || grub_strncmp("HISOEFI", label, 7)) + { + grub_device_close(dev2); + return hiperiso_set_check_result(10, "Partition name is not HISOEFI"); + } + + grub_device_close(dev2); + } + + /* MBR check */ + disk = grub_disk_open(dev->disk->name); + if (!disk) + { + return hiperiso_set_check_result(11, "Disk open failed"); + } + + grub_memset(mbr, 0, 512); + grub_disk_read(disk, 0, 0, 512, mbr); + grub_disk_close(disk); + + if (grub_memcmp(g_check_mbr_data, mbr, 0x30) || grub_memcmp(g_check_mbr_data + 0x30, mbr + 0x190, 16)) + { + return hiperiso_set_check_result(12, "MBR check failed"); + } + + return hiperiso_set_check_result(0, NULL); +} + +static int hiperiso_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + if (0 == info->dir) + { + if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".hiperisoignore", 13)) + { + *((int *)data) = 1; + return 0; + } + } + + return 0; +} + +grub_uint64_t hiperiso_grub_get_file_size(const char *fmt, ...) +{ + grub_uint64_t size = 0; + grub_file_t file; + va_list ap; + char fullpath[256] = {0}; + + va_start (ap, fmt); + grub_vsnprintf(fullpath, 255, fmt, ap); + va_end (ap); + + file = grub_file_open(fullpath, HIPERISO_FILE_TYPE); + if (!file) + { + debug("grub_file_open failed <%s>\n", fullpath); + grub_errno = 0; + return 0; + } + + size = file->size; + grub_file_close(file); + return size; +} + +grub_file_t hiperiso_grub_file_open(enum grub_file_type type, const char *fmt, ...) +{ + va_list ap; + grub_file_t file; + char fullpath[512] = {0}; + + va_start (ap, fmt); + grub_vsnprintf(fullpath, 511, fmt, ap); + va_end (ap); + + file = grub_file_open(fullpath, type); + if (!file) + { + debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno); + grub_errno = 0; + } + + return file; +} + +int hiperiso_is_dir_exist(const char *fmt, ...) +{ + va_list ap; + int len; + char *pos = NULL; + char buf[512] = {0}; + + grub_snprintf(buf, sizeof(buf), "%s", "[ -d \""); + pos = buf + 6; + + va_start (ap, fmt); + len = grub_vsnprintf(pos, 511, fmt, ap); + va_end (ap); + + grub_strncpy(pos + len, "\" ]", 3); + + debug("script exec %s\n", buf); + + if (0 == grub_script_execute_sourcecode(buf)) + { + return 1; + } + + return 0; +} + +int hiperiso_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len) +{ + mz_stream s; + grub_uint8_t *outbuf; + grub_uint8_t gzHdr[10] = + { + 0x1F, 0x8B, /* magic */ + 8, /* z method */ + 0, /* flags */ + 0,0,0,0, /* mtime */ + 4, /* xfl */ + 3, /* OS */ + }; + + grub_memset(&s, 0, sizeof(mz_stream)); + + mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY); + + outbuf = (grub_uint8_t *)mem_out; + + mem_out_len -= sizeof(gzHdr) + 8; + grub_memcpy(outbuf, gzHdr, sizeof(gzHdr)); + outbuf += sizeof(gzHdr); + + s.avail_in = mem_in_len; + s.next_in = mem_in; + + s.avail_out = mem_out_len; + s.next_out = outbuf; + + mz_deflate(&s, MZ_FINISH); + + mz_deflateEnd(&s); + + outbuf += s.total_out; + *(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out); + *(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out); + + return s.total_out + sizeof(gzHdr) + 8; +} + + +#if 0 +hiperiso grub cmds +#endif + +static grub_err_t hiperiso_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args) +{ + if (argc != 1) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name); + } + + if (0 == grub_strcmp(args[0], "on")) + { + g_hiperiso_debug = 1; + grub_env_set("vtdebug_flag", "debug"); + } + else + { + g_hiperiso_debug = 0; + grub_env_set("vtdebug_flag", ""); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + + if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1')) + { + grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name); + grub_printf(" level:\r\n"); + grub_printf(" 01/11: busybox / (+cat log)\r\n"); + grub_printf(" 02/12: initrd / (+cat log)\r\n"); + grub_printf(" 03/13: hook / (+cat log)\r\n"); + grub_printf("\r\n"); + grub_printf(" debug:\r\n"); + grub_printf(" 0: debug is off\r\n"); + grub_printf(" 1: debug is on\r\n"); + grub_printf("\r\n"); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); + } + + g_hiperiso_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16); + + if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0) + { + g_hiperiso_debug_level = 1; + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + return (grub_strstr(args[0], args[1])) ? 0 : 1; +} + +static grub_err_t hiperiso_cmd_istrstr(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_err_t ret = 1; + char *s1 = NULL; + char *s2 = NULL; + + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + s1 = grub_strdup(args[0]); + s2 = grub_strdup(args[1]); + if (s1 == NULL || s2 == NULL) + { + goto end; + } + + hiperiso_str_toupper(s1); + hiperiso_str_toupper(s2); + ret = (grub_strstr(s1, s2)) ? 0 : 1; + +end: + grub_check_free(s1); + grub_check_free(s2); + return ret; +} + +static grub_err_t hiperiso_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *c0, *c1; + + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + c0 = args[0]; + c1 = args[1]; + + while (*c0 && *c1) + { + if (*c0 != *c1) + { + return 1; + } + c0++; + c1++; + } + + if (*c1) + { + return 1; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_strcasebegin(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *c0, *c1; + + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + c0 = args[0]; + c1 = args[1]; + + while (*c0 && *c1) + { + if ((*c0 != *c1) && (*c0 != grub_toupper(*c1))) + { + return 1; + } + c0++; + c1++; + } + + if (*c1) + { + return 1; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args) +{ + long value_long = 0; + char buf[32]; + + if ((argc != 2) || (!hiperiso_is_decimal(args[1]))) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name); + } + + if (GRUB_ERR_NONE != hiperiso_check_decimal_var(args[0], &value_long)) + { + return grub_errno; + } + + value_long += grub_strtol(args[1], NULL, 10); + + grub_snprintf(buf, sizeof(buf), "%ld", value_long); + grub_env_set(args[0], buf); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args) +{ + ulonglong value1 = 0; + ulonglong value2 = 0; + char buf[32]; + + if (argc != 3) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name); + } + + value1 = grub_strtoull(args[0], NULL, 10); + value2 = grub_strtoull(args[1], NULL, 10); + + grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1))); + grub_env_set(args[2], buf); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + char buf[32]; + grub_file_t file; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 2) + { + return rc; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (file == NULL) + { + debug("failed to open file <%s> for udf check\n", args[0]); + return 1; + } + + grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size); + + grub_env_set(args[1], buf); + + grub_file_close(file); + rc = 0; + + return rc; +} + +static grub_err_t hiperiso_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file; + + (void)ctxt; + (void)argc; + (void)args; + + g_wimboot_enable = 0; + g_wimiso_size = 0; + grub_check_free(g_wimiso_path); + grub_check_free(g_wimiso_chunk_list.chunk); + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + return 0; + } + + grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list)); + g_wimiso_chunk_list.chunk = grub_malloc(sizeof(hiperiso_img_chunk) * DEFAULT_CHUNK_NUM); + if (NULL == g_wimiso_chunk_list.chunk) + { + return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n"); + } + + g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM; + g_wimiso_chunk_list.cur_chunk = 0; + + hiperiso_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start); + + g_wimboot_enable = 1; + g_wimiso_path = grub_strdup(args[0]); + g_wimiso_size = (grub_uint32_t)(file->size); + grub_file_close(file); + + return 0; +} + +static grub_err_t hiperiso_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 0; + int totlen = 0; + int offset = 0; + grub_file_t file; + char *buf = NULL; + char *data = NULL; + hiperiso_iso9660_override *dirent; + + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + totlen = sizeof(hiperiso_chain_head); + + if (hiperiso_load_efiboot_template(&buf, &len, &offset)) + { + debug("failed to load efiboot template %d\n", len); + return 1; + } + + totlen += len; + + debug("efiboot template len:%d offset:%d\n", len, offset); + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]); + if (file == NULL) + { + debug("failed to open file <%s>\n", args[0]); + return 1; + } + + if (grub_strncmp(args[0], g_iso_path, grub_strlen(g_iso_path))) + { + file->vlnk = 1; + } + + totlen += hiperiso_align_2k(file->size); + + dirent = (hiperiso_iso9660_override *)(buf + offset); + dirent->first_sector = len / 2048; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size = (grub_uint32_t)file->size; + dirent->size_be = grub_swap_bytes32(dirent->size); + + debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen); + +#ifdef GRUB_MACHINE_EFI + data = (char *)grub_efi_allocate_iso_buf(totlen); +#else + data = (char *)grub_malloc(totlen); +#endif + + hiperiso_fill_os_param(file, (hiperiso_os_param *)data); + + grub_memcpy(data + sizeof(hiperiso_chain_head), buf, len); + grub_check_free(buf); + + grub_file_read(file, data + sizeof(hiperiso_chain_head) + len, file->size); + grub_file_close(file); + + hiperiso_memfile_env_set(args[1], data, (ulonglong)totlen); + + return 0; +} + +grub_err_t hiperiso_cmd_set_wim_prompt(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_hiso_load_prompt = 0; + grub_memset(g_hiso_prompt_msg, 0, sizeof(g_hiso_prompt_msg)); + + if (argc == 2 && args[0][0] == '1') + { + g_hiso_load_prompt = 1; + grub_snprintf(g_hiso_prompt_msg, sizeof(g_hiso_prompt_msg), "%s", args[1]); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +int hiperiso_need_prompt_load_file(void) +{ + return g_hiso_load_prompt; +} + +grub_ssize_t hiperiso_load_file_with_prompt(grub_file_t file, void *buf, grub_ssize_t size) +{ + grub_uint64_t ro = 0; + grub_uint64_t div = 0; + grub_ssize_t left = size; + char *cur = (char *)buf; + + grub_printf("\r%s 1%% ", g_hiso_prompt_msg); + grub_refresh(); + + while (left >= HISO_SIZE_2MB) + { + grub_file_read(file, cur, HISO_SIZE_2MB); + cur += HISO_SIZE_2MB; + left -= HISO_SIZE_2MB; + + div = grub_divmod64((grub_uint64_t)((size - left) * 100), (grub_uint64_t)size, &ro); + if (div < 1) + { + div = 1; + } + grub_printf("\r%s %d%% ", g_hiso_prompt_msg, (int)div); + grub_refresh(); + } + + if (left > 0) + { + grub_file_read(file, cur, left); + } + + grub_printf("\r%s 100%% \n", g_hiso_prompt_msg); + grub_refresh(); + + return size; +} + +static grub_err_t hiperiso_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + char *buf = NULL; + grub_file_t file; + enum grub_file_type type; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 3) + { + return rc; + } + + if (grub_strcmp(args[0], "nodecompress") == 0) + { + type = HIPERISO_FILE_TYPE; + } + else + { + type = GRUB_FILE_TYPE_LINUX_INITRD; + } + + file = hiperiso_grub_file_open(type, "%s", args[1]); + if (file == NULL) + { + debug("failed to open file <%s>\n", args[1]); + return 1; + } + +#ifdef GRUB_MACHINE_EFI + buf = (char *)grub_efi_allocate_chain_buf(file->size); +#else + buf = (char *)grub_malloc(file->size); +#endif + + if (!buf) + { + grub_file_close(file); + return 1; + } + + if (g_hiso_load_prompt) + { + hiperiso_load_file_with_prompt(file, buf, file->size); + } + else + { + grub_file_read(file, buf, file->size); + } + + hiperiso_memfile_env_set(args[2], buf, (ulonglong)(file->size)); + + grub_file_close(file); + rc = 0; + + return rc; +} + +static grub_err_t hiperiso_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + int headlen; + char *buf = NULL; + grub_file_t file; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 2) + { + return rc; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (file == NULL) + { + debug("failed to open file <%s> for udf check\n", args[0]); + return 1; + } + + headlen = sizeof(hiperiso_chain_head); + +#ifdef GRUB_MACHINE_EFI + buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size); +#else + buf = (char *)grub_malloc(headlen + file->size); +#endif + + hiperiso_fill_os_param(file, (hiperiso_os_param *)buf); + + grub_file_read(file, buf + headlen, file->size); + + hiperiso_memfile_env_set(args[1], buf, (ulonglong)(file->size)); + + grub_file_close(file); + rc = 0; + + return rc; +} + +static grub_err_t hiperiso_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (grub_iso9660_is_joliet()) + { + debug("This time has joliet process\n"); + return 0; + } + else + { + return 1; + } +} + +static grub_err_t hiperiso_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + + if (argc != 1) + { + return 1; + } + + if (args[0][0] == '1') + { + grub_iso9660_set_nojoliet(1); + } + else + { + grub_iso9660_set_nojoliet(0); + } + + return 0; +} + +static grub_err_t hiperiso_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int rc = 1; + grub_file_t file; + grub_uint8_t buf[32]; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 1) + { + return rc; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (file == NULL) + { + debug("failed to open file <%s> for udf check\n", args[0]); + return 1; + } + + for (i = 16; i < 32; i++) + { + grub_file_seek(file, i * 2048); + grub_file_read(file, buf, sizeof(buf)); + if (buf[0] == 255) + { + break; + } + } + + i++; + grub_file_seek(file, i * 2048); + grub_file_read(file, buf, sizeof(buf)); + + if (grub_memcmp(buf + 1, "BEA01", 5) == 0) + { + i++; + grub_file_seek(file, i * 2048); + grub_file_read(file, buf, sizeof(buf)); + + if (grub_memcmp(buf + 1, "NSR02", 5) == 0 || + grub_memcmp(buf + 1, "NSR03", 5) == 0) + { + rc = 0; + } + } + + grub_file_close(file); + + debug("ISO UDF: %s\n", rc ? "NO" : "YES"); + + return rc; +} + +static grub_err_t hiperiso_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args) +{ + long value_long1 = 0; + long value_long2 = 0; + + if ((argc != 3) || (!hiperiso_is_decimal(args[0])) || (!hiperiso_is_decimal(args[2]))) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name); + } + + value_long1 = grub_strtol(args[0], NULL, 10); + value_long2 = grub_strtol(args[2], NULL, 10); + + if (0 == grub_strcmp(args[1], "eq")) + { + grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else if (0 == grub_strcmp(args[1], "ne")) + { + grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else if (0 == grub_strcmp(args[1], "gt")) + { + grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else if (0 == grub_strcmp(args[1], "lt")) + { + grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else if (0 == grub_strcmp(args[1], "ge")) + { + grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else if (0 == grub_strcmp(args[1], "le")) + { + grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; + } + else + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name); + } + + return grub_errno; +} + +static grub_err_t hiperiso_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *pos = NULL; + char buf[128] = {0}; + + if (argc != 2) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name); + } + + grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1); + pos = grub_strstr(buf, ","); + if (pos) + { + *pos = 0; + } + + grub_env_set(args[1], buf); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + char buf[256]; + grub_disk_t disk; + char *pos = NULL; + const char *files[] = { "hiperiso.dat", "HIPERISO.DAT" }; + + (void)ctxt; + + if (argc != 1) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name); + } + + for (i = 0; i < (int)ARRAY_SIZE(files); i++) + { + grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]); + if (0 == grub_script_execute_sourcecode(buf)) + { + debug("file %s exist, hiperiso_compatible YES\n", buf); + grub_env_set("hiperiso_compatible", "YES"); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); + } + else + { + debug("file %s NOT exist\n", buf); + } + } + + grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]); + pos = grub_strstr(buf, ")"); + if (pos) + { + *pos = 0; + } + + disk = grub_disk_open(buf); + if (disk) + { + grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf); + grub_disk_close(disk); + + g_img_swap_tmp_buf[703] = 0; + for (i = 318; i < 703; i++) + { + if (g_img_swap_tmp_buf[i] == 'V' && + 0 == grub_strncmp(g_img_swap_tmp_buf + i, HIPERISO_COMPATIBLE_STR, HIPERISO_COMPATIBLE_STR_LEN)) + { + debug("Hiperiso compatible string exist at %d, hiperiso_compatible YES\n", i); + grub_env_set("hiperiso_compatible", "YES"); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); + } + } + } + else + { + debug("failed to open disk <%s>\n", buf); + } + + grub_env_set("hiperiso_compatible", "NO"); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +int hiperiso_cmp_img(img_info *img1, img_info *img2) +{ + char *s1, *s2; + int c1 = 0; + int c2 = 0; + + if (g_plugin_image_list == HIPERISO_IMG_WHITE_LIST) + { + return (img1->plugin_list_index - img2->plugin_list_index); + } + + for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++) + { + c1 = *s1; + c2 = *s2; + + if (0 == g_sort_case_sensitive) + { + if (grub_islower(c1)) + { + c1 = c1 - 'a' + 'A'; + } + + if (grub_islower(c2)) + { + c2 = c2 - 'a' + 'A'; + } + } + + if (c1 != c2) + { + break; + } + } + + return (c1 - c2); +} + +static int hiperiso_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2) +{ + int i = 0; + int c1 = 0; + int c2 = 0; + int len = 0; + char *s1, *s2; + + if (g_plugin_image_list == HIPERISO_IMG_WHITE_LIST) + { + return (node1->plugin_list_index - node2->plugin_list_index); + } + + s1 = node1->dir; + s2 = node2->dir; + len = grub_min(node1->dirlen, node2->dirlen); + + for (i = 0; i < len - 1; i++) + { + c1 = *s1++; + c2 = *s2++; + + if (0 == g_sort_case_sensitive) + { + if (grub_islower(c1)) + { + c1 = c1 - 'a' + 'A'; + } + + if (grub_islower(c2)) + { + c2 = c2 - 'a' + 'A'; + } + } + + if (c1 != c2) + { + return (c1 - c2); + } + } + + if (len == node1->dirlen) + { + c1 = 0; + } + + if (len == node2->dirlen) + { + c2 = 0; + } + + return (c1 - c2); +} + +void hiperiso_swap_img(img_info *img1, img_info *img2) +{ + grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info)); + + grub_memcpy(img1, img2, sizeof(img_info)); + img1->next = g_img_swap_tmp.next; + img1->prev = g_img_swap_tmp.prev; + + g_img_swap_tmp.next = img2->next; + g_img_swap_tmp.prev = img2->prev; + grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info)); +} + +int hiperiso_img_name_valid(const char *filename, grub_size_t namelen) +{ + (void)namelen; + + if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_') + { + return 0; + } + + return 1; +} + +static int hiperiso_vlnk_iterate_partition(struct grub_disk *disk, const grub_partition_t partition, void *data) +{ + hiperiso_vlnk_part *node = NULL; + grub_uint32_t SelfSig; + grub_uint32_t *pSig = (grub_uint32_t *)data; + + /* skip Hiperiso partition 1/2 */ + grub_memcpy(&SelfSig, g_hiperiso_part_info->MBR.BootCode + 0x1b8, 4); + if (partition->number < 2 && SelfSig == *pSig) + { + return 0; + } + + node = grub_zalloc(sizeof(hiperiso_vlnk_part)); + if (node) + { + node->disksig = *pSig; + node->partoffset = (partition->start << GRUB_DISK_SECTOR_BITS); + grub_snprintf(node->disk, sizeof(node->disk) - 1, "%s", disk->name); + grub_snprintf(node->device, sizeof(node->device) - 1, "%s,%d", disk->name, partition->number + 1); + + node->next = g_vlnk_part_list; + g_vlnk_part_list = node; + } + + return 0; +} + +static int hiperiso_vlnk_iterate_disk(const char *name, void *data) +{ + grub_disk_t disk; + grub_uint32_t sig; + + (void)data; + + disk = grub_disk_open(name); + if (disk) + { + grub_disk_read(disk, 0, 0x1b8, 4, &sig); + grub_partition_iterate(disk, hiperiso_vlnk_iterate_partition, &sig); + grub_disk_close(disk); + } + + return 0; +} + +static int hiperiso_vlnk_probe_fs(hiperiso_vlnk_part *cur) +{ + const char *fs[hiperiso_fs_max + 1] = + { + "exfat", "ntfs", "ext2", "xfs", "udf", "fat", "btrfs", NULL + }; + + if (!cur->dev) + { + cur->dev = grub_device_open(cur->device); + } + + if (cur->dev) + { + cur->fs = grub_fs_list_probe(cur->dev, fs); + } + + return 0; +} + +static int hiperiso_check_vlnk_data(hiperiso_vlnk *vlnk, int print, char *dst, int size) +{ + int diskfind = 0; + int partfind = 0; + int filefind = 0; + char *disk, *device; + grub_uint32_t readcrc, calccrc; + hiperiso_vlnk_part *cur; + grub_fs_t fs = NULL; + + if (grub_memcmp(&(vlnk->guid), &g_hiperiso_guid, sizeof(hiperiso_guid))) + { + if (print) + { + grub_printf("VLNK invalid guid\n"); + grub_refresh(); + } + return 1; + } + + readcrc = vlnk->crc32; + vlnk->crc32 = 0; + calccrc = grub_getcrc32c(0, vlnk, sizeof(hiperiso_vlnk)); + if (readcrc != calccrc) + { + if (print) + { + grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc, readcrc); + grub_refresh(); + } + return 1; + } + + if (!g_vlnk_part_list) + { + grub_disk_dev_iterate(hiperiso_vlnk_iterate_disk, NULL); + } + + for (cur = g_vlnk_part_list; cur && filefind == 0; cur = cur->next) + { + if (cur->disksig == vlnk->disk_signature) + { + diskfind = 1; + disk = cur->disk; + if (cur->partoffset == vlnk->part_offset) + { + partfind = 1; + device = cur->device; + + if (cur->probe == 0) + { + cur->probe = 1; + hiperiso_vlnk_probe_fs(cur); + } + + if (!fs) + { + fs = cur->fs; + } + + if (cur->fs) + { + struct grub_file file; + + grub_memset(&file, 0, sizeof(file)); + file.device = cur->dev; + if (cur->fs->fs_open(&file, vlnk->filepath) == GRUB_ERR_NONE) + { + filefind = 1; + cur->fs->fs_close(&file); + grub_snprintf(dst, size - 1, "(%s)%s", cur->device, vlnk->filepath); + } + else + { + grub_errno = 0; + } + } + } + } + } + + if (print) + { + grub_printf("\n==== VLNK Information ====\n" + "Disk Signature: %08x\n" + "Partition Offset: %llu\n" + "File Path: <%s>\n\n", + vlnk->disk_signature, (ulonglong)vlnk->part_offset, vlnk->filepath); + + if (diskfind) + { + grub_printf("Disk Find: [ YES ] [ %s ]\n", disk); + } + else + { + grub_printf("Disk Find: [ NO ]\n"); + } + + if (partfind) + { + grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device, fs ? fs->name : "N/A"); + } + else + { + grub_printf("Part Find: [ NO ]\n"); + } + grub_printf("File Find: [ %s ]\n", filefind ? "YES" : "NO"); + if (filefind) + { + grub_printf("VLNK File: <%s>\n", dst); + } + + grub_printf("\n"); + grub_refresh(); + } + + return (1 - filefind); +} + +int hiperiso_add_vlnk_file(char *dir, const char *name) +{ + int rc = 1; + char src[512]; + char dst[512]; + grub_file_t file = NULL; + hiperiso_vlnk vlnk; + + if (!dir) + { + grub_snprintf(src, sizeof(src), "%s%s", g_iso_path, name); + } + else if (dir[0] == '/') + { + grub_snprintf(src, sizeof(src), "%s%s%s", g_iso_path, dir, name); + } + else + { + grub_snprintf(src, sizeof(src), "%s/%s%s", g_iso_path, dir, name); + } + + file = grub_file_open(src, HIPERISO_FILE_TYPE); + if (!file) + { + return 1; + } + + grub_memset(&vlnk, 0, sizeof(vlnk)); + grub_file_read(file, &vlnk, sizeof(vlnk)); + grub_file_close(file); + + if (hiperiso_check_vlnk_data(&vlnk, 0, dst, sizeof(dst)) == 0) + { + rc = grub_file_add_vlnk(src, dst); + } + + return rc; +} + +static int hiperiso_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + //int i = 0; + int type = 0; + int ignore = 0; + int index = 0; + int vlnk = 0; + grub_size_t len; + img_info *img; + img_info *tail; + const menu_tip *tip; + img_iterator_node *tmp; + img_iterator_node *new_node; + img_iterator_node *node = (img_iterator_node *)data; + + if (g_enumerate_time_checked == 0) + { + g_enumerate_finish_time_ms = grub_get_time_ms(); + if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000) + { + grub_cls(); + grub_printf("\n\n Hiperiso scanning files, please wait...\n"); + grub_refresh(); + g_enumerate_time_checked = 1; + } + } + + len = grub_strlen(filename); + + if (info->dir) + { + if (node->level + 1 > g_img_max_search_level) + { + return 0; + } + + if ((len == 1 && filename[0] == '.') || + (len == 2 && filename[0] == '.' && filename[1] == '.')) + { + return 0; + } + + if (!hiperiso_img_name_valid(filename, len)) + { + return 0; + } + + if (g_filt_trash_dir) + { + if (0 == grub_strncmp(filename, ".trash-", 7) || + 0 == grub_strcmp(filename, ".Trashes") || + 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12)) + { + return 0; + } + } + + if (g_plugin_image_list == HIPERISO_IMG_WHITE_LIST) + { + grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename); + index = hiperiso_plugin_get_image_list_index(hiso_class_directory, g_img_swap_tmp_buf); + if (index == 0) + { + debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf); + return 0; + } + } + + new_node = grub_zalloc(sizeof(img_iterator_node)); + if (new_node) + { + new_node->level = node->level + 1; + new_node->plugin_list_index = index; + new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename); + + g_enum_fs->fs_dir(g_enum_dev, new_node->dir, hiperiso_check_ignore_flag, &ignore); + if (ignore) + { + debug("Directory %s ignored...\n", new_node->dir); + grub_free(new_node); + return 0; + } + + new_node->tail = node->tail; + + new_node->parent = node; + if (!node->firstchild) + { + node->firstchild = new_node; + } + + if (g_img_iterator_tail) + { + g_img_iterator_tail->next = new_node; + g_img_iterator_tail = new_node; + } + else + { + g_img_iterator_head.next = new_node; + g_img_iterator_tail = new_node; + } + } + } + else + { + debug("Find a file %s\n", filename); + if (len < 4) + { + return 0; + } + + if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso")) + { + type = img_type_iso; + } + else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim"))) + { + type = img_type_wim; + } + else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") || + (len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx")))) + { + type = img_type_vhd; + } + #ifdef GRUB_MACHINE_EFI + else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi")) + { + type = img_type_efi; + } + #endif + else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img")) + { + if (len == 18 && grub_strncmp(filename, "hiperiso_", 7) == 0) + { + if (grub_strncmp(filename + 7, "wimboot", 7) == 0 || + grub_strncmp(filename + 7, "vhdboot", 7) == 0) + { + return 0; + } + } + type = img_type_img; + } + else if (FILE_FLT(HISO) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".hiso")) + { + type = img_type_hiso; + } + else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg")) + { + if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.')) + { + grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename); + hiperiso_plugin_add_custom_boot(g_img_swap_tmp_buf); + } + return 0; + } + else + { + return 0; + } + + if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_') + { + return 0; + } + + if (g_plugin_image_list) + { + grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename); + index = hiperiso_plugin_get_image_list_index(hiso_class_image_file, g_img_swap_tmp_buf); + if (HIPERISO_IMG_WHITE_LIST == g_plugin_image_list && index == 0) + { + debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf); + return 0; + } + else if (HIPERISO_IMG_BLACK_LIST == g_plugin_image_list && index > 0) + { + debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index); + return 0; + } + } + + if (info->size == HISO_FILT_MIN_FILE_SIZE || info->size == 0) + { + if (grub_file_is_vlnk_suffix(filename, len)) + { + vlnk = 1; + if (hiperiso_add_vlnk_file(node->dir, filename) != 0) + { + return 0; + } + } + } + + img = grub_zalloc(sizeof(img_info)); + if (img) + { + img->type = type; + img->plugin_list_index = index; + grub_snprintf(img->name, sizeof(img->name), "%s", filename); + + img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name); + + img->size = info->size; + if (vlnk || 0 == img->size) + { + if (node->dir[0] == '/') + { + img->size = hiperiso_grub_get_file_size("%s%s%s", g_iso_path, node->dir, filename); + } + else + { + img->size = hiperiso_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename); + } + } + + if (img->size < HISO_FILT_MIN_FILE_SIZE) + { + debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size); + grub_free(img); + return 0; + } + + if (g_hiperiso_img_list) + { + tail = *(node->tail); + img->prev = tail; + tail->next = img; + } + else + { + g_hiperiso_img_list = img; + } + + img->id = g_hiperiso_img_count; + img->parent = node; + if (node && NULL == node->firstiso) + { + node->firstiso = img; + } + + node->isocnt++; + tmp = node->parent; + while (tmp) + { + tmp->isocnt++; + tmp = tmp->parent; + } + + *((img_info **)(node->tail)) = img; + g_hiperiso_img_count++; + + img->alias = hiperiso_plugin_get_menu_alias(hiso_alias_image_file, img->path); + + tip = hiperiso_plugin_get_menu_tip(hiso_tip_image_file, img->path); + if (tip) + { + img->tip1 = tip->tip1; + img->tip2 = tip->tip2; + } + + img->class = hiperiso_plugin_get_menu_class(hiso_class_image_file, img->name, img->path); + if (!img->class) + { + img->class = g_menu_class[type]; + } + img->menu_prefix = g_menu_prefix[type]; + + if (img_type_iso == type) + { + if (hiperiso_plugin_check_memdisk(img->path)) + { + img->menu_prefix = "miso"; + } + } + else if (img_type_img == type) + { + if (hiperiso_plugin_check_memdisk(img->path)) + { + img->menu_prefix = "mimg"; + } + } + + debug("Add %s%s to list %d\n", node->dir, filename, g_hiperiso_img_count); + } + } + + return 0; +} + +int hiperiso_fill_data(grub_uint32_t buflen, char *buffer) +{ + int len = GRUB_UINT_MAX; + const char *value = NULL; + char name[32] = {0}; + char plat[32] = {0}; + char guidstr[32] = {0}; + hiperiso_guid guid = HIPERISO_GUID; + const char *fmt1 = NULL; + const char *fmt2 = NULL; + const char *fmt3 = NULL; + grub_uint32_t *puint = (grub_uint32_t *)name; + grub_uint32_t *puint2 = (grub_uint32_t *)plat; + const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 }; + const char fmtcode[]={ + 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70, + 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25, + 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78, + 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F, + 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, + 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00 + }; + + grub_memset(name, 0, sizeof(name)); + puint[0] = grub_swap_bytes32(0x56454e54); + puint[3] = grub_swap_bytes32(0x4f4e0000); + puint[2] = grub_swap_bytes32(0x45525349); + puint[1] = grub_swap_bytes32(0x4f595f56); + value = hiperiso_get_env(name); + + grub_memset(name, 0, sizeof(name)); + puint[1] = grub_swap_bytes32(0x5f544f50); + puint[0] = grub_swap_bytes32(0x56544c45); + fmt1 = hiperiso_get_env(name); + if (!fmt1) + { + fmt1 = fmtdata; + } + + grub_memset(name, 0, sizeof(name)); + puint[1] = grub_swap_bytes32(0x5f4c4654); + puint[0] = grub_swap_bytes32(0x56544c45); + fmt2 = hiperiso_get_env(name); + + grub_memset(name, 0, sizeof(name)); + puint[1] = grub_swap_bytes32(0x5f434c52); + puint[0] = grub_swap_bytes32(0x56544c45); + fmt3 = hiperiso_get_env(name); + + grub_memcpy(guidstr, &guid, sizeof(guid)); + + puint2[0] = grub_swap_bytes32(g_hiperiso_plat_data); + + /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wformat-nonliteral" + len = grub_snprintf(buffer, buflen, fmtcode, + fmt1 ? fmt1 : fmtdata, + fmt2 ? fmt2 : fmtdata + 4, + value ? value : "", plat, guidstr, + fmt3 ? fmt3 : fmtdata + 6); + #pragma GCC diagnostic pop + + grub_memset(name, 0, sizeof(name)); + puint[0] = grub_swap_bytes32(0x76746f79); + puint[2] = grub_swap_bytes32(0x656e7365); + puint[1] = grub_swap_bytes32(0x5f6c6963); + hiperiso_set_env(name, guidstr); + + return len; +} + +static int +hiperiso_password_get (char buf[], unsigned buf_size) +{ + unsigned i, cur_len = 0; + int key; + struct grub_term_coordinate *pos = grub_term_save_pos (); + + while (1) + { + key = grub_getkey (); + if (key == '\n' || key == '\r') + break; + + if (key == GRUB_TERM_ESC) + { + cur_len = 0; + break; + } + + if (key == '\b') + { + if (cur_len) + { + grub_term_restore_pos (pos); + for (i = 0; i < cur_len; i++) + grub_xputs (" "); + grub_term_restore_pos (pos); + cur_len--; + for (i = 0; i < cur_len; i++) + grub_xputs ("*"); + grub_refresh (); + } + continue; + } + + if (!grub_isprint (key)) + continue; + + if (cur_len + 2 < buf_size) + buf[cur_len++] = key; + grub_xputs ("*"); + grub_refresh (); + } + + grub_memset (buf + cur_len, 0, buf_size - cur_len); + + grub_xputs ("\n"); + grub_refresh (); + grub_free (pos); + + return (key != GRUB_TERM_ESC); +} + +static int hiperiso_get_password(char buf[], unsigned buf_size) +{ + const char *env = NULL; + + env = grub_env_get("HISO_SHOW_PASSWORD_ASTERISK"); + if (env && env[0] == '0' && env[1] == 0) + { + return grub_password_get(buf, buf_size); + } + else + { + return hiperiso_password_get(buf, buf_size); + } +} + +int hiperiso_check_password(const hiso_password *pwd, int retry) +{ + int offset; + char input[256]; + grub_uint8_t md5[16]; + + while (retry--) + { + grub_memset(input, 0, sizeof(input)); + + grub_printf("Enter password: "); + grub_refresh(); + + if (pwd->type == HISO_PASSWORD_TXT) + { + hiperiso_get_password(input, 128); + if (grub_strcmp(pwd->text, input) == 0) + { + return 0; + } + } + else if (pwd->type == HISO_PASSWORD_MD5) + { + hiperiso_get_password(input, 128); + grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input)); + if (grub_memcmp(pwd->md5, md5, 16) == 0) + { + return 0; + } + } + else if (pwd->type == HISO_PASSWORD_SALT_MD5) + { + offset = (int)grub_snprintf(input, 128, "%s", pwd->salt); + hiperiso_get_password(input + offset, 128); + + grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input)); + if (grub_memcmp(pwd->md5, md5, 16) == 0) + { + return 0; + } + } + + grub_printf("Invalid password!\n\n"); + grub_refresh(); + } + + return 1; +} + +static img_info * hiperiso_get_min_iso(img_iterator_node *node) +{ + img_info *minimg = NULL; + img_info *img = (img_info *)(node->firstiso); + + while (img && (img_iterator_node *)(img->parent) == node) + { + if (img->select == 0 && (NULL == minimg || hiperiso_cmp_img(img, minimg) < 0)) + { + minimg = img; + } + img = img->next; + } + + if (minimg) + { + minimg->select = 1; + } + + return minimg; +} + +static img_iterator_node * hiperiso_get_min_child(img_iterator_node *node) +{ + img_iterator_node *Minchild = NULL; + img_iterator_node *child = node->firstchild; + + while (child && child->parent == node) + { + if (child->select == 0 && (NULL == Minchild || hiperiso_cmp_subdir(child, Minchild) < 0)) + { + Minchild = child; + } + child = child->next; + } + + if (Minchild) + { + Minchild->select = 1; + } + + return Minchild; +} + +static int hiperiso_dynamic_tree_menu(img_iterator_node *node) +{ + int offset = 1; + img_info *img = NULL; + const char *dir_class = NULL; + const char *dir_alias = NULL; + img_iterator_node *child = NULL; + const menu_tip *tip = NULL; + + if (node->isocnt == 0 || node->done == 1) + { + return 0; + } + + if (node->parent && node->parent->dirlen < node->dirlen) + { + offset = node->parent->dirlen; + } + + if (node == &g_img_iterator_head) + { + if (g_default_menu_mode == 0) + { + if (g_tree_view_menu_style == 0) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"%-10s [%s]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n" + "}\n", "<--", hiperiso_get_vmenu_title("VTLANG_RET_TO_LISTVIEW")); + } + else + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"[%s]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n" + "}\n", hiperiso_get_vmenu_title("VTLANG_RET_TO_LISTVIEW")); + } + } + + g_tree_script_pre = g_tree_script_pos; + } + else + { + node->dir[node->dirlen - 1] = 0; + dir_class = hiperiso_plugin_get_menu_class(hiso_class_directory, node->dir, node->dir); + if (!dir_class) + { + dir_class = "hisodir"; + } + + tip = hiperiso_plugin_get_menu_tip(hiso_tip_directory, node->dir); + + dir_alias = hiperiso_plugin_get_menu_alias(hiso_alias_directory, node->dir); + if (dir_alias) + { + if (g_tree_view_menu_style == 0) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n", + "DIR", dir_alias, dir_class, node->dir + offset, tip); + } + else + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n", + dir_alias, dir_class, node->dir + offset, tip); + } + } + else + { + dir_alias = node->dir + offset; + + if (g_tree_view_menu_style == 0) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n", + "DIR", dir_alias, dir_class, node->dir + offset, tip); + } + else + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n", + dir_alias, dir_class, node->dir + offset, tip); + } + } + + if (g_tree_view_menu_style == 0) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"%-10s [%s/..]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n" + "}\n", "<--", node->dir); + } + else + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"[%s/..]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n" + "}\n", node->dir); + } + } + + while ((child = hiperiso_get_min_child(node)) != NULL) + { + hiperiso_dynamic_tree_menu(child); + } + + while ((img = hiperiso_get_min_iso(node)) != NULL) + { + if (g_tree_view_menu_style == 0) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n" + " %s_%s \n" + "}\n", + grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT), + img->unsupport ? "[***********] " : "", + img->alias ? img->alias : img->name, img->class, img, + img->menu_prefix, + img->unsupport ? "unsupport_menuentry" : "common_menuentry"); + } + else + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, + "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n" + " %s_%s \n" + "}\n", + img->unsupport ? "[***********] " : "", + img->alias ? img->alias : img->name, img->class, img, + img->menu_prefix, + img->unsupport ? "unsupport_menuentry" : "common_menuentry"); + } + } + + if (node != &g_img_iterator_head) + { + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, "}\n"); + } + + node->done = 1; + return 0; +} + +static int hiperiso_set_default_menu(void) +{ + int img_len = 0; + char *pos = NULL; + char *end = NULL; + char *def = NULL; + const char *strdata = NULL; + img_info *cur = NULL; + img_info *default_node = NULL; + const char *default_image = NULL; + + default_image = hiperiso_get_env("HISO_DEFAULT_IMAGE"); + if (default_image && default_image[0] == '/') + { + img_len = grub_strlen(default_image); + + for (cur = g_hiperiso_img_list; cur; cur = cur->next) + { + if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0) + { + default_node = cur; + break; + } + } + + if (!default_node) + { + return 1; + } + + if (0 == g_default_menu_mode) + { + hiso_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%p'\n", default_node); + } + else + { + def = grub_strdup(default_image); + if (!def) + { + return 1; + } + + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\''); + + strdata = hiperiso_get_env("HISO_DEFAULT_SEARCH_ROOT"); + if (strdata && strdata[0] == '/') + { + pos = def + grub_strlen(strdata); + if (*pos == '/') + { + pos++; + } + } + else + { + pos = def + 1; + } + + while ((end = grub_strchr(pos, '/')) != NULL) + { + *end = 0; + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos); + pos = end + 1; + } + + hiso_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%p'\n", default_node); + grub_free(def); + } + } + + return 0; +} + +static grub_err_t hiperiso_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args) +{ + img_info *next = NULL; + img_info *cur = g_hiperiso_img_list; + + (void)ctxt; + (void)argc; + (void)args; + + while (cur) + { + next = cur->next; + grub_free(cur); + cur = next; + } + + g_hiperiso_img_list = NULL; + g_hiperiso_img_count = 0; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args) +{ + long img_id = 0; + img_info *cur = g_hiperiso_img_list; + + (void)ctxt; + + if (argc != 2 || (!hiperiso_is_decimal(args[0]))) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name); + } + + img_id = grub_strtol(args[0], NULL, 10); + if (img_id >= g_hiperiso_img_count) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_hiperiso_img_count); + } + + debug("Find image %ld name \n", img_id); + + while (cur && img_id > 0) + { + img_id--; + cur = cur->next; + } + + if (!cur) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images"); + } + + debug("image name is %s\n", cur->name); + + grub_env_set(args[1], cur->name); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 0; + char id[32] = {0}; + img_info *cur = g_hiperiso_img_list; + + (void)ctxt; + + if (argc != 1) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name); + } + + len = (int)grub_strlen(args[0]); + + while (cur) + { + if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path)) + { + break; + } + cur = cur->next; + } + + if (!cur) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image"); + } + + grub_snprintf(id, sizeof(id), "VID_%p", cur); + grub_env_set("chosen", id); + grub_env_export("chosen"); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static char g_fake_vlnk_src[512]; +static char g_fake_vlnk_dst[512]; +static grub_uint64_t g_fake_vlnk_size; +static grub_err_t hiperiso_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_fake_vlnk_size = (grub_uint64_t)grub_strtoull(args[2], NULL, 10); + + grub_strncpy(g_fake_vlnk_dst, args[0], sizeof(g_fake_vlnk_dst)); + grub_snprintf(g_fake_vlnk_src, sizeof(g_fake_vlnk_src), "%s/________HIPERISOVLNK.vlnk.%s", g_iso_path, args[1]); + + grub_file_hiso_vlnk(g_fake_vlnk_src, g_fake_vlnk_dst); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_fake_vlnk_src[0] = 0; + g_fake_vlnk_dst[0] = 0; + g_fake_vlnk_size = 0; + grub_file_hiso_vlnk(NULL, NULL); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + + +static grub_err_t hiperiso_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char value[32]; + char *pos = NULL; + char *last = NULL; + const char *id = NULL; + img_info *cur = NULL; + + (void)ctxt; + + if (argc < 1 || argc > 3) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name); + } + + if (g_fake_vlnk_src[0] && g_fake_vlnk_dst[0]) + { + pos = grub_strchr(g_fake_vlnk_src, '/'); + grub_env_set(args[0], pos); + if (argc > 1) + { + grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(g_fake_vlnk_size)); + grub_env_set(args[1], value); + } + + if (argc > 2) + { + for (last = pos; *pos; pos++) + { + if (*pos == '/') + { + last = pos; + } + } + grub_env_set(args[2], last + 1); + } + + goto end; + } + + id = grub_env_get("chosen"); + + pos = grub_strstr(id, "VID_"); + if (pos) + { + cur = (img_info *)(void *)grub_strtoul(pos + 4, NULL, 16); + } + else + { + cur = g_hiperiso_img_list; + } + + if (!cur) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image"); + } + + grub_env_set(args[0], cur->path); + + if (argc > 1) + { + grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size)); + grub_env_set(args[1], value); + } + + if (argc > 2) + { + grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size)); + grub_env_set(args[2], cur->name); + } + +end: + g_svd_replace_offset = 0; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + + +static grub_err_t hiperiso_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len; + grub_fs_t fs; + grub_device_t dev = NULL; + img_info *cur = NULL; + img_info *tail = NULL; + img_info *min = NULL; + img_info *head = NULL; + const char *strdata = NULL; + char *device_name = NULL; + char buf[32]; + img_iterator_node *node = NULL; + img_iterator_node *tmp = NULL; + + (void)ctxt; + + if (argc != 2) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name); + } + + if (g_hiperiso_img_list || g_hiperiso_img_count) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list"); + } + + HISO_CMD_CHECK(1); + + g_enumerate_time_checked = 0; + g_enumerate_start_time_ms = grub_get_time_ms(); + + strdata = hiperiso_get_env("HISO_FILT_DOT_UNDERSCORE_FILE"); + if (strdata && strdata[0] == '1' && strdata[1] == 0) + { + g_filt_dot_underscore_file = 1; + } + + strdata = hiperiso_get_env("HISO_FILT_TRASH_DIR"); + if (strdata && strdata[0] == '0' && strdata[1] == 0) + { + g_filt_trash_dir = 0; + } + + strdata = hiperiso_get_env("HISO_SORT_CASE_SENSITIVE"); + if (strdata && strdata[0] == '1' && strdata[1] == 0) + { + g_sort_case_sensitive = 1; + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + goto fail; + } + + g_enum_dev = dev = grub_device_open(device_name); + if (!dev) + { + goto fail; + } + + g_enum_fs = fs = grub_fs_probe(dev); + if (!fs) + { + goto fail; + } + + if (hiperiso_get_fs_type(fs->name) >= hiperiso_fs_max) + { + debug("unsupported fs:<%s>\n", fs->name); + hiperiso_set_env("HISO_NO_ISO_TIP", "unsupported file system"); + goto fail; + } + + hiperiso_set_env("hiso_iso_fs", fs->name); + + strdata = hiperiso_get_env("HISO_DEFAULT_MENU_MODE"); + if (strdata && strdata[0] == '1') + { + g_default_menu_mode = 1; + } + + grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head)); + + grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]); + + strdata = hiperiso_get_env("HISO_DEFAULT_SEARCH_ROOT"); + if (strdata && strdata[0] == '/') + { + len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata); + if (g_img_iterator_head.dir[len - 1] != '/') + { + g_img_iterator_head.dir[len++] = '/'; + } + g_img_iterator_head.dirlen = len; + } + else + { + g_img_iterator_head.dirlen = 1; + grub_strcpy(g_img_iterator_head.dir, "/"); + } + + g_img_iterator_head.tail = &tail; + + if (g_img_max_search_level < 0) + { + g_img_max_search_level = GRUB_INT_MAX; + strdata = hiperiso_get_env("HISO_MAX_SEARCH_LEVEL"); + if (strdata && hiperiso_is_decimal(strdata)) + { + g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10); + } + } + + g_hiso_file_flt[HISO_FILE_FLT_ISO] = hiperiso_control_get_flag("HISO_FILE_FLT_ISO"); + g_hiso_file_flt[HISO_FILE_FLT_WIM] = hiperiso_control_get_flag("HISO_FILE_FLT_WIM"); + g_hiso_file_flt[HISO_FILE_FLT_EFI] = hiperiso_control_get_flag("HISO_FILE_FLT_EFI"); + g_hiso_file_flt[HISO_FILE_FLT_IMG] = hiperiso_control_get_flag("HISO_FILE_FLT_IMG"); + g_hiso_file_flt[HISO_FILE_FLT_VHD] = hiperiso_control_get_flag("HISO_FILE_FLT_VHD"); + g_hiso_file_flt[HISO_FILE_FLT_HISO] = hiperiso_control_get_flag("HISO_FILE_FLT_HISO"); + + for (node = &g_img_iterator_head; node; node = node->next) + { + fs->fs_dir(dev, node->dir, hiperiso_collect_img_files, node); + } + + strdata = hiperiso_get_env("HISO_TREE_VIEW_MENU_STYLE"); + if (strdata && strdata[0] == '1' && strdata[1] == 0) + { + g_tree_view_menu_style = 1; + } + + hiperiso_set_default_menu(); + + for (node = &g_img_iterator_head; node; node = node->next) + { + hiperiso_dynamic_tree_menu(node); + } + + /* free node */ + node = g_img_iterator_head.next; + while (node) + { + tmp = node->next; + grub_free(node); + node = tmp; + } + + /* sort image list by image name */ + while (g_hiperiso_img_list) + { + min = g_hiperiso_img_list; + for (cur = g_hiperiso_img_list->next; cur; cur = cur->next) + { + if (hiperiso_cmp_img(min, cur) > 0) + { + min = cur; + } + } + + if (min->prev) + { + min->prev->next = min->next; + } + + if (min->next) + { + min->next->prev = min->prev; + } + + if (min == g_hiperiso_img_list) + { + g_hiperiso_img_list = min->next; + } + + if (head == NULL) + { + head = tail = min; + min->prev = NULL; + min->next = NULL; + } + else + { + tail->next = min; + min->prev = tail; + min->next = NULL; + tail = min; + } + } + + g_hiperiso_img_list = head; + + if (g_default_menu_mode == 1) + { + hiso_ssprintf(g_list_script_buf, g_list_script_pos, + "menuentry \"%s [%s]\" --class=\"hisoret\" HISO_RET {\n " + " echo 'return ...' \n" + "}\n", "<--", hiperiso_get_vmenu_title("VTLANG_RET_TO_TREEVIEW")); + } + + for (cur = g_hiperiso_img_list; cur; cur = cur->next) + { + hiso_ssprintf(g_list_script_buf, g_list_script_pos, + "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n" + " %s_%s \n" + "}\n", + cur->unsupport ? "[***********] " : "", + cur->alias ? cur->alias : cur->name, cur->class, cur, + cur->menu_prefix, + cur->unsupport ? "unsupport_menuentry" : "common_menuentry"); + } + + g_tree_script_buf[g_tree_script_pos] = 0; + g_list_script_buf[g_list_script_pos] = 0; + + grub_snprintf(buf, sizeof(buf), "%d", g_hiperiso_img_count); + grub_env_set(args[1], buf); + +fail: + + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +int hiperiso_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature) +{ + grub_disk_t disk; + char *device_name; + char *pos; + char *pos2; + + device_name = grub_file_get_device_name(filename); + if (!device_name) + { + return 1; + } + + pos = device_name; + if (pos[0] == '(') + { + pos++; + } + + pos2 = grub_strstr(pos, ","); + if (!pos2) + { + pos2 = grub_strstr(pos, ")"); + } + + if (pos2) + { + *pos2 = 0; + } + + disk = grub_disk_open(pos); + if (disk) + { + grub_disk_read(disk, 0, 0x180, 16, guid); + grub_disk_read(disk, 0, 0x1b8, 4, signature); + grub_disk_close(disk); + } + else + { + return 1; + } + + grub_free(device_name); + return 0; +} + +grub_uint32_t hiperiso_get_iso_boot_catlog(grub_file_t file) +{ + eltorito_descriptor desc; + + grub_memset(&desc, 0, sizeof(desc)); + grub_file_seek(file, 17 * 2048); + grub_file_read(file, &desc, sizeof(desc)); + + if (desc.type != 0 || desc.version != 1) + { + return 0; + } + + if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 || + grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0) + { + return 0; + } + + return desc.sector; +} + +static grub_uint32_t hiperiso_get_bios_eltorito_rba(grub_file_t file, grub_uint32_t sector) +{ + grub_uint8_t buf[512]; + + grub_file_seek(file, sector * 2048); + grub_file_read(file, buf, sizeof(buf)); + + if (buf[0] == 0x01 && buf[1] == 0x00 && + buf[30] == 0x55 && buf[31] == 0xaa && buf[32] == 0x88) + { + return *((grub_uint32_t *)(buf + 40)); + } + + return 0; +} + +int hiperiso_has_efi_eltorito(grub_file_t file, grub_uint32_t sector) +{ + int i; + int x86count = 0; + grub_uint8_t buf[512]; + grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C }; + + grub_file_seek(file, sector * 2048); + grub_file_read(file, buf, sizeof(buf)); + + if (buf[0] == 0x01 && buf[1] == 0xEF) + { + debug("%s efi eltorito in Validation Entry\n", file->name); + return 1; + } + + if (buf[0] == 0x01 && buf[1] == 0x00) + { + x86count++; + } + + for (i = 64; i < (int)sizeof(buf); i += 32) + { + if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF) + { + debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]); + return 1; + } + + if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1) + { + debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]); + return 1; + } + } + + if (x86count && buf[32] == 0x88 && buf[33] == 0x04) + { + for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++) + { + if (buf[36] == parttype[i]) + { + debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]); + return 1; + } + } + } + + debug("%s does not contain efi eltorito\n", file->name); + return 0; +} + +void hiperiso_fill_os_param(grub_file_t file, hiperiso_os_param *param) +{ + char *pos; + const char *fs = NULL; + const char *val = NULL; + const char *cdprompt = NULL; + grub_uint32_t i; + grub_uint8_t chksum = 0; + grub_disk_t disk; + + disk = file->device->disk; + grub_memcpy(¶m->guid, &g_hiperiso_guid, sizeof(hiperiso_guid)); + + param->hiso_disk_size = disk->total_sectors * (1 << disk->log_sector_size); + param->hiso_disk_part_id = disk->partition->number + 1; + param->hiso_disk_part_type = hiperiso_get_fs_type(file->fs->name); + + pos = grub_strstr(file->name, "/"); + if (!pos) + { + pos = file->name; + } + + grub_snprintf(param->hiso_img_path, sizeof(param->hiso_img_path), "%s", pos); + + hiperiso_get_disk_guid(file->name, param->hiso_disk_guid, param->hiso_disk_signature); + + param->hiso_img_size = file->size; + + param->hiso_reserved[0] = g_hiperiso_break_level; + param->hiso_reserved[1] = g_hiperiso_debug_level; + + param->hiso_reserved[2] = g_hiperiso_chain_type; + + /* Windows CD/DVD prompt 0:suppress 1:reserved */ + param->hiso_reserved[4] = 0; + if (g_hiperiso_chain_type == 1) /* Windows */ + { + cdprompt = hiperiso_get_env("HISO_WINDOWS_CD_PROMPT"); + if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0) + { + param->hiso_reserved[4] = 1; + } + } + + fs = hiperiso_get_env("hiperiso_fs_probe"); + if (fs && grub_strcmp(fs, "udf") == 0) + { + param->hiso_reserved[3] = 1; + } + + param->hiso_reserved[5] = 0; + val = hiperiso_get_env("HISO_LINUX_REMOUNT"); + if (val && val[0] == '1' && val[1] == 0) + { + param->hiso_reserved[5] = 1; + } + + /* hiperiso_disk_signature used for vlnk */ + param->hiso_reserved[6] = file->vlnk; + grub_memcpy(param->hiso_reserved + 7, g_hiperiso_part_info->MBR.BootCode + 0x1b8, 4); + + + /* Windows UEFI force resolution lock */ + if (g_hiperiso_chain_type == 1) /* Windows */ + { + val = hiperiso_get_env("HISO_WIN_UEFI_RES_LOCK"); + if (val && val[1] == 0) + { + if (val[0] == '1') + { + param->hiso_reserved[11] = 1; + } + else if (val[0] == '2') + { + param->hiso_reserved[11] = 2; + } + } + } + + + /* calculate checksum */ + for (i = 0; i < sizeof(hiperiso_os_param); i++) + { + chksum += *((grub_uint8_t *)param + i); + } + param->chksum = (grub_uint8_t)(0x100 - chksum); + + return; +} + +static const char* g_chunk_err_msg[HISO_CHUNK_ERR_MAX] = +{ + "success", + "File system use more than 1 disks! (maybe RAID)", + "File system enable RAID feature, this is NOT supported!", + "File is compressed in disk, this is not supported!", + "File not flat in disk! (maybe compressed)", + "Read buffer overflow!", +}; + +static const char * hiperiso_get_chunk_err_msg(grub_uint32_t err) +{ + if (err < HISO_CHUNK_ERR_MAX) + { + return g_chunk_err_msg[err]; + } + + return "XXXX"; +} + +int hiperiso_check_block_list(grub_file_t file, hiperiso_img_chunk_list *chunklist, +grub_disk_addr_t start, char *err, grub_uint32_t len) +{ + grub_uint32_t i = 0; + grub_uint64_t total = 0; + grub_uint64_t fileblk = 0; + hiperiso_img_chunk *chunk = NULL; + + if (chunklist->err_code) + { + if (err) + { + grub_snprintf(err, len, "%s", hiperiso_get_chunk_err_msg(chunklist->err_code)); + } + + return 1; + } + + if (err) + { + grub_snprintf(err, len, "Unsupported chunk list."); + } + + for (i = 0; i < chunklist->cur_chunk; i++) + { + chunk = chunklist->chunk + i; + + if (chunk->disk_start_sector <= start) + { + debug("%u disk start invalid %lu\n", i, (ulong)start); + return 1; + } + + total += chunk->disk_end_sector + 1 - chunk->disk_start_sector; + } + + fileblk = (file->size + 511) / 512; + + if (total != fileblk) + { + debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk); + if ((file->size % 512) && (total + 1 == fileblk)) + { + debug("maybe img file to be processed.\n"); + return 0; + } + + return 1; + } + + return 0; +} + +int hiperiso_get_block_list(grub_file_t file, hiperiso_img_chunk_list *chunklist, grub_disk_addr_t start) +{ + int fs_type; + int len; + grub_uint32_t i = 0; + grub_uint32_t sector = 0; + grub_uint32_t count = 0; + grub_off_t size = 0; + grub_off_t read = 0; + + fs_type = hiperiso_get_fs_type(file->fs->name); + if (fs_type == hiperiso_fs_exfat) + { + grub_fat_get_file_chunk(start, file, chunklist); + } + else if (fs_type == hiperiso_fs_ext) + { + grub_ext_get_file_chunk(start, file, chunklist); + } + else if (fs_type == hiperiso_fs_btrfs) + { + grub_btrfs_get_file_chunk(start, file, chunklist); + } + else + { + file->read_hook = (grub_disk_read_hook_t)(void *)grub_disk_blocklist_read; + file->read_hook_data = chunklist; + + for (size = file->size; size > 0; size -= read) + { + read = (size > HISO_SIZE_1GB) ? HISO_SIZE_1GB : size; + grub_file_read(file, NULL, read); + } + + for (i = 0; start > 0 && i < chunklist->cur_chunk; i++) + { + chunklist->chunk[i].disk_start_sector += start; + chunklist->chunk[i].disk_end_sector += start; + } + + if (hiperiso_fs_udf == fs_type) + { + for (i = 0; i < chunklist->cur_chunk; i++) + { + count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2; + chunklist->chunk[i].img_start_sector = sector; + chunklist->chunk[i].img_end_sector = sector + count - 1; + sector += count; + } + } + } + + len = (int)grub_strlen(file->name); + if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) || + (len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) || + (len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) || + (len > 5 && grub_strncasecmp(file->name + len - 5, ".hiso", 5) == 0)) + { + for (i = 0; i < chunklist->cur_chunk; i++) + { + count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector; + if (count < 4) + { + count = 1; + } + else + { + count >>= 2; + } + + chunklist->chunk[i].img_start_sector = sector; + chunklist->chunk[i].img_end_sector = sector + count - 1; + sector += count; + } + } + + return 0; +} + +static grub_err_t hiperiso_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc; + int fs_type; + grub_file_t file; + grub_disk_addr_t start; + char errmsg[128]; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]); + } + + g_conf_replace_count = 0; + grub_memset(g_conf_replace_node, 0, sizeof(g_conf_replace_node )); + grub_memset(g_conf_replace_offset, 0, sizeof(g_conf_replace_offset )); + + if (g_img_chunk_list.chunk) + { + grub_free(g_img_chunk_list.chunk); + } + + fs_type = hiperiso_get_fs_type(file->fs->name); + if (fs_type >= hiperiso_fs_max) + { + grub_file_close(file); + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name); + } + + /* get image chunk data */ + grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list)); + g_img_chunk_list.chunk = grub_malloc(sizeof(hiperiso_img_chunk) * DEFAULT_CHUNK_NUM); + if (NULL == g_img_chunk_list.chunk) + { + return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n"); + } + + g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM; + g_img_chunk_list.cur_chunk = 0; + + start = file->device->disk->partition->start; + + hiperiso_get_block_list(file, &g_img_chunk_list, start); + + rc = hiperiso_check_block_list(file, &g_img_chunk_list, start, errmsg, sizeof(errmsg)); + grub_file_close(file); + + if (rc) + { + if (fs_type == hiperiso_fs_btrfs) + { + hiso_tip(10, "%s\n\nWill exit in 10 seconds...\n", errmsg); + grub_exit(); + } + return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "%s\n", errmsg); + } + + grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace)); + grub_memset(&g_grub_param->img_replace, 0, sizeof(g_grub_param->img_replace)); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int n; + grub_uint64_t offset = 0; + grub_uint32_t align = 0; + grub_file_t file = NULL; + conf_replace *node = NULL; + conf_replace *nodes[HISO_MAX_CONF_REPLACE] = { NULL }; + hiperiso_grub_param_file_replace *replace = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + debug("select conf replace argc:%d\n", argc); + + if (argc < 2) + { + return 0; + } + + n = hiperiso_plugin_find_conf_replace(args[1], nodes); + if (!n) + { + debug("Conf replace not found for %s\n", args[1]); + goto end; + } + + debug("Find %d conf replace for %s\n", n, args[1]); + + g_conf_replace_count = n; + for (i = 0; i < n; i++) + { + node = nodes[i]; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(loop)%s", node->orgconf); + if (file) + { + offset = grub_iso9660_get_last_file_dirent_pos(file); + grub_file_close(file); + } + else if (node->img > 0) + { + offset = 0; + } + else + { + debug("<(loop)%s> NOT exist\n", node->orgconf); + continue; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", args[0], node->newconf); + if (!file) + { + debug("New config file <%s%s> NOT exist\n", args[0], node->newconf); + continue; + } + + align = ((int)file->size + 2047) / 2048 * 2048; + + if (align > hiso_max_replace_file_size) + { + debug("New config file <%s%s> too big\n", args[0], node->newconf); + grub_file_close(file); + continue; + } + + grub_file_read(file, g_conf_replace_new_buf[i], file->size); + grub_file_close(file); + g_conf_replace_new_len[i] = (int)file->size; + g_conf_replace_new_len_align[i] = align; + + g_conf_replace_node[i] = node; + g_conf_replace_offset[i] = offset + 2; + + if (node->img > 0) + { + replace = &(g_grub_param->img_replace[i]); + replace->magic = GRUB_IMG_REPLACE_MAGIC; + grub_snprintf(replace->old_file_name[replace->old_name_cnt], 256, "%s", node->orgconf); + replace->old_name_cnt++; + } + + debug("conf_replace OK: newlen[%d]: %d img:%d\n", i, g_conf_replace_new_len[i], node->img); + } + +end: + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_var_expand(int *record, int *flag, const char *var, char *expand, int len) +{ + int i = 0; + int n = 0; + char c; + const char *ch = var; + + *record = 0; + expand[0] = 0; + + while (*ch) + { + if (*ch == '_' || (*ch >= '0' && *ch <= '9') || (*ch >= 'A' && *ch <= 'Z') || (*ch >= 'a' && *ch <= 'z')) + { + ch++; + n++; + } + else + { + debug("Invalid variable letter <%c>\n", *ch); + goto end; + } + } + + if (n > 32) + { + debug("Invalid variable length:%d <%s>\n", n, var); + goto end; + } + + if (grub_strncmp(var, "VT_", 3) == 0) /* built-in variables */ + { + + } + else + { + if (*flag == 0) + { + *flag = 1; + grub_printf("\n=================== Variables Expansion ===================\n\n"); + } + + grub_printf("<%s>: ", var); + grub_refresh(); + + while (i < (len - 1)) + { + c = grub_getkey(); + if ((c == '\n') || (c == '\r')) + { + if (i > 0) + { + grub_printf("\n"); + grub_refresh(); + *record = 1; + break; + } + } + else if (grub_isprint(c)) + { + if (i + 1 < (len - 1)) + { + grub_printf("%c", c); + grub_refresh(); + expand[i++] = c; + expand[i] = 0; + } + } + else if (c == '\b') + { + if (i > 0) + { + expand[i - 1] = ' '; + grub_printf("\r<%s>: %s", var, expand); + + expand[i - 1] = 0; + grub_printf("\r<%s>: %s", var, expand); + + grub_refresh(); + i--; + } + } + } + } + +end: + if (expand[0] == 0) + { + grub_snprintf(expand, len, "$$%s$$", var); + } + + return 0; +} + +static int hiperiso_auto_install_var_expand(install_template *node) +{ + int pos = 0; + int flag = 0; + int record = 0; + int newlen = 0; + char *start = NULL; + char *end = NULL; + char *newbuf = NULL; + char *curline = NULL; + char *nextline = NULL; + grub_uint8_t *code = NULL; + char value[512]; + var_node *CurNode = NULL; + var_node *pVarList = NULL; + + code = (grub_uint8_t *)node->filebuf; + + if (node->filelen >= HISO_SIZE_1MB) + { + debug("auto install script too long %d\n", node->filelen); + return 0; + } + + if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff)) + { + debug("UCS-2 encoding NOT supported\n"); + return 0; + } + + start = grub_strstr(node->filebuf, "$$"); + if (!start) + { + debug("no need to expand variable, no start.\n"); + return 0; + } + + end = grub_strstr(start + 2, "$$"); + if (!end) + { + debug("no need to expand variable, no end.\n"); + return 0; + } + + newlen = grub_max(node->filelen * 10, HISO_SIZE_128KB); + newbuf = grub_malloc(newlen); + if (!newbuf) + { + debug("Failed to alloc newbuf %d\n", newlen); + return 0; + } + + for (curline = node->filebuf; curline; curline = nextline) + { + nextline = hiperiso_get_line(curline); + + start = grub_strstr(curline, "$$"); + if (start) + { + end = grub_strstr(start + 2, "$$"); + } + + if (start && end) + { + *start = *end = 0; + HISO_APPEND_NEWBUF(curline); + + for (CurNode = pVarList; CurNode; CurNode = CurNode->next) + { + if (grub_strcmp(start + 2, CurNode->var) == 0) + { + grub_snprintf(value, sizeof(value) - 1, "%s", CurNode->val); + break; + } + } + + if (!CurNode) + { + value[sizeof(value) - 1] = 0; + hiperiso_var_expand(&record, &flag, start + 2, value, sizeof(value) - 1); + + if (record) + { + CurNode = grub_zalloc(sizeof(var_node)); + if (CurNode) + { + grub_snprintf(CurNode->var, sizeof(CurNode->var), "%s", start + 2); + grub_snprintf(CurNode->val, sizeof(CurNode->val), "%s", value); + CurNode->next = pVarList; + pVarList = CurNode; + } + } + } + + HISO_APPEND_NEWBUF(value); + + HISO_APPEND_NEWBUF(end + 2); + } + else + { + HISO_APPEND_NEWBUF(curline); + } + + if (pos > 0 && newbuf[pos - 1] == '\r') + { + newbuf[pos - 1] = '\n'; + } + else + { + newbuf[pos++] = '\n'; + } + } + + grub_free(node->filebuf); + node->filebuf = newbuf; + node->filelen = pos; + + while (pVarList) + { + CurNode = pVarList->next; + grub_free(pVarList); + pVarList = CurNode; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + int pos = 0; + int defidx = 1; + char *buf = NULL; + grub_file_t file = NULL; + char configfile[128]; + install_template *node = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + debug("select auto installation argc:%d\n", argc); + + if (argc < 1) + { + return 0; + } + + node = hiperiso_plugin_find_install_template(args[0]); + if (!node) + { + debug("Auto install template not found for %s\n", args[0]); + return 0; + } + + if (node->autosel >= 0 && node->autosel <= node->templatenum) + { + defidx = node->autosel; + if (node->timeout < 0) + { + node->cursel = node->autosel - 1; + debug("Auto install template auto select %d\n", node->autosel); + goto load; + } + } + + buf = (char *)grub_malloc(HISO_MAX_SCRIPT_BUF); + if (!buf) + { + return 0; + } + + if (node->timeout > 0) + { + hiso_ssprintf(buf, pos, "set timeout=%d\n", node->timeout); + } + + hiso_ssprintf(buf, pos, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n" + " echo %s\n}\n", ""); + + for (i = 0; i < node->templatenum; i++) + { + hiso_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n" + " echo \"\"\n}\n", + hiperiso_get_vmenu_title("VTLANG_AUTOINS_USE"), + node->templatepath[i].path); + } + + g_hiperiso_menu_esc = 1; + g_hiperiso_suppress_esc = 1; + g_hiperiso_suppress_esc_default = defidx; + g_hiperiso_secondary_menu_on = 1; + + grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos); + grub_script_execute_sourcecode(configfile); + + g_hiperiso_menu_esc = 0; + g_hiperiso_suppress_esc = 0; + g_hiperiso_suppress_esc_default = 1; + g_hiperiso_secondary_menu_on = 0; + + grub_free(buf); + + node->cursel = g_hiperiso_last_entry - 1; + +load: + grub_check_free(node->filebuf); + node->filelen = 0; + + if (node->cursel >= 0 && node->cursel < node->templatenum) + { + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", hiperiso_get_env("hiso_iso_part"), + node->templatepath[node->cursel].path); + if (file) + { + node->filebuf = grub_malloc(file->size + 8); + if (node->filebuf) + { + grub_file_read(file, node->filebuf, file->size); + grub_file_close(file); + + grub_memset(node->filebuf + file->size, 0, 8); + node->filelen = (int)file->size; + + hiperiso_auto_install_var_expand(node); + } + } + else + { + debug("Failed to open auto install script <%s%s>\n", + hiperiso_get_env("hiso_iso_part"), node->templatepath[node->cursel].path); + } + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + int pos = 0; + int defidx = 1; + char *buf = NULL; + char configfile[128]; + persistence_config *node; + + (void)ctxt; + (void)argc; + (void)args; + + debug("select persistence argc:%d\n", argc); + + if (argc < 1) + { + return 0; + } + + node = hiperiso_plugin_find_persistent(args[0]); + if (!node) + { + debug("Persistence image not found for %s\n", args[0]); + return 0; + } + + if (node->autosel >= 0 && node->autosel <= node->backendnum) + { + defidx = node->autosel; + if (node->timeout < 0) + { + node->cursel = node->autosel - 1; + debug("Persistence image auto select %d\n", node->autosel); + return 0; + } + } + + buf = (char *)grub_malloc(HISO_MAX_SCRIPT_BUF); + if (!buf) + { + return 0; + } + + if (node->timeout > 0) + { + hiso_ssprintf(buf, pos, "set timeout=%d\n", node->timeout); + } + + hiso_ssprintf(buf, pos, "menuentry \"$VTLANG_NO_PERSIST\" --class=\"sel_persistence\" {\n" + " echo %s\n}\n", ""); + + for (i = 0; i < node->backendnum; i++) + { + hiso_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n" + " echo \"\"\n}\n", + hiperiso_get_vmenu_title("VTLANG_PERSIST_USE"), + node->backendpath[i].path); + + } + + g_hiperiso_menu_esc = 1; + g_hiperiso_suppress_esc = 1; + g_hiperiso_suppress_esc_default = defidx; + g_hiperiso_secondary_menu_on = 1; + + grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos); + grub_script_execute_sourcecode(configfile); + + g_hiperiso_menu_esc = 0; + g_hiperiso_suppress_esc = 0; + g_hiperiso_suppress_esc_default = 1; + g_hiperiso_secondary_menu_on = 0; + + grub_free(buf); + + node->cursel = g_hiperiso_last_entry - 1; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t i; + hiperiso_img_chunk *cur; + + (void)ctxt; + (void)argc; + (void)args; + + for (i = 0; i < g_img_chunk_list.cur_chunk; i++) + { + cur = g_img_chunk_list.chunk + i; + grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n", + cur->img_start_sector, cur->img_end_sector, + (unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector + ); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t i; + grub_file_t file; + hiperiso_img_chunk_list chunklist; + char errmsg[128]; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]); + } + + /* get image chunk data */ + grub_memset(&chunklist, 0, sizeof(chunklist)); + chunklist.chunk = grub_malloc(sizeof(hiperiso_img_chunk) * DEFAULT_CHUNK_NUM); + if (NULL == chunklist.chunk) + { + return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n"); + } + + chunklist.max_chunk = DEFAULT_CHUNK_NUM; + chunklist.cur_chunk = 0; + + hiperiso_get_block_list(file, &chunklist, 0); + + if (0 != hiperiso_check_block_list(file, &chunklist, 0, errmsg, sizeof(errmsg))) + { + grub_printf("%s\n", errmsg); + grub_printf("########## UNSUPPORTED ###############\n"); + } + + grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk); + + for (i = 0; i < chunklist.cur_chunk; i++) + { + grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector, + (ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector)); + } + + grub_printf("\n==================================\n"); + + for (i = 0; i < chunklist.cur_chunk; i++) + { + grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i, + (ulonglong)chunklist.chunk[i].img_start_sector, + (ulonglong)chunklist.chunk[i].img_end_sector, + (ulonglong)chunklist.chunk[i].disk_start_sector, + (ulonglong)chunklist.chunk[i].disk_end_sector + ); + } + + grub_free(chunklist.chunk); + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + hiperiso_grub_param_file_replace *replace = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc >= 2) + { + replace = &(g_grub_param->file_replace); + replace->magic = GRUB_FILE_REPLACE_MAGIC; + + replace->old_name_cnt = 0; + for (i = 0; i < 4 && i + 1 < argc; i++) + { + replace->old_name_cnt++; + grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]); + } + + replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char buf[32]; + hiperiso_grub_param_file_replace *replace = &(g_grub_param->file_replace); + + (void)ctxt; + + if (argc >= 1) + { + grub_snprintf(buf, sizeof(buf), "%u", replace->old_name_cnt); + grub_env_set(args[0], buf); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (argc == 0) + { + grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, HISO_MAX_SCRIPT_BUF); + grub_printf("%s", g_list_script_buf); + } + else + { + grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, HISO_MAX_SCRIPT_BUF); + grub_printf("%s", g_tree_script_buf); + } + + return 0; +} + +static grub_err_t hiperiso_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args) +{ + img_info *cur = g_hiperiso_img_list; + + (void)ctxt; + (void)argc; + (void)args; + + while (cur) + { + grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index); + grub_printf("name:<%s>\n\n", cur->name); + cur = cur->next; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_plugin_dump_injection(); + + return 0; +} + +static grub_err_t hiperiso_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_plugin_dump_auto_install(); + + return 0; +} + +static grub_err_t hiperiso_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_plugin_dump_persistence(); + + return 0; +} + +static int hiperiso_check_mode_by_name(char *filename, const char *suffix) +{ + int i; + int len1; + int len2; + + len1 = (int)grub_strlen(filename); + len2 = (int)grub_strlen(suffix); + + if (len1 <= len2) + { + return 0; + } + + for (i = len1 - 1; i >= 0; i--) + { + if (filename[i] == '.') + { + break; + } + } + + if (i < len2 + 1) + { + return 0; + } + + if (filename[i - len2 - 1] != '_') + { + return 0; + } + + if (grub_strncasecmp(filename + (i - len2), suffix, len2) == 0) + { + return 1; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 1 && argc != 2) + { + return 1; + } + + if (args[0][0] == '0') + { + if (g_hiperiso_memdisk_mode) + { + return 0; + } + + if (argc == 2 && hiperiso_check_mode_by_name(args[1], "vtmemdisk")) + { + return 0; + } + + return 1; + } + else if (args[0][0] == '1') + { + return g_hiperiso_iso_raw ? 0 : 1; + } + else if (args[0][0] == '2') + { + return g_hiperiso_iso_uefi_drv ? 0 : 1; + } + else if (args[0][0] == '3') + { + if (g_hiperiso_grub2_mode) + { + return 0; + } + + if (argc == 2 && hiperiso_check_mode_by_name(args[1], "vtgrub2")) + { + return 0; + } + + return 1; + } + else if (args[0][0] == '4') + { + if (g_hiperiso_wimboot_mode) + { + return 0; + } + + if (argc == 2 && hiperiso_check_mode_by_name(args[1], "vtwimboot")) + { + return 0; + } + + return 1; + } + + return 1; +} + +static grub_err_t hiperiso_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + static int configfile_mode = 0; + char memfile[128] = {0}; + + (void)ctxt; + (void)argc; + (void)args; + + /* + * args[0]: 0:normal 1:configfile + * args[1]: 0:list_buf 1:tree_buf + */ + + if (argc != 2) + { + debug("Invalid argc %d\n", argc); + return 0; + } + + HISO_CMD_CHECK(1); + + if (args[0][0] == '0') + { + if (args[1][0] == '0') + { + grub_script_execute_sourcecode(g_list_script_buf); + } + else + { + grub_script_execute_sourcecode(g_tree_script_buf); + } + } + else + { + if (configfile_mode) + { + debug("Now already in F3 mode %d\n", configfile_mode); + return 0; + } + + if (args[1][0] == '0') + { + grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d", + (ulonglong)(ulong)g_list_script_buf, g_list_script_pos); + } + else + { + g_hiperiso_last_entry = -1; + grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d", + (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos); + } + + configfile_mode = 1; + grub_script_execute_sourcecode(memfile); + configfile_mode = 0; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file; + + (void)ctxt; + + if (argc != 1) + { + return 1; + } + + g_hiperiso_case_insensitive = 1; + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + g_hiperiso_case_insensitive = 0; + + grub_errno = 0; + + if (file) + { + grub_file_close(file); + return 0; + } + return 1; +} + +static grub_err_t hiperiso_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int id = 0; + int find = 0; + grub_disk_t disk; + const char *isopath = NULL; + char hdname[32]; + hiperiso_mbr_head mbr; + + (void)ctxt; + (void)argc; + + if (argc != 1) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name); + } + + isopath = grub_env_get("hiso_iso_part"); + if (!isopath) + { + debug("isopath is null %p\n", isopath); + return 0; + } + + debug("isopath is %s\n", isopath); + + for (id = 0; id < 30 && (find == 0); id++) + { + grub_snprintf(hdname, sizeof(hdname), "hd%d,", id); + if (grub_strstr(isopath, hdname)) + { + debug("skip %s ...\n", hdname); + continue; + } + + grub_snprintf(hdname, sizeof(hdname), "hd%d", id); + + disk = grub_disk_open(hdname); + if (!disk) + { + debug("%s not exist\n", hdname); + break; + } + + grub_memset(&mbr, 0, sizeof(mbr)); + if (0 == grub_disk_read(disk, 0, 0, 512, &mbr)) + { + if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA) + { + if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 || + mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80) + { + + grub_env_set(args[0], hdname); + find = 1; + } + } + debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable"); + } + else + { + debug("read %s failed\n", hdname); + } + + grub_disk_close(disk); + } + + return 0; +} + +static grub_err_t hiperiso_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 1024; + grub_file_t file; + char *buf = NULL; + + (void)ctxt; + (void)argc; + + if (argc != 2) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("failed to open file %s\n", args[0]); + return 0; + } + + buf = grub_malloc(len); + if (!buf) + { + goto end; + } + + buf[len - 1] = 0; + grub_file_read(file, buf, len - 1); + + hiperiso_get_line(buf); + hiperiso_set_env(args[1], buf); + +end: + + grub_check_free(buf); + grub_file_close(file); + + return 0; +} + +static int hiperiso_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data) +{ + grub_uint64_t end_max = 0; + int *pCnt = (int *)data; + + (void)disk; + + (*pCnt)++; + g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, HISO_MAX_SCRIPT_BUF - g_part_list_pos, + "0 %llu linear /dev/hiperiso %llu\n", + (ulonglong)partition->len, (ulonglong)partition->start); + + end_max = (partition->len + partition->start) * 512; + if (end_max > g_part_end_max) + { + g_part_end_max = end_max; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int cnt = 0; + char *device_name = NULL; + grub_device_t dev = NULL; + char buf[64]; + + (void)ctxt; + + g_part_list_pos = 0; + g_part_end_max = 0; + grub_env_unset("hiso_img_part_file"); + + if (argc != 1) + { + return 1; + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + debug("hiperiso_cmd_img_part_info failed, %s\n", args[0]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("grub_device_open failed, %s\n", device_name); + goto end; + } + + grub_partition_iterate(dev->disk, hiperiso_img_partition_callback, &cnt); + + grub_snprintf(buf, sizeof(buf), "newc:hiso_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos); + grub_env_set("hiso_img_part_file", buf); + + grub_snprintf(buf, sizeof(buf), "%d", cnt); + grub_env_set("hiso_img_part_cnt", buf); + + grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)g_part_end_max); + grub_env_set("hiso_img_max_part_end", buf); + +end: + + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + return 0; +} + + +static grub_err_t hiperiso_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + grub_file_t file; + char *buf = NULL; + + (void)ctxt; + (void)argc; + + if (argc != 2) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("failed to open file %s\n", args[0]); + return 1; + } + + buf = grub_malloc(file->size + 1); + if (!buf) + { + goto end; + } + + buf[file->size] = 0; + grub_file_read(file, buf, file->size); + + if (grub_strstr(buf, args[1])) + { + rc = 0; + } + +end: + + grub_check_free(buf); + grub_file_close(file); + + return rc; +} + +static grub_err_t hiperiso_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len; + grub_file_t file; + char buf[64]; + grub_uint64_t size; + hiperiso_iso9660_vd pvd; + + (void)ctxt; + (void)argc; + + if (argc != 4) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("failed to open file %s\n", args[0]); + return 0; + } + + grub_file_seek(file, 16 * 2048); + len = (int)grub_file_read(file, &pvd, sizeof(pvd)); + if (len != sizeof(pvd)) + { + debug("failed to read pvd %d\n", len); + goto end; + } + + grub_memset(buf, 0, sizeof(buf)); + grub_memcpy(buf, pvd.sys, sizeof(pvd.sys)); + hiperiso_set_env(args[1], buf); + + grub_memset(buf, 0, sizeof(buf)); + grub_memcpy(buf, pvd.vol, sizeof(pvd.vol)); + hiperiso_set_env(args[2], buf); + + size = pvd.space; + size *= 2048; + grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size); + hiperiso_set_env(args[3], buf); + +end: + grub_file_close(file); + + return 0; +} + +static grub_err_t hiperiso_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len; + grub_file_t file; + char buf[64]; + + (void)ctxt; + (void)argc; + + if (argc != 2) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("failed to open file %s\n", args[0]); + return 0; + } + + grub_memset(buf, 0, sizeof(buf)); + grub_file_seek(file, 16 * 2048 + 813); + len = (int)grub_file_read(file, buf, 17); + if (len != 17) + { + debug("failed to read create date %d\n", len); + goto end; + } + + hiperiso_set_env(args[1], buf); + +end: + grub_file_close(file); + + return 0; +} + +static grub_err_t hiperiso_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_env_hook_root(1); + + return 0; +} + +static grub_err_t hiperiso_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_env_hook_root(0); + + return 0; +} + +#ifdef GRUB_MACHINE_EFI +static grub_err_t hiperiso_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + return g_sys_sb ? 0 : 1; +} +#else +static grub_err_t hiperiso_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + return 1; +} +#endif + +static grub_err_t hiperiso_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int ret = 1; + grub_file_t file; + grub_uint64_t FileSectors = 0; + hiperiso_gpt_info *gpt = NULL; + hiperiso_part_table *pt = NULL; + grub_uint8_t zeroguid[16] = {0}; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("failed to open file %s\n", args[0]); + return 1; + } + + if (file->size % 512) + { + debug("unaligned file size: %llu\n", (ulonglong)file->size); + goto out; + } + + gpt = grub_zalloc(sizeof(hiperiso_gpt_info)); + if (!gpt) + { + goto out; + } + + FileSectors = file->size / 512; + + grub_file_read(file, gpt, sizeof(hiperiso_gpt_info)); + if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0) + { + debug("This is EFI partition table\n"); + + for (i = 0; i < 128; i++) + { + if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16)) + { + if (FileSectors < gpt->PartTbl[i].LastLBA) + { + debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i, + (ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors); + goto out; + } + } + } + } + else + { + debug("This is MBR partition table\n"); + + for (i = 0; i < 4; i++) + { + pt = gpt->MBR.PartTbl + i; + if (FileSectors < pt->StartSectorId + pt->SectorCount) + { + debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i, + (ulonglong)(pt->StartSectorId + pt->SectorCount), + (ulonglong)FileSectors); + goto out; + } + } + } + + ret = 0; + +out: + grub_file_close(file); + grub_check_free(gpt); + grub_errno = GRUB_ERR_NONE; + return ret; +} + +static grub_err_t hiperiso_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int ret; + + (void)ctxt; + (void)argc; + (void)args; + + for (i = 0; i < 500; i++) + { + ret = grub_getkey_noblock(); + if (ret == GRUB_TERM_NO_KEY) + { + break; + } + } + + if (i >= 500) + { + grub_cls(); + grub_printf("\n\n Still have key input after clear.\n"); + grub_refresh(); + grub_sleep(5); + } + + return 0; +} + +static grub_err_t hiperiso_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int buflen; + int datalen; + int loclen; + int img_chunk_num; + int image_sector_size; + char cmd[64]; + hiperiso_chain_head *chain; + hiperiso_img_chunk *chunk; + hiperiso_os_param *osparam; + hiperiso_image_location *location; + hiperiso_image_disk_region *region; + struct grub_acpi_table_header *acpi; + + (void)ctxt; + + if (argc != 2) + { + return 1; + } + + debug("hiperiso_cmd_acpi_param %s %s\n", args[0], args[1]); + + chain = (hiperiso_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16); + if (!chain) + { + return 1; + } + + image_sector_size = (int)grub_strtol(args[1], NULL, 10); + + if (grub_memcmp(&g_hiperiso_guid, &(chain->os_param.guid), 16)) + { + debug("Invalid hiperiso guid 0x%x\n", chain->os_param.guid.data1); + return 1; + } + + img_chunk_num = chain->img_chunk_num; + + loclen = sizeof(hiperiso_image_location) + (img_chunk_num - 1) * sizeof(hiperiso_image_disk_region); + datalen = sizeof(hiperiso_os_param) + loclen; + + buflen = sizeof(struct grub_acpi_table_header) + datalen; + acpi = grub_zalloc(buflen); + if (!acpi) + { + return 1; + } + + /* Step1: Fill acpi table header */ + grub_memcpy(acpi->signature, "HISO", 4); + acpi->length = buflen; + acpi->revision = 1; + grub_memcpy(acpi->oemid, "HIPERISO", 6); + grub_memcpy(acpi->oemtable, "OSPARAMS", 8); + acpi->oemrev = 1; + acpi->creator_id[0] = 1; + acpi->creator_rev = 1; + + /* Step2: Fill data */ + osparam = (hiperiso_os_param *)(acpi + 1); + grub_memcpy(osparam, &chain->os_param, sizeof(hiperiso_os_param)); + osparam->hiso_img_location_addr = 0; + osparam->hiso_img_location_len = loclen; + osparam->chksum = 0; + osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(hiperiso_os_param)); + + location = (hiperiso_image_location *)(osparam + 1); + grub_memcpy(&location->guid, &osparam->guid, sizeof(hiperiso_guid)); + location->image_sector_size = image_sector_size; + location->disk_sector_size = chain->disk_sector_size; + location->region_count = img_chunk_num; + + region = location->regions; + chunk = (hiperiso_img_chunk *)((char *)chain + chain->img_chunk_offset); + if (512 == image_sector_size) + { + for (i = 0; i < img_chunk_num; i++) + { + region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1; + region->image_start_sector = chunk->img_start_sector * 4; + region->disk_start_sector = chunk->disk_start_sector; + region++; + chunk++; + } + } + else + { + for (i = 0; i < img_chunk_num; i++) + { + region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1; + region->image_start_sector = chunk->img_start_sector; + region->disk_start_sector = chunk->disk_start_sector; + region++; + chunk++; + } + } + + /* Step3: Fill acpi checksum */ + acpi->checksum = 0; + acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length); + + /* load acpi table */ + grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length); + grub_script_execute_sourcecode(cmd); + + grub_free(acpi); + + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_hiperiso_last_entry_back = g_hiperiso_last_entry; + g_hiperiso_last_entry = -1; + + return 0; +} + +static grub_err_t hiperiso_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_hiperiso_last_entry = g_hiperiso_last_entry_back; + + return 0; +} + +static int hiperiso_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + const char *pos = filename + 1; + + if (info->dir) + { + while (*pos) + { + if (*pos == '.') + { + if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9')) + { + grub_strncpy((char *)data, filename, 128); + return 1; + } + } + pos++; + } + } + + return 0; +} + +static grub_err_t hiperiso_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + char *device_name = NULL; + grub_device_t dev = NULL; + grub_fs_t fs = NULL; + char buf[128] = {0}; + + (void)ctxt; + + if (argc != 3) + { + debug("hiperiso_cmd_lib_module_ver, invalid param num %d\n", argc); + return 1; + } + + debug("hiperiso_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]); + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + debug("grub_file_get_device_name failed, %s\n", args[0]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("grub_device_open failed, %s\n", device_name); + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + debug("grub_fs_probe failed, %s\n", device_name); + goto end; + } + + fs->fs_dir(dev, args[1], hiperiso_lib_module_callback, buf); + + if (buf[0]) + { + hiperiso_set_env(args[2], buf); + } + + rc = 0; + +end: + + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + return rc; +} + +int hiperiso_load_part_table(const char *diskname) +{ + char name[64]; + int ret; + grub_disk_t disk; + grub_device_t dev; + + g_hiperiso_part_info = grub_zalloc(sizeof(hiperiso_gpt_info)); + if (!g_hiperiso_part_info) + { + return 1; + } + + disk = grub_disk_open(diskname); + if (!disk) + { + debug("Failed to open disk %s\n", diskname); + return 1; + } + + g_hiperiso_disk_size = disk->total_sectors * (1U << disk->log_sector_size); + + g_hiperiso_disk_bios_id = disk->id; + + grub_disk_read(disk, 0, 0, sizeof(hiperiso_gpt_info), g_hiperiso_part_info); + grub_disk_close(disk); + + grub_snprintf(name, sizeof(name), "%s,1", diskname); + dev = grub_device_open(name); + if (dev) + { + /* Check for official Hiperiso device */ + ret = hiperiso_check_official_device(dev); + grub_device_close(dev); + + if (ret) + { + return 1; + } + } + + g_hiperiso_disk_part_size[0] = hiperiso_get_hiso_partsize(0); + g_hiperiso_disk_part_size[1] = hiperiso_get_hiso_partsize(1); + + return 0; +} + +void hiperiso_prompt_end(void) +{ + int op = 0; + char c; + + grub_printf("\n\n\n"); + grub_printf(" 1 --- Exit grub\n"); + grub_printf(" 2 --- Reboot\n"); + grub_printf(" 3 --- Shut down\n"); + grub_printf("Please enter your choice: "); + grub_refresh(); + + while (1) + { + c = grub_getkey(); + if (c >= '1' && c <= '3') + { + if (op == 0) + { + op = c - '0'; + grub_printf("%c", c); + grub_refresh(); + } + } + else if (c == '\r' || c == '\n') + { + if (op) + { + if (op == 1) + { + grub_exit(); + } + else if (op == 2) + { + grub_reboot(); + } + else if (op == 3) + { + grub_script_execute_sourcecode("halt"); + } + } + } + else if (c == '\b') + { + if (op) + { + op = 0; + grub_printf("\rPlease enter your choice: "); + grub_printf("\rPlease enter your choice: "); + grub_refresh(); + } + } + } +} + +static grub_err_t hiperiso_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret; + + (void)argc; + (void)ctxt; + + ret = hiperiso_load_part_table(args[0]); + if (ret) + { + hiperiso_prompt_end(); + } + + g_hiperiso_disk_part_size[0] = hiperiso_get_hiso_partsize(0); + g_hiperiso_disk_part_size[1] = hiperiso_get_hiso_partsize(1); + + return 0; +} + +static grub_err_t hiperiso_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + const char *vcfg = NULL; + + (void)argc; + (void)ctxt; + + vcfg = hiperiso_plugin_get_custom_boot(args[0]); + if (vcfg) + { + debug("custom boot <%s>:<%s>\n", args[0], vcfg); + grub_env_set(args[1], vcfg); + ret = 0; + } + else + { + debug("custom boot <%s>:\n", args[0]); + } + + grub_errno = 0; + return ret; +} + + +static grub_err_t hiperiso_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int id; + grub_uint8_t zeroguid[16] = {0}; + + (void)argc; + (void)ctxt; + + id = (int)grub_strtoul(args[0], NULL, 10); + grub_errno = 0; + + if (grub_memcmp(g_hiperiso_part_info->Head.Signature, "EFI PART", 8) == 0) + { + if (id >= 1 && id <= 128) + { + if (grub_memcmp(g_hiperiso_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16)) + { + return 0; + } + } + } + else + { + if (id >= 1 && id <= 4) + { + if (g_hiperiso_part_info->MBR.PartTbl[id - 1].FsFlag) + { + return 0; + } + } + } + + return 1; +} + +static grub_err_t hiperiso_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 1; + char *device_name = NULL; + grub_device_t dev = NULL; + grub_fs_t fs = NULL; + char *label = NULL; + + (void)ctxt; + + debug("get fs label for %s\n", args[0]); + + if (argc != 2) + { + debug("hiperiso_cmd_get_fs_label, invalid param num %d\n", argc); + return 1; + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + debug("grub_file_get_device_name failed, %s\n", args[0]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("grub_device_open failed, %s\n", device_name); + goto end; + } + + fs = grub_fs_probe(dev); + if (NULL == fs || NULL == fs->fs_label) + { + debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label); + goto end; + } + + fs->fs_label(dev, &label); + if (label) + { + debug("label=<%s>\n", label); + hiperiso_set_env(args[1], label); + grub_free(label); + } + + rc = 0; + +end: + + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + return rc; +} + +static int hiperiso_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + if (!info->dir) + { + grub_snprintf((char *)data, 256, "%s", filename); + return 1; + } + + return 0; +} + +static int hiperiso_fs_enum_1st_dir(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + if (info->dir && filename && filename[0] != '.') + { + grub_snprintf((char *)data, 256, "%s", filename); + return 1; + } + + return 0; +} + +static grub_err_t hiperiso_fs_enum_1st_child(int argc, char **args, grub_fs_dir_hook_t hook) +{ + int rc = 1; + char *device_name = NULL; + grub_device_t dev = NULL; + grub_fs_t fs = NULL; + char name[256] ={0}; + + if (argc != 3) + { + debug("hiperiso_fs_enum_1st_child, invalid param num %d\n", argc); + return 1; + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + debug("grub_file_get_device_name failed, %s\n", args[0]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("grub_device_open failed, %s\n", device_name); + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + debug("grub_fs_probe failed, %s\n", device_name); + goto end; + } + + fs->fs_dir(dev, args[1], hook, name); + if (name[0]) + { + hiperiso_set_env(args[2], name); + } + + rc = 0; + +end: + + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + return rc; +} + +static grub_err_t hiperiso_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + return hiperiso_fs_enum_1st_child(argc, args, hiperiso_fs_enum_1st_file); +} + +static grub_err_t hiperiso_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + return hiperiso_fs_enum_1st_child(argc, args, hiperiso_fs_enum_1st_dir); +} + +static grub_err_t hiperiso_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char c; + char *pos = NULL; + char *end = NULL; + + (void)ctxt; + + if (argc != 2) + { + debug("hiperiso_cmd_basename, invalid param num %d\n", argc); + return 1; + } + + for (pos = args[0]; *pos; pos++) + { + if (*pos == '.') + { + end = pos; + } + } + + if (end) + { + c = *end; + *end = 0; + } + + grub_env_set(args[1], args[0]); + + if (end) + { + *end = c; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int len; + const char *buf; + + (void)ctxt; + + if (argc != 2) + { + debug("hiperiso_cmd_basefile, invalid param num %d\n", argc); + return 1; + } + + buf = args[0]; + len = (int)grub_strlen(buf); + for (i = len; i > 0; i--) + { + if (buf[i - 1] == '/') + { + grub_env_set(args[1], buf + i); + return 0; + } + } + + grub_env_set(args[1], buf); + + return 0; +} + +static grub_err_t hiperiso_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_video_mode_info info; + char buf[32]; + + (void)ctxt; + (void)argc; + (void)args; + + if (!g_video_mode_list) + { + hiperiso_enum_video_mode(); + } + + if (grub_video_get_info(&info) == GRUB_ERR_NONE) + { + grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height); + } + else + { + grub_snprintf(buf, sizeof(buf), "Resolution (0x0)"); + } + + grub_env_set("HISO_CUR_VIDEO_MODE", buf); + + grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num); + grub_env_set("HISO_VIDEO_MODE_NUM", buf); + + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_video_mode_info info; + char buf[32]; + + (void)ctxt; + (void)argc; + (void)args; + + if (grub_video_get_info(&info) == GRUB_ERR_NONE) + { + grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp); + } + else + { + grub_snprintf(buf, sizeof(buf), "0x0x0"); + } + + grub_env_set(args[0], buf); + + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int id; + char buf[32]; + + (void)ctxt; + (void)argc; + + if (!g_video_mode_list) + { + return 0; + } + + id = (int)grub_strtoul(args[0], NULL, 10); + if (id < g_video_mode_num) + { + grub_snprintf(buf, sizeof(buf), "%ux%ux%u", + g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp); + } + + grub_env_set(args[1], buf); + + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t i; + grub_uint32_t loadsector = 0; + grub_file_t file; + char value[32]; + grub_uint32_t boot_catlog = 0; + grub_uint8_t buf[512]; + + (void)ctxt; + + if (argc != 2) + { + debug("hiperiso_cmd_get_efivdisk_offset, invalid param num %d\n", argc); + return 1; + } + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + debug("failed to open %s\n", args[0]); + return 1; + } + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + if (boot_catlog == 0) + { + debug("No bootcatlog found\n"); + grub_file_close(file); + return 1; + } + + grub_memset(buf, 0, sizeof(buf)); + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, buf, sizeof(buf)); + grub_file_close(file); + + for (i = 0; i < sizeof(buf); i += 32) + { + if ((buf[i] == 0 || buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF) + { + if (buf[i + 32] == 0x88) + { + loadsector = *(grub_uint32_t *)(buf + i + 32 + 8); + grub_snprintf(value, sizeof(value), "%u", loadsector * 4); //change to sector size 512 + break; + } + } + } + + if (loadsector == 0) + { + debug("No EFI eltorito info found\n"); + return 1; + } + + debug("hiperiso_cmd_get_efivdisk_offset <%s>\n", value); + grub_env_set(args[1], value); + HIPERISO_CMD_RETURN(0); +} + +static int hiperiso_collect_replace_initrd(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + int curpos; + int printlen; + grub_size_t len; + replace_fs_dir *pfsdir = (replace_fs_dir *)data; + + if (pfsdir->initrd[0]) + { + return 1; + } + + curpos = pfsdir->curpos; + len = grub_strlen(filename); + + if (info->dir) + { + if ((len == 1 && filename[0] == '.') || + (len == 2 && filename[0] == '.' && filename[1] == '.')) + { + return 0; + } + + //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename); + pfsdir->dircnt++; + + printlen = grub_snprintf(pfsdir->fullpath + curpos, 512 - curpos, "%s/", filename); + pfsdir->curpos = curpos + printlen; + pfsdir->fs->fs_dir(pfsdir->dev, pfsdir->fullpath, hiperiso_collect_replace_initrd, pfsdir); + pfsdir->curpos = curpos; + pfsdir->fullpath[curpos] = 0; + } + else + { + //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename); + pfsdir->filecnt++; + + /* We consider the xxx.img file bigger than 32MB is the initramfs file */ + if (len > 4 && grub_strncmp(filename + len - 4, ".img", 4) == 0) + { + if (info->size > 32 * HISO_SIZE_1MB) + { + grub_snprintf(pfsdir->initrd, sizeof(pfsdir->initrd), "%s%s", pfsdir->fullpath, filename); + return 1; + } + } + } + + return 0; +} + +static grub_err_t hiperiso_cmd_search_replace_initrd(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + char *pos = NULL; + char *device_name = NULL; + grub_device_t dev = NULL; + grub_fs_t fs = NULL; + replace_fs_dir *pfsdir = NULL; + + (void)ctxt; + + if (argc != 2) + { + debug("hiperiso_cmd_search_replace_initrd, invalid param num %d\n", argc); + return 1; + } + + pfsdir = grub_zalloc(sizeof(replace_fs_dir)); + if (!pfsdir) + { + return 1; + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + goto fail; + } + + dev = grub_device_open(device_name); + if (!dev) + { + goto fail; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + goto fail; + } + + pfsdir->dev = dev; + pfsdir->fs = fs; + pfsdir->curpos = 1; + pfsdir->fullpath[0] = '/'; + fs->fs_dir(dev, "/", hiperiso_collect_replace_initrd, pfsdir); + + if (pfsdir->initrd[0]) + { + debug("Replace initrd <%s> <%d %d>\n", pfsdir->initrd, pfsdir->dircnt, pfsdir->filecnt); + + for (i = 0; i < (int)sizeof(pfsdir->initrd) && pfsdir->initrd[i]; i++) + { + if (pfsdir->initrd[i] == '/') + { + pfsdir->initrd[i] = '\\'; + } + } + + pos = (pfsdir->initrd[0] == '\\') ? pfsdir->initrd + 1 : pfsdir->initrd; + grub_env_set(args[1], pos); + } + else + { + debug("Replace initrd NOT found <%s> <%d %d>\n", args[0], pfsdir->dircnt, pfsdir->filecnt); + } + +fail: + + grub_check_free(pfsdir); + grub_check_free(device_name); + check_free(dev, grub_device_close); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_push_pager(grub_extcmd_context_t ctxt, int argc, char **args) +{ + const char *pager = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + pager = grub_env_get("pager"); + if (NULL == pager) + { + g_pager_flag = 1; + grub_env_set("pager", "1"); + } + else if (pager[0] == '1') + { + g_pager_flag = 0; + } + else + { + grub_snprintf(g_old_pager, sizeof(g_old_pager), "%s", pager); + g_pager_flag = 2; + grub_env_set("pager", "1"); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_pop_pager(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (g_pager_flag == 1) + { + grub_env_unset("pager"); + } + else if (g_pager_flag == 2) + { + grub_env_set("pager", g_old_pager); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_chk_case_file(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + if (g_json_case_mis_path[0]) + { + return 1; + } + + if (0 == info->dir && grub_strcasecmp(filename, "hiperiso.json") == 0) + { + grub_snprintf(g_json_case_mis_path, 32, "%s/%s", (char *)data, filename); + return 1; + } + return 0; +} + +static int hiperiso_chk_case_dir(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + char path[16]; + chk_case_fs_dir *fs_dir = (chk_case_fs_dir *)data; + + if (g_json_case_mis_path[0]) + { + return 1; + } + + if (info->dir && (filename[0] == 'v' || filename[0] == 'V')) + { + if (grub_strcasecmp(filename, "hiperiso") == 0) + { + grub_snprintf(path, sizeof(path), "/%s", filename); + fs_dir->fs->fs_dir(fs_dir->dev, path, hiperiso_chk_case_file, path); + if (g_json_case_mis_path[0]) + { + return 1; + } + } + } + + return 0; +} + +static grub_err_t hiperiso_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int fstype = 0; + char *device_name = NULL; + grub_device_t dev = NULL; + grub_fs_t fs = NULL; + chk_case_fs_dir fs_dir; + + (void)ctxt; + (void)argc; + (void)args; + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + goto out; + } + + dev = grub_device_open(device_name); + if (!dev) + { + goto out; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + goto out; + } + + fstype = hiperiso_get_fs_type(fs->name); + if (fstype == hiperiso_fs_fat || fstype == hiperiso_fs_exfat || fstype >= hiperiso_fs_max) + { + goto out; + } + + g_json_case_mis_path[0] = 0; + fs_dir.dev = dev; + fs_dir.fs = fs; + fs->fs_dir(dev, "/", hiperiso_chk_case_dir, &fs_dir); + + if (g_json_case_mis_path[0]) + { + grub_env_set("HISO_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path); + } + +out: + + grub_check_free(device_name); + check_free(dev, grub_device_close); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t grub_cmd_gptpriority(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_disk_t disk; + grub_partition_t part; + char priority_str[3]; /* Maximum value 15 */ + + (void)ctxt; + + if (argc < 2 || argc > 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "gptpriority DISKNAME PARTITIONNUM [VARNAME]"); + + /* Open the disk if it exists */ + disk = grub_disk_open (args[0]); + if (!disk) + { + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Not a disk"); + } + + part = grub_partition_probe (disk, args[1]); + if (!part) + { + grub_disk_close (disk); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "No such partition"); + } + + if (grub_strcmp (part->partmap->name, "gpt")) + { + grub_disk_close (disk); + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "Not a GPT partition"); + } + + grub_snprintf (priority_str, sizeof(priority_str), "%u", + (grub_uint32_t)((part->gpt_attrib >> 48) & 0xfULL)); + + if (argc == 3) + { + grub_env_set (args[2], priority_str); + grub_env_export (args[2]); + } + else + { + grub_printf ("Priority is %s\n", priority_str); + } + + grub_disk_close (disk); + return GRUB_ERR_NONE; +} + + +static grub_err_t grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + int joliet = 0; + grub_file_t file = NULL; + grub_uint32_t loadrba = 0; + grub_uint32_t boot_catlog = 0; + grub_uint8_t sector[512]; + boot_info_table *info = NULL; + + (void)ctxt; + (void)argc; + + /* This also trigger a iso9660 fs parse */ + if (hiperiso_check_file_exist("(loop)/isolinux/isolinux.cfg")) + { + return 0; + } + + joliet = grub_iso9660_is_joliet(); + if (joliet == 0) + { + return 1; + } + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + debug("failed to open %s\n", args[0]); + return 1; + } + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + if (boot_catlog == 0) + { + debug("no bootcatlog found %u\n", boot_catlog); + goto out; + } + + loadrba = hiperiso_get_bios_eltorito_rba(file, boot_catlog); + if (loadrba == 0) + { + debug("no bios eltorito rba found %u\n", loadrba); + goto out; + } + + grub_file_seek(file, loadrba * 2048); + grub_file_read(file, sector, 512); + + info = (boot_info_table *)sector; + if (info->bi_data0 == 0x7c6ceafa && + info->bi_data1 == 0x90900000 && + info->bi_PrimaryVolumeDescriptor == 16 && + info->bi_BootFileLocation == loadrba) + { + debug("bootloader is syslinux, %u.\n", loadrba); + ret = 0; + } + +out: + + grub_file_close(file); + grub_errno = GRUB_ERR_NONE; + return ret; +} + +static grub_err_t grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int n = 0; + hiperiso_vlnk_part *node; + + (void)ctxt; + (void)argc; + (void)args; + + for (node = g_vlnk_part_list; node; node = node->next) + { + grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n", + ++n, node->device, node->disksig, + (ulonglong)node->partoffset, (node->fs ? node->fs->name : "N/A")); + } + + return 0; +} + +static grub_err_t grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 0; + + (void)ctxt; + + if (argc == 1) + { + len = (int)grub_strlen(args[0]); + if (grub_file_is_vlnk_suffix(args[0], len)) + { + return 0; + } + } + + return 1; +} + +static grub_err_t grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int vlnk = 0; + const char *name = NULL; + + (void)ctxt; + + if (argc == 2) + { + grub_env_unset(args[1]); + name = grub_file_get_vlnk(args[0], &vlnk); + if (vlnk) + { + debug("VLNK SRC: <%s>\n", args[0]); + debug("VLNK DST: <%s>\n", name); + grub_env_set(args[1], name); + return 0; + } + } + + return 1; +} + +static grub_err_t grub_cmd_check_vlnk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + int len = 0; + grub_file_t file = NULL; + hiperiso_vlnk vlnk; + char dst[512]; + + (void)ctxt; + + if (argc != 1) + { + goto out; + } + + len = (int)grub_strlen(args[0]); + if (!grub_file_is_vlnk_suffix(args[0], len)) + { + grub_printf("Invalid vlnk suffix\n"); + goto out; + } + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE | GRUB_FILE_TYPE_NO_VLNK); + if (!file) + { + grub_printf("Failed to open %s\n", args[0]); + goto out; + } + + if (file->size != 32768) + { + grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong)file->size); + goto out; + } + + grub_memset(&vlnk, 0, sizeof(vlnk)); + grub_file_read(file, &vlnk, sizeof(vlnk)); + + ret = hiperiso_check_vlnk_data(&vlnk, 1, dst, sizeof(dst)); + +out: + + grub_refresh(); + check_free(file, grub_file_close); + grub_errno = GRUB_ERR_NONE; + return ret; +} + +static grub_err_t hiperiso_iso_vd_id_clear(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_iso_vd_id_publisher[0] = 0; + g_iso_vd_id_prepare[0] = 0; + g_iso_vd_id_application[0] = 0; + + return 0; +} + +static grub_err_t hiperiso_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + int offset = 318; + grub_file_t file = NULL; + + (void)ctxt; + (void)argc; + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + grub_printf("Failed to open %s\n", args[0]); + goto out; + } + + grub_file_seek(file, 16 * 2048 + offset); + grub_file_read(file, g_iso_vd_id_publisher, 128); + + offset += 128; + grub_file_seek(file, 16 * 2048 + offset); + grub_file_read(file, g_iso_vd_id_prepare, 128); + + offset += 128; + grub_file_seek(file, 16 * 2048 + offset); + grub_file_read(file, g_iso_vd_id_application, 128); + +out: + + check_free(file, grub_file_close); + grub_errno = GRUB_ERR_NONE; + return ret; +} + +static grub_err_t hiperiso_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + char *id = g_iso_vd_id_publisher; + + (void)ctxt; + (void)argc; + + if (args[0][0] == '1') + { + id = g_iso_vd_id_prepare; + } + else if (args[0][0] == '2') + { + id = g_iso_vd_id_application; + } + + if (args[1][0] == '0' && grub_strncasecmp(id, args[2], grub_strlen(args[2])) == 0) + { + ret = 0; + } + + if (args[1][0] == '1' && grub_strncmp(id, args[2], grub_strlen(args[2])) == 0) + { + ret = 0; + } + + grub_errno = GRUB_ERR_NONE; + return ret; +} + +static grub_err_t hiperiso_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + g_hiperiso_fn_mutex = 0; + if (argc == 1 && args[0][0] == '1' && args[0][1] == 0) + { + g_hiperiso_fn_mutex = 1; + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_dump_rsv_page(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint64_t total; + grub_uint64_t org_required; + grub_uint64_t new_required; + + (void)ctxt; + (void)argc; + (void)args; + +#ifdef GRUB_MACHINE_EFI + grub_efi_get_reserved_page_num(&total, &org_required, &new_required); + grub_printf("Total pages: %llu\n", (unsigned long long)total); + grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required); + grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required); +#else + (void)total; + (void)org_required; + (void)new_required; + grub_printf("Non EFI mode!\n"); +#endif + + grub_refresh(); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_need_secondary_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + const char *env = NULL; + + (void)ctxt; + (void)argc; + + if (g_hiperiso_memdisk_mode || g_hiperiso_grub2_mode || g_hiperiso_wimboot_mode || g_hiperiso_iso_raw) + { + return 1; + } + + if (hiperiso_check_mode_by_name(args[0], "vtgrub2") || + hiperiso_check_mode_by_name(args[0], "vtwimboot") || + hiperiso_check_mode_by_name(args[0], "vtmemdisk") || + hiperiso_check_mode_by_name(args[0], "vtnormal") + ) + { + return 1; + } + + env = grub_env_get("HISO_SECONDARY_BOOT_MENU"); + if (env && env[0] == '0' && env[1] == 0) + { + return 1; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_show_secondary_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int n = 0; + int pos = 0; + int len = 0; + int select = 0; + int timeout = 0; + char *cmd = NULL; + const char *env = NULL; + ulonglong fsize = 0; + char cfgfile[128]; + int seldata[16] = {0}; + + (void)ctxt; + (void)argc; + + len = 8 * HISO_SIZE_1KB; + cmd = (char *)grub_malloc(len); + if (!cmd) + { + return 1; + } + + g_hiso_secondary_need_recover = 0; + grub_env_unset("HISO_SECOND_EXIT"); + grub_env_unset("HISO_CHKSUM_FILE_PATH"); + + env = grub_env_get("HISO_SECONDARY_TIMEOUT"); + if (env) + { + timeout = (int)grub_strtol(env, NULL, 10); + } + + if (timeout > 0) + { + hiso_len_ssprintf(cmd, pos, len, "set timeout=%d\n", timeout); + } + + fsize = grub_strtoull(args[2], NULL, 10); + + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_NORMAL_MODE", "second_normal"); seldata[n++] = 1; + + if (grub_strcmp(args[1], "Unix") != 0) + { + if (grub_strcmp(args[1], "Windows") == 0) + { + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata[n++] = 2; + } + else + { + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata[n++] = 3; + } + + if (fsize <= HISO_SIZE_1GB) + { + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata[n++] = 4; + } + } + + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata[n++] = 5; + hiso_dummy_menuentry(cmd, pos, len, "$VTLANG_RETURN_PRV_NOESC", "second_return"); seldata[n++] = 6; + + do { + grub_errno = GRUB_ERR_NONE; + g_hiperiso_menu_esc = 1; + g_hiperiso_suppress_esc = 1; + g_hiperiso_suppress_esc_default = 0; + g_hiperiso_secondary_menu_on = 1; + grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)cmd, pos); + grub_script_execute_sourcecode(cfgfile); + g_hiperiso_menu_esc = 0; + g_hiperiso_suppress_esc = 0; + g_hiperiso_suppress_esc_default = 1; + g_hiperiso_secondary_menu_on = 0; + + select = seldata[g_hiperiso_last_entry]; + + if (select == 2) + { + g_hiperiso_wimboot_mode = 1; + g_hiso_secondary_need_recover = 1; + } + else if (select == 3) + { + g_hiperiso_grub2_mode = 1; + g_hiso_secondary_need_recover = 2; + } + else if (select == 4) + { + g_hiperiso_memdisk_mode = 1; + g_hiso_secondary_need_recover = 3; + } + else if (select == 5) + { + grub_env_set("HISO_CHKSUM_FILE_PATH", args[0]); + grub_script_execute_sourcecode("configfile $hiso_efi_part/grub/checksum.cfg"); + } + else if (select == 6) + { + grub_env_set("HISO_SECOND_EXIT", "1"); + } + }while (select == 5); + + grub_free(cmd); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (g_hiso_secondary_need_recover == 1) + { + g_hiperiso_wimboot_mode = 0; + } + else if (g_hiso_secondary_need_recover == 2) + { + g_hiperiso_grub2_mode = 0; + } + else if (g_hiso_secondary_need_recover == 3) + { + g_hiperiso_memdisk_mode = 0; + } + + g_hiso_secondary_need_recover = 0; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_cmd_fs_ignore_case(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + if (args[0][0] == '0') + { + g_hiperiso_case_insensitive = 0; + } + else + { + g_hiperiso_case_insensitive = 1; + } + + return 0; +} + +static grub_err_t hiperiso_cmd_init_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + hiperiso_plugin_load_menu_lang(1, args[0]); + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_load_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + hiperiso_plugin_load_menu_lang(0, args[0]); + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_update_sb_policy(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + +#ifdef GRUB_MACHINE_EFI + hiperiso_set_sb_policy(); +#endif + + HIPERISO_CMD_RETURN(0); +} + +static grub_err_t hiperiso_cmd_sb_info(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + +#ifdef GRUB_MACHINE_EFI + const char *policy = NULL; + grub_efi_guid_t security = + { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; + grub_efi_guid_t security2 = + { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; + + if (g_sb_policy == HISO_SB_POLICY_BYPASS) + { + policy = "ByPass"; + } + else if (g_sb_policy == HISO_SB_POLICY_CHECK) + { + policy = "Check"; + } + else + { + policy = "XXX"; + } + + grub_printf("UEFI Security %s\n", grub_efi_locate_protocol(&security, NULL) ? "Yes" : "No"); + grub_printf("UEFI Security2 %s\n", grub_efi_locate_protocol(&security2, NULL) ? "Yes" : "No"); + grub_printf("Hiperiso Secure Policy %s\n", policy); + +#else + grub_printf("Non EFI mode!\n"); +#endif + + grub_refresh(); + + HIPERISO_CMD_RETURN(0); +} + +static int hiperiso_chksum_pathcmp(int chktype, char *rlpath, char *rdpath) +{ + char *pos1 = NULL; + char *pos2 = NULL; + + if (chktype == 2) + { + pos1 = hiperiso_str_basename(rlpath); + pos2 = hiperiso_str_basename(rdpath); + return grub_strcmp(pos1, pos2); + } + else if (chktype == 3 || chktype == 4) + { + if (grub_strcmp(rlpath, rdpath) == 0 || grub_strcmp(rlpath + 1, rdpath) == 0) + { + return 0; + } + } + + return 1; +} + +static int hiperiso_find_checksum +( + grub_file_t file, + const char *uname, + int retlen, + char *path, + int chktype, + char *chksum +) +{ + int ulen; + char *pos = NULL; + char *pos1 = NULL; + char *pos2 = NULL; + char *buf = NULL; + char *currline = NULL; + char *nextline = NULL; + + ulen = (int)grub_strlen(uname); + + /* read file to buffer */ + buf = grub_malloc(file->size + 4); + if (!buf) + { + return 1; + } + grub_file_read(file, buf, file->size); + buf[file->size] = 0; + + /* parse each line */ + for (currline = buf; currline; currline = nextline) + { + nextline = hiperiso_get_line(currline); + HISO_SKIP_SPACE(currline); + + if (grub_strncasecmp(currline, uname, ulen) == 0) + { + pos = grub_strchr(currline, '='); + pos1 = grub_strchr(currline, '('); + pos2 = grub_strchr(currline, ')'); + + if (pos && pos1 && pos2) + { + *pos2 = 0; + if (hiperiso_chksum_pathcmp(chktype, path, pos1 + 1) == 0) + { + HISO_SKIP_SPACE_NEXT(pos, 1); + grub_memcpy(chksum, pos, retlen); + goto end; + } + } + } + else if (hiperiso_str_len_alnum(currline, retlen)) + { + HISO_SKIP_SPACE_NEXT_EX(pos, currline, retlen); + if (hiperiso_chksum_pathcmp(chktype, path, pos) == 0) + { + grub_memcpy(chksum, currline, retlen); + goto end; + } + } + } + +end: + grub_free(buf); + return 0; +} + +static int hiperiso_check_chkfile(const char *isopart, char *path, const char *lchkname, grub_file_t *pfile) +{ + int ret = 0; + int cnt = 0; + char c = 0; + char *pos = NULL; + grub_file_t file = NULL; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s.%s", isopart, path, lchkname); + if (file) + { + HISO_GOTO_END(1); + } + + cnt = hiperiso_str_chrcnt(path, '/'); + if (cnt > 1) + { + pos = grub_strrchr(path, '/'); + c = *pos; + *pos = 0; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s/HIPERISO_CHECKSUM", isopart, path); + if (file) + { + *pos = c; + HISO_GOTO_END(2); + } + *pos = c; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/HIPERISO_CHECKSUM", isopart); + if (file) + { + ret = (cnt > 1) ? 3 : 4; + } + +end: + + if (pfile) + { + *pfile = file; + } + else + { + check_free(file, grub_file_close); + } + return ret; +} + +static grub_err_t hiperiso_cmd_cmp_checksum(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int index = 0; + int chktype = 0; + char *pos = NULL; + grub_file_t file = NULL; + const char *calc_value = NULL; + const char *isopart = NULL; + char fchksum[64]; + char readchk[256] = {0}; + char filebuf[512] = {0}; + char uchkname[16]; + + (void)ctxt; + + index = (int)grub_strtol(args[0], NULL, 10); + if (argc != 2 || index < 0 || index >= HISO_CHKSUM_NUM) + { + return 1; + } + + grub_strncpy(uchkname, g_lower_chksum_name[index], sizeof(uchkname)); + hiperiso_str_toupper(uchkname); + + isopart = grub_env_get("hiso_iso_part"); + calc_value = grub_env_get("VT_LAST_CHECK_SUM"); + + chktype = hiperiso_check_chkfile(isopart, args[1], g_lower_chksum_name[index], &file); + if (chktype <= 0) + { + grub_printf("\n\nNo checksum file found.\n"); + goto end; + } + + if (chktype == 1) + { + grub_snprintf(fchksum, sizeof(fchksum), ".%s", g_lower_chksum_name[index]); + grub_memset(filebuf, 0, sizeof(filebuf)); + grub_file_read(file, filebuf, 511); + + pos = grub_strchr(filebuf, '='); + if (pos) + { + HISO_SKIP_SPACE_NEXT(pos, 1); + grub_memcpy(readchk, pos, g_chksum_retlen[index]); + } + else + { + grub_memcpy(readchk, filebuf, g_chksum_retlen[index]); + } + } + else if (chktype == 3 || chktype == 4) + { + grub_snprintf(fchksum, sizeof(fchksum), "global HIPERISO_CHECKSUM"); + hiperiso_find_checksum(file, uchkname, g_chksum_retlen[index], args[1], chktype, readchk); + if (readchk[0] == 0) + { + grub_printf("\n\n%s value not found in %s.\n", uchkname, fchksum); + goto end; + } + } + else + { + grub_snprintf(fchksum, sizeof(fchksum), "local HIPERISO_CHECKSUM"); + hiperiso_find_checksum(file, uchkname, g_chksum_retlen[index], args[1], chktype, readchk); + if (readchk[0] == 0) + { + grub_file_close(file); + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/HIPERISO_CHECKSUM", isopart); + if (file) + { + grub_snprintf(fchksum, sizeof(fchksum), "global HIPERISO_CHECKSUM"); + hiperiso_find_checksum(file, uchkname, g_chksum_retlen[index], args[1], 3, readchk); + if (readchk[0] == 0) + { + grub_printf("\n\n%s value not found in both local and global HIPERISO_CHECKSUM.\n", uchkname); + goto end; + } + } + } + } + + if (grub_strcasecmp(calc_value, readchk) == 0) + { + grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname, fchksum); + } + else + { + grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname, fchksum); + grub_printf("The %s value in %s file is:\n%s\n", uchkname, fchksum, readchk); + } + +end: + grub_refresh(); + check_free(file, grub_file_close); + HIPERISO_CMD_RETURN(0); +} + +static int hiperiso_find_all_checksum +( + grub_file_t file, + char *path, + int chktype, + int exists[HISO_CHKSUM_NUM], + int *ptotexist +) +{ + int i; + int ulen; + int tot = 0; + char c = 0; + char *pos = NULL; + char *pos1 = NULL; + char *pos2 = NULL; + char *buf = NULL; + char *currline = NULL; + char *nextline = NULL; + const char *uname = NULL; + + tot = *ptotexist; + + /* read file to buffer */ + buf = grub_malloc(file->size + 4); + if (!buf) + { + return 1; + } + grub_file_read(file, buf, file->size); + buf[file->size] = 0; + + /* parse each line */ + for (currline = buf; currline; currline = nextline) + { + nextline = hiperiso_get_line(currline); + HISO_SKIP_SPACE(currline); + + for (i = 0; i < HISO_CHKSUM_NUM; i++) + { + if (exists[i]) + { + continue; + } + + uname = g_lower_chksum_name[i]; + ulen = g_lower_chksum_namelen[i]; + + if (grub_strncasecmp(currline, uname, ulen) == 0) + { + pos = grub_strchr(currline, '='); + pos1 = grub_strchr(currline, '('); + pos2 = grub_strchr(currline, ')'); + + if (pos && pos1 && pos2) + { + c = *pos2; + *pos2 = 0; + if (hiperiso_chksum_pathcmp(chktype, path, pos1 + 1) == 0) + { + exists[i] = 1; + tot++; + } + *pos2 = c; + } + } + else if (hiperiso_str_len_alnum(currline, g_chksum_retlen[i])) + { + HISO_SKIP_SPACE_NEXT_EX(pos, currline, g_chksum_retlen[i]); + if (hiperiso_chksum_pathcmp(chktype, path, pos) == 0) + { + exists[i] = 1; + tot++; + } + } + + if (tot >= HISO_CHKSUM_NUM) + { + goto end; + } + } + } + +end: + + *ptotexist = tot; + grub_free(buf); + return 0; +} + +static grub_err_t hiperiso_cmd_hisochksum_exist(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + int cnt = 0; + char c = 0; + int tip = 0; + char *pos = NULL; + grub_file_t file = NULL; + const char *isopart = NULL; + int exists[HISO_CHKSUM_NUM] = { 0, 0, 0, 0 }; + int totexist = 0; + + (void)argc; + (void)ctxt; + + isopart = grub_env_get("hiso_iso_part"); + + for (i = 0; i < HISO_CHKSUM_NUM; i++) + { + if (hiperiso_check_file_exist("%s%s.%s", isopart, args[0], g_lower_chksum_name[i])) + { + exists[i] = 1; + totexist++; + } + } + + if (totexist == HISO_CHKSUM_NUM) + { + goto end; + } + + cnt = hiperiso_str_chrcnt(args[0], '/'); + if (cnt > 1) + { + pos = grub_strrchr(args[0], '/'); + c = *pos; + *pos = 0; + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s/HIPERISO_CHECKSUM", isopart, args[0]); + *pos = c; + + if (file) + { + if (tip == 0 && file->size > (32 * HISO_SIZE_1KB)) + { + tip = 1; + grub_printf("Reading checksum file...\n"); + grub_refresh(); + } + + debug("parse local HIPERISO_CHECKSUM\n"); + hiperiso_find_all_checksum(file, args[0], 2, exists, &totexist); + grub_file_close(file); + } + } + + if (totexist == HISO_CHKSUM_NUM) + { + goto end; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/HIPERISO_CHECKSUM", isopart); + if (file) + { + if (tip == 0 && file->size > (32 * HISO_SIZE_1KB)) + { + tip = 1; + grub_printf("Reading checksum file...\n"); + grub_refresh(); + } + + debug("parse global HIPERISO_CHECKSUM\n"); + hiperiso_find_all_checksum(file, args[0], (cnt > 1) ? 3 : 4, exists, &totexist); + grub_file_close(file); + } + +end: + + hiperiso_env_int_set("VT_EXIST_MD5", exists[0]); + hiperiso_env_int_set("VT_EXIST_SHA1", exists[1]); + hiperiso_env_int_set("VT_EXIST_SHA256", exists[2]); + hiperiso_env_int_set("VT_EXIST_SHA512", exists[3]); + + HIPERISO_CMD_RETURN(0); +} + + +static const char * hiperiso_menu_lang_read_hook(struct grub_env_var *var, const char *val) +{ + (void)var; + return hiperiso_get_vmenu_title(val); +} + +int hiperiso_env_init(void) +{ + int i; + char buf[64]; + + grub_env_set("vtdebug_flag", ""); + + grub_register_hiso_menu_lang_hook(hiperiso_menu_lang_read_hook); + hiperiso_ctrl_var_init(); + hiperiso_global_var_init(); + + g_part_list_buf = grub_malloc(HISO_PART_BUF_LEN); + g_tree_script_buf = grub_malloc(HISO_MAX_SCRIPT_BUF); + g_list_script_buf = grub_malloc(HISO_MAX_SCRIPT_BUF); + for (i = 0; i < HISO_MAX_CONF_REPLACE; i++) + { + g_conf_replace_new_buf[i] = grub_malloc(hiso_max_replace_file_size); + } + + hiperiso_filt_register(0, hiperiso_wrapper_open); + + g_grub_param = (hiperiso_grub_param *)grub_zalloc(sizeof(hiperiso_grub_param)); + if (g_grub_param) + { + g_grub_param->grub_env_get = grub_env_get; + g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set; + g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf; + grub_snprintf(buf, sizeof(buf), "%p", g_grub_param); + grub_env_set("env_param", buf); + grub_env_set("hiperiso_env_param", buf); + + grub_env_export("env_param"); + grub_env_export("hiperiso_env_param"); + } + + grub_env_export("hiso_winpeshl_ini_addr"); + grub_env_export("hiso_winpeshl_ini_size"); + + grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)hiperiso_chain_file_size); + grub_env_set("hiso_chain_file_size", buf); + grub_env_export("hiso_chain_file_size"); + + grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)hiperiso_chain_file_read); + grub_env_set("hiso_chain_file_read", buf); + grub_env_export("hiso_chain_file_read"); + + grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)hiperiso_get_vmenu_title); + grub_env_set("HISO_VMENU_FUNC_ADDR", buf); + grub_env_export("HISO_VMENU_FUNC_ADDR"); + + grub_snprintf(buf, sizeof(buf), "%s-%s", GRUB_TARGET_CPU, GRUB_PLATFORM); + grub_env_set("grub_cpu_platform", buf); + grub_env_export("grub_cpu_platform"); + + return 0; +} + + + +static grub_err_t hiperiso_cmd_boot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char cmdline[2048]; + char log_dir[512]; + char linux_script[2048 + 256]; + char initrd_script[256]; + const char *iso_path; + const char *trace_level; + const char *fallback; + const char *display; + const char *vga; + const char *env_val; + int ram = 2048; + int cpus = 2; + int clen = 0; + const char *auto_install; + const char *persistence; + const char *dud; + const char *injection; + const char *conf_replace; + int secure_boot = 0; + int tpm = 0; + int net_dump = 0; + const char *cpu_features; + const char *boot_mode; + char *iso_clean; + + (void)ctxt; + + if (argc < 1 || !args[0][0]) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "usage: hiperiso_boot "); + } + + iso_path = args[0]; + + { + const char *base = grub_strrchr(iso_path, '/'); + base = base ? base + 1 : iso_path; + grub_snprintf(log_dir, sizeof(log_dir), "/hiperiso/logs/%s/", base); + } + + trace_level = hiperiso_get_env("HISO_TRACE_LEVEL"); + if (!trace_level || !trace_level[0]) + trace_level = "standard"; + + fallback = hiperiso_get_env("HISO_FALLBACK"); + if (!fallback || !fallback[0]) + fallback = "0"; + + display = hiperiso_get_env("HISO_DISPLAY"); + if (!display || !display[0]) + display = "none"; + vga = hiperiso_get_env("HISO_VGA"); + if (!vga || !vga[0]) + vga = "none"; + + env_val = hiperiso_get_env("HISO_GUEST_RAM"); + if (env_val && env_val[0]) + ram = (int)grub_strtoul(env_val, NULL, 10); + env_val = hiperiso_get_env("HISO_GUEST_CPUS"); + if (env_val && env_val[0]) + cpus = (int)grub_strtoul(env_val, NULL, 10); + + auto_install = hiperiso_get_env("HISO_AUTO_INSTALL"); + persistence = hiperiso_get_env("HISO_PERSISTENCE"); + dud = hiperiso_get_env("HISO_DUD"); + injection = hiperiso_get_env("HISO_INJECTION"); + conf_replace = hiperiso_get_env("HISO_CONF_REPLACE"); + + env_val = hiperiso_get_env("HISO_SECURE_BOOT"); + secure_boot = (env_val && env_val[0] && env_val[0] != '0') ? 1 : 0; + env_val = hiperiso_get_env("HISO_TPM"); + tpm = (env_val && env_val[0] && env_val[0] != '0') ? 1 : 0; + env_val = hiperiso_get_env("HISO_NET_DUMP"); + net_dump = (env_val && env_val[0] && env_val[0] != '0') ? 1 : 0; + cpu_features = hiperiso_get_env("HISO_CPU_FEATURES"); + boot_mode = "normal"; + if (argc >= 2 && args[1][0]) + boot_mode = args[1]; + + iso_clean = grub_strdup(iso_path); + if (iso_clean) + { + char *p; + for (p = iso_clean; *p; p++) + if (*p == '"') + *p = '\''; + } + + clen = grub_snprintf(cmdline, sizeof(cmdline), + "hiperiso_iso=\"%s\" hiperiso_log=\"%s\" hiperiso_trace_level=\"%s\" " + "hiperiso_ram=\"%d\" hiperiso_cpus=\"%d\" hiperiso_display=\"%s\" " + "hiperiso_vga=\"%s\" hiperiso_fallback=\"%s\"", + iso_clean ? iso_clean : iso_path, + log_dir, trace_level, ram, cpus, display, vga, fallback); + + if (auto_install && auto_install[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_auto_install=\"%s\"", auto_install); + if (persistence && persistence[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_persistence=\"%s\"", persistence); + if (dud && dud[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_dud=\"%s\"", dud); + if (injection && injection[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_injection=\"%s\"", injection); + if (conf_replace && conf_replace[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_conf_replace=\"%s\"", conf_replace); + if (secure_boot) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_secure_boot=\"1\""); + if (tpm) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_tpm=\"1\""); + if (cpu_features && cpu_features[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_cpu_features=\"%s\"", cpu_features); + if (boot_mode && boot_mode[0]) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_boot_mode=\"%s\"", boot_mode); + if (net_dump) + clen += grub_snprintf(cmdline + clen, sizeof(cmdline) - clen, + " hiperiso_net_dump=\"1\""); + + if (iso_clean) + grub_free(iso_clean); + + if (clen >= (int)sizeof(cmdline)) + { + debug("hiperiso_boot: cmdline too long, truncated\n"); + } + + grub_snprintf(linux_script, sizeof(linux_script), + "linux ($hiso_efi_part)/EFI/hiperiso/vmlinuz %s", cmdline); + grub_script_execute_sourcecode(linux_script); + if (grub_errno != GRUB_ERR_NONE) + { + debug("hiperiso_boot: Failed to load kernel\n"); + HIPERISO_CMD_RETURN(grub_errno); + } + + grub_snprintf(initrd_script, sizeof(initrd_script), + "initrd ($hiso_efi_part)/EFI/hiperiso/initramfs.cpio.gz"); + grub_script_execute_sourcecode(initrd_script); + if (grub_errno != GRUB_ERR_NONE) + { + debug("hiperiso_boot: Failed to load initramfs\n"); + HIPERISO_CMD_RETURN(grub_errno); + } + + debug("hiperiso_boot: Launching hypervisor for %s\n", iso_path); + + grub_script_execute_sourcecode("boot"); + + if (grub_errno != GRUB_ERR_NONE) + { + debug("hiperiso_boot: boot command failed\n"); + } + + HIPERISO_CMD_RETURN(grub_errno); +} + + +static cmd_para hiperiso_cmds[] = +{ + { "vt_browser_disk", hiperiso_cmd_browser_disk, 0, NULL, "", "", NULL }, + { "vt_browser_dir", hiperiso_cmd_browser_dir, 0, NULL, "", "", NULL }, + { "vt_incr", hiperiso_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL }, + { "vt_mod", hiperiso_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL }, + { "vt_strstr", hiperiso_cmd_strstr, 0, NULL, "", "", NULL }, + { "vt_istrstr", hiperiso_cmd_istrstr, 0, NULL, "", "", NULL }, + { "vt_str_begin", hiperiso_cmd_strbegin, 0, NULL, "", "", NULL }, + { "vt_str_casebegin", hiperiso_cmd_strcasebegin, 0, NULL, "", "", NULL }, + { "vt_debug", hiperiso_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL }, + { "vtdebug", hiperiso_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL }, + { "vtbreak", hiperiso_cmd_break, 0, NULL, "{level}", "set debug break", NULL }, + { "vt_cmp", hiperiso_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL }, + { "vt_device", hiperiso_cmd_device, 0, NULL, "path var", "", NULL }, + { "vt_check_compatible", hiperiso_cmd_check_compatible, 0, NULL, "", "", NULL }, + { "vt_list_img", hiperiso_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL }, + { "vt_clear_img", hiperiso_cmd_clear_img, 0, NULL, "", "clear image list", NULL }, + { "vt_img_name", hiperiso_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL }, + { "vt_chosen_img_path", hiperiso_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL }, + { "vt_ext_select_img_path", hiperiso_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL }, + { "vt_img_sector", hiperiso_cmd_img_sector, 0, NULL, "{imageName}", "", NULL }, + { "vt_dump_img_sector", hiperiso_cmd_dump_img_sector, 0, NULL, "", "", NULL }, + { "vt_load_wimboot", hiperiso_cmd_load_wimboot, 0, NULL, "", "", NULL }, + { "vt_load_vhdboot", hiperiso_cmd_load_vhdboot, 0, NULL, "", "", NULL }, + { "vt_patch_vhdboot", hiperiso_cmd_patch_vhdboot, 0, NULL, "", "", NULL }, + { "vt_raw_chain_data", hiperiso_cmd_raw_chain_data, 0, NULL, "", "", NULL }, + { "vt_get_hiso_type", hiperiso_cmd_get_hiso_type, 0, NULL, "", "", NULL }, + { "vt_check_custom_boot", hiperiso_cmd_check_custom_boot, 0, NULL, "", "", NULL }, + { "vt_dump_custom_boot", hiperiso_cmd_dump_custom_boot, 0, NULL, "", "", NULL }, + + { "vt_skip_svd", hiperiso_cmd_skip_svd, 0, NULL, "", "", NULL }, + { "vt_cpio_busybox64", hiperiso_cmd_cpio_busybox_64, 0, NULL, "", "", NULL }, + { "vt_load_cpio", hiperiso_cmd_load_cpio, 0, NULL, "", "", NULL }, + { "vt_trailer_cpio", hiperiso_cmd_trailer_cpio, 0, NULL, "", "", NULL }, + { "vt_push_last_entry", hiperiso_cmd_push_last_entry, 0, NULL, "", "", NULL }, + { "vt_pop_last_entry", hiperiso_cmd_pop_last_entry, 0, NULL, "", "", NULL }, + { "vt_get_lib_module_ver", hiperiso_cmd_lib_module_ver, 0, NULL, "", "", NULL }, + + { "vt_load_part_table", hiperiso_cmd_load_part_table, 0, NULL, "", "", NULL }, + { "vt_check_part_exist", hiperiso_cmd_part_exist, 0, NULL, "", "", NULL }, + { "vt_get_fs_label", hiperiso_cmd_get_fs_label, 0, NULL, "", "", NULL }, + { "vt_fs_enum_1st_file", hiperiso_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL }, + { "vt_fs_enum_1st_dir", hiperiso_cmd_fs_enum_1st_dir, 0, NULL, "", "", NULL }, + { "vt_file_basename", hiperiso_cmd_basename, 0, NULL, "", "", NULL }, + { "vt_file_basefile", hiperiso_cmd_basefile, 0, NULL, "", "", NULL }, + { "vt_enum_video_mode", hiperiso_cmd_enum_video_mode, 0, NULL, "", "", NULL }, + { "vt_get_video_mode", hiperiso_cmd_get_video_mode, 0, NULL, "", "", NULL }, + { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL }, + + + { "vt_find_first_bootable_hd", hiperiso_cmd_find_bootable_hdd, 0, NULL, "", "", NULL }, + { "vt_dump_menu", hiperiso_cmd_dump_menu, 0, NULL, "", "", NULL }, + { "vt_dynamic_menu", hiperiso_cmd_dynamic_menu, 0, NULL, "", "", NULL }, + { "vt_check_mode", hiperiso_cmd_check_mode, 0, NULL, "", "", NULL }, + { "vt_dump_img_list", hiperiso_cmd_dump_img_list, 0, NULL, "", "", NULL }, + { "vt_dump_injection", hiperiso_cmd_dump_injection, 0, NULL, "", "", NULL }, + { "vt_dump_auto_install", hiperiso_cmd_dump_auto_install, 0, NULL, "", "", NULL }, + { "vt_dump_persistence", hiperiso_cmd_dump_persistence, 0, NULL, "", "", NULL }, + { "vt_select_auto_install", hiperiso_cmd_sel_auto_install, 0, NULL, "", "", NULL }, + { "vt_select_persistence", hiperiso_cmd_sel_persistence, 0, NULL, "", "", NULL }, + { "vt_select_conf_replace", hiperiso_select_conf_replace, 0, NULL, "", "", NULL }, + + { "vt_iso9660_nojoliet", hiperiso_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL }, + { "vt_iso9660_isjoliet", hiperiso_cmd_iso9660_is_joliet, 0, NULL, "", "", NULL }, + { "vt_is_udf", hiperiso_cmd_is_udf, 0, NULL, "", "", NULL }, + { "vt_file_size", hiperiso_cmd_file_size, 0, NULL, "", "", NULL }, + { "vt_load_file_to_mem", hiperiso_cmd_load_file_to_mem, 0, NULL, "", "", NULL }, + { "vt_load_img_memdisk", hiperiso_cmd_load_img_memdisk, 0, NULL, "", "", NULL }, + { "vt_concat_efi_iso", hiperiso_cmd_concat_efi_iso, 0, NULL, "", "", NULL }, + + { "vt_linux_parse_initrd_isolinux", hiperiso_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL }, + { "vt_linux_parse_initrd_grub", hiperiso_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL }, + { "vt_linux_specify_initrd_file", hiperiso_cmd_specify_initrd_file, 0, NULL, "", "", NULL }, + { "vt_linux_clear_initrd", hiperiso_cmd_clear_initrd_list, 0, NULL, "", "", NULL }, + { "vt_linux_dump_initrd", hiperiso_cmd_dump_initrd_list, 0, NULL, "", "", NULL }, + { "vt_linux_initrd_count", hiperiso_cmd_initrd_count, 0, NULL, "", "", NULL }, + { "vt_linux_valid_initrd_count", hiperiso_cmd_valid_initrd_count, 0, NULL, "", "", NULL }, + { "vt_linux_locate_initrd", hiperiso_cmd_linux_locate_initrd, 0, NULL, "", "", NULL }, + { "vt_linux_chain_data", hiperiso_cmd_linux_chain_data, 0, NULL, "", "", NULL }, + { "vt_linux_get_main_initrd_index", hiperiso_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL }, + + { "vt_windows_reset", hiperiso_cmd_wimdows_reset, 0, NULL, "", "", NULL }, + { "vt_windows_chain_data", hiperiso_cmd_windows_chain_data, 0, NULL, "", "", NULL }, + { "vt_windows_wimboot_data", hiperiso_cmd_windows_wimboot_data, 0, NULL, "", "", NULL }, + { "vt_windows_collect_wim_patch", hiperiso_cmd_collect_wim_patch, 0, NULL, "", "", NULL }, + { "vt_windows_locate_wim_patch", hiperiso_cmd_locate_wim_patch, 0, NULL, "", "", NULL }, + { "vt_windows_count_wim_patch", hiperiso_cmd_wim_patch_count, 0, NULL, "", "", NULL }, + { "vt_dump_wim_patch", hiperiso_cmd_dump_wim_patch, 0, NULL, "", "", NULL }, + { "vt_wim_check_bootable", hiperiso_cmd_wim_check_bootable, 0, NULL, "", "", NULL }, + { "vt_wim_chain_data", hiperiso_cmd_wim_chain_data, 0, NULL, "", "", NULL }, + + { "vt_add_replace_file", hiperiso_cmd_add_replace_file, 0, NULL, "", "", NULL }, + { "vt_get_replace_file_cnt", hiperiso_cmd_get_replace_file_cnt, 0, NULL, "", "", NULL }, + { "vt_test_block_list", hiperiso_cmd_test_block_list, 0, NULL, "", "", NULL }, + { "vt_file_exist_nocase", hiperiso_cmd_file_exist_nocase, 0, NULL, "", "", NULL }, + + + { "vt_load_plugin", hiperiso_cmd_load_plugin, 0, NULL, "", "", NULL }, + { "vt_check_plugin_json", hiperiso_cmd_plugin_check_json, 0, NULL, "", "", NULL }, + { "vt_check_password", hiperiso_cmd_check_password, 0, NULL, "", "", NULL }, + + { "vt_1st_line", hiperiso_cmd_read_1st_line, 0, NULL, "", "", NULL }, + { "vt_file_strstr", hiperiso_cmd_file_strstr, 0, NULL, "", "", NULL }, + { "vt_img_part_info", hiperiso_cmd_img_part_info, 0, NULL, "", "", NULL }, + + + { "vt_parse_iso_volume", hiperiso_cmd_parse_volume, 0, NULL, "", "", NULL }, + { "vt_parse_iso_create_date", hiperiso_cmd_parse_create_date, 0, NULL, "", "", NULL }, + { "vt_parse_freenas_ver", hiperiso_cmd_parse_freenas_ver, 0, NULL, "", "", NULL }, + { "vt_unix_parse_freebsd_ver", hiperiso_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL }, + { "vt_unix_parse_freebsd_ver_elf", hiperiso_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL }, + { "vt_unix_reset", hiperiso_cmd_unix_reset, 0, NULL, "", "", NULL }, + { "vt_unix_check_vlnk", hiperiso_cmd_unix_check_vlnk, 0, NULL, "", "", NULL }, + { "vt_unix_replace_conf", hiperiso_cmd_unix_replace_conf, 0, NULL, "", "", NULL }, + { "vt_unix_replace_grub_conf", hiperiso_cmd_unix_replace_grub_conf, 0, NULL, "", "", NULL }, + { "vt_unix_replace_ko", hiperiso_cmd_unix_replace_ko, 0, NULL, "", "", NULL }, + { "vt_unix_ko_fillmap", hiperiso_cmd_unix_ko_fillmap, 0, NULL, "", "", NULL }, + { "vt_unix_fill_image_desc", hiperiso_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL }, + { "vt_unix_gzip_new_ko", hiperiso_cmd_unix_gzip_newko, 0, NULL, "", "", NULL }, + { "vt_unix_chain_data", hiperiso_cmd_unix_chain_data, 0, NULL, "", "", NULL }, + + { "vt_img_hook_root", hiperiso_cmd_img_hook_root, 0, NULL, "", "", NULL }, + { "vt_img_unhook_root", hiperiso_cmd_img_unhook_root, 0, NULL, "", "", NULL }, + { "vt_acpi_param", hiperiso_cmd_acpi_param, 0, NULL, "", "", NULL }, + { "vt_check_secureboot_var", hiperiso_cmd_check_secureboot_var, 0, NULL, "", "", NULL }, + { "vt_clear_key", hiperiso_cmd_clear_key, 0, NULL, "", "", NULL }, + { "vt_img_check_range", hiperiso_cmd_img_check_range, 0, NULL, "", "", NULL }, + { "vt_is_pe64", hiperiso_cmd_is_pe64, 0, NULL, "", "", NULL }, + { "vt_sel_wimboot", hiperiso_cmd_sel_wimboot, 0, NULL, "", "", NULL }, + { "vt_set_wim_load_prompt", hiperiso_cmd_set_wim_prompt, 0, NULL, "", "", NULL }, + { "vt_set_theme", hiperiso_cmd_set_theme, 0, NULL, "", "", NULL }, + { "vt_set_theme_path", hiperiso_cmd_set_theme_path, 0, NULL, "", "", NULL }, + { "vt_select_theme_cfg", hiperiso_cmd_select_theme_cfg, 0, NULL, "", "", NULL }, + + { "vt_get_efi_vdisk_offset", hiperiso_cmd_get_efivdisk_offset, 0, NULL, "", "", NULL }, + { "vt_search_replace_initrd", hiperiso_cmd_search_replace_initrd, 0, NULL, "", "", NULL }, + { "vt_push_pager", hiperiso_cmd_push_pager, 0, NULL, "", "", NULL }, + { "vt_pop_pager", hiperiso_cmd_pop_pager, 0, NULL, "", "", NULL }, + { "vt_check_json_path_case", hiperiso_cmd_chk_json_pathcase, 0, NULL, "", "", NULL }, + { "vt_append_extra_sector", hiperiso_cmd_append_ext_sector, 0, NULL, "", "", NULL }, + { "gptpriority", grub_cmd_gptpriority, 0, NULL, "", "", NULL }, + { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet, 0, NULL, "", "", NULL }, + { "vt_vlnk_check", grub_cmd_check_vlnk, 0, NULL, "", "", NULL }, + { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part, 0, NULL, "", "", NULL }, + { "vt_is_vlnk_name", grub_cmd_is_vlnk_name, 0, NULL, "", "", NULL }, + { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst, 0, NULL, "", "", NULL }, + { "vt_set_fake_vlnk", hiperiso_cmd_set_fake_vlnk, 0, NULL, "", "", NULL }, + { "vt_reset_fake_vlnk", hiperiso_cmd_reset_fake_vlnk, 0, NULL, "", "", NULL }, + { "vt_iso_vd_id_parse", hiperiso_cmd_iso_vd_id_parse, 0, NULL, "", "", NULL }, + { "vt_iso_vd_id_clear", hiperiso_iso_vd_id_clear, 0, NULL, "", "", NULL }, + { "vt_iso_vd_id_begin", hiperiso_cmd_iso_vd_id_begin, 0, NULL, "", "", NULL }, + { "vt_fn_mutex_lock", hiperiso_cmd_fn_mutex_lock, 0, NULL, "", "", NULL }, + { "vt_efi_dump_rsv_page", hiperiso_cmd_dump_rsv_page, 0, NULL, "", "", NULL }, + { "vt_is_standard_winiso", hiperiso_cmd_is_standard_winiso, 0, NULL, "", "", NULL }, + { "vt_sel_winpe_wim", hiperiso_cmd_sel_winpe_wim, 0, NULL, "", "", NULL }, + { "vt_need_secondary_menu", hiperiso_cmd_need_secondary_menu, 0, NULL, "", "", NULL }, + { "vt_show_secondary_menu", hiperiso_cmd_show_secondary_menu, 0, NULL, "", "", NULL }, + { "vt_fs_ignore_case", hiperiso_cmd_fs_ignore_case, 0, NULL, "", "", NULL }, + { "vt_systemd_menu", hiperiso_cmd_linux_systemd_menu, 0, NULL, "", "", NULL }, + { "vt_limine_menu", hiperiso_cmd_linux_limine_menu, 0, NULL, "", "", NULL }, + { "vt_secondary_recover_mode", hiperiso_cmd_secondary_recover_mode, 0, NULL, "", "", NULL }, + { "vt_load_menu_lang", hiperiso_cmd_load_menu_lang, 0, NULL, "", "", NULL }, + { "vt_init_menu_lang", hiperiso_cmd_init_menu_lang, 0, NULL, "", "", NULL }, + { "vt_cur_menu_lang", hiperiso_cmd_cur_menu_lang, 0, NULL, "", "", NULL }, + { "vt_hisochksum_exist", hiperiso_cmd_hisochksum_exist, 0, NULL, "", "", NULL }, + { "vt_cmp_checksum", hiperiso_cmd_cmp_checksum, 0, NULL, "", "", NULL }, + { "vt_push_menu_lang", hiperiso_cmd_push_menulang, 0, NULL, "", "", NULL }, + { "vt_pop_menu_lang", hiperiso_cmd_pop_menulang, 0, NULL, "", "", NULL }, + { "vt_linux_initrd", hiperiso_cmd_linux_initrd, 0, NULL, "", "", NULL }, + + { "vt_sbinfo", hiperiso_cmd_sb_info, 0, NULL, "", "", NULL }, + { "vt_update_sb_policy", hiperiso_cmd_update_sb_policy, 0, NULL, "", "", NULL }, + + { "hiperiso_boot", hiperiso_cmd_boot, 0, NULL, "{iso_path}", "Boot ISO via KVM/QEMU hypervisor", NULL }, + +}; + +int hiperiso_register_all_cmd(void) +{ + grub_uint32_t i; + cmd_para *cur = NULL; + + for (i = 0; i < ARRAY_SIZE(hiperiso_cmds); i++) + { + cur = hiperiso_cmds + i; + cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags, + cur->summary, cur->description, cur->parser); + } + + return 0; +} + +int hiperiso_unregister_all_cmd(void) +{ + grub_uint32_t i; + + for (i = 0; i < ARRAY_SIZE(hiperiso_cmds); i++) + { + grub_unregister_extcmd(hiperiso_cmds[i].cmd); + } + + return 0; +} + + diff --git a/src/grub2/hiperiso_def.h b/src/grub2/hiperiso_def.h new file mode 100644 index 0000000..64e343e --- /dev/null +++ b/src/grub2/hiperiso_def.h @@ -0,0 +1,1345 @@ +/****************************************************************************** + * hiperiso_def.h + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#ifndef __HIPERISO_DEF_H__ +#define __HIPERISO_DEF_H__ + +#define HISO_MAX_DIR_DEPTH 32 + +#define HISO_MAX_SCRIPT_BUF (4 * 1024 * 1024) + +#define HISO_PART_BUF_LEN (128 * 1024) + +#define HISO_FILT_MIN_FILE_SIZE 32768 + +#define HISO_LINUX_SYSTEMD_MENU_MAX_BUF 16384 + +#define HISO_SIZE_1GB 1073741824 +#define HISO_SIZE_1MB (1024 * 1024) +#define HISO_SIZE_2MB (2 * 1024 * 1024) +#define HISO_SIZE_4MB (4 * 1024 * 1024) +#define HISO_SIZE_512KB (512 * 1024) +#define HISO_SIZE_1KB 1024 +#define HISO_SIZE_4KB 4096 +#define HISO_SIZE_32KB (32 * 1024) +#define HISO_SIZE_128KB (128 * 1024) + +#define JSON_SUCCESS 0 +#define JSON_FAILED 1 +#define JSON_NOT_FOUND 2 + +#define WINDATA_FLAG_TEMPLATE 1 + +#define ulong unsigned long +#define ulonglong unsigned long long + +#define hiso_to_upper(c) (((char)(c) >= 'a' && (char)(c) <= 'z') ? ((char)(c) - 'a' + 'A') : (char)(c)) + +#define HIPERISO_CMD_RETURN(err) grub_errno = (err); return (err) +#define HIPERISO_FILE_TYPE (GRUB_FILE_TYPE_NO_DECOMPRESS | GRUB_FILE_TYPE_LINUX_INITRD) + +#define hiperiso_env_op1(op, a) grub_env_##op(a) +#define hiperiso_env_op2(op, a, b) grub_env_##op((a), (b)) + +#define hiperiso_get_env(key) hiperiso_env_op1(get, key) +#define hiperiso_set_env(key, val) hiperiso_env_op2(set, key, val) + +#define HISO_WARNING "!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!" + +#define HISO_CHKSUM_NUM 4 + +#define HISO_PLAT_I386_UEFI 0x49413332 +#define HISO_PLAT_ARM64_UEFI 0x41413634 +#define HISO_PLAT_X86_64_UEFI 0x55454649 +#define HISO_PLAT_X86_LEGACY 0x42494f53 +#define HISO_PLAT_MIPS_UEFI 0x4D495053 + +#define HISO_COMM_CPIO "hiperiso.cpio" +#if defined(__arm__) || defined(__aarch64__) +#define HISO_ARCH_CPIO "hiperiso_arm64.cpio" +#elif defined(__mips__) +#define HISO_ARCH_CPIO "hiperiso_mips64.cpio" +#else +#define HISO_ARCH_CPIO "hiperiso_x86.cpio" +#endif + +#define hiperiso_left_key "VTLE_LFT" +#define hiperiso_top_key "VTLE_TOP" +#define hiperiso_color_key "VTLE_CLR" + +#define hiperiso_varg_4(arg) arg[0], arg[1], arg[2], arg[3] +#define hiperiso_varg_8(arg) arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7] + +#define HISO_PWD_CORRUPTED(err) \ +{\ + grub_printf("\n\n Password corrupted, will reboot after 5 seconds.\n\n"); \ + grub_refresh(); \ + grub_sleep(5); \ + grub_exit(); \ + return (err);\ +} + +#define hiso_tip(wait_seconds, fmt, ...) \ + grub_printf(fmt, __VA_ARGS__); \ + grub_refresh(); \ + grub_sleep(wait_seconds) + + +#define HISO_APPEND_NEWBUF(buf) \ +{\ + char *__c = buf;\ + while (*__c)\ + {\ + newbuf[pos++] = *__c;\ + __c++;\ + }\ +} + +#define HISO_SKIP_SPACE(s) \ + while (hiperiso_isspace(*s)) \ + {\ + s++;\ + } + +#define HISO_SKIP_SPACE_NEXT(s, initial) \ + s += initial;\ + while (hiperiso_isspace(*s)) \ + {\ + s++;\ + } + +#define HISO_SKIP_SPACE_NEXT_EX(s, base, initial) \ + s = base + initial;\ + while (hiperiso_isspace(*s)) \ + {\ + s++;\ + } + +#define HISO_GOTO_END(v) ret = v; goto end + +typedef enum HISO_FILE_FLT +{ + HISO_FILE_FLT_ISO = 0, /* .iso */ + HISO_FILE_FLT_WIM, /* .wim */ + HISO_FILE_FLT_EFI, /* .efi */ + HISO_FILE_FLT_IMG, /* .img */ + HISO_FILE_FLT_VHD, /* .vhd(x) */ + HISO_FILE_FLT_HISO, /* .hiso */ + + HISO_FILE_FLT_BUTT +}HISO_FILE_FLT; + +#define FILE_FLT(type) (0 == g_hiso_file_flt[HISO_FILE_FLT_##type]) + +typedef struct hiperiso_initrd_ctx +{ + const char *path_prefix; + const char *dir_prefix; +}hiperiso_initrd_ctx; + +typedef struct cmd_para +{ + const char *name; + grub_extcmd_func_t func; + grub_command_flags_t flags; + const struct grub_arg_option *parser; + + const char *summary; + const char *description; + + grub_extcmd_t cmd; +}cmd_para; + +#define hiperiso_align_2k(value) ((value + 2047) / 2048 * 2048) +#define hiperiso_align(value, align) (((value) + ((align) - 1)) & (~((align) - 1))) + +#pragma pack(1) +typedef struct cpio_newc_header +{ + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}cpio_newc_header; +#pragma pack() + + +#define cmd_raw_name ctxt->extcmd->cmd->name +#define check_free(p, func) if (p) { func(p); p = NULL; } +#define grub_check_free(p) if (p) { grub_free(p); p = NULL; } + +#define HISO_SHIM_POLICY_GUID {0x90a29d14, 0x3968, 0x48fe, { 0x85, 0x81, 0x6b, 0x7f, 0x7d, 0xc4, 0x70, 0x55 }}; + +typedef void (*HISO_BYPASS_SB)(void); +typedef void (*HISO_CHECK_SB)(void); +typedef void (*HISO_LAUNCHED)(void); +typedef struct _HISO_SHIM{ + HISO_BYPASS_SB ByPassSB; + HISO_CHECK_SB CheckSB; + HISO_LAUNCHED Launched; +} HISO_SHIM; + + +typedef int (*grub_char_check_func)(int c); +#define hiperiso_is_decimal(str) hiperiso_string_check(str, grub_isdigit) + +#define OFFSET_OF(TYPE, MEMBER) ((grub_size_t) &((TYPE *)0)->MEMBER) + +#pragma pack(1) +typedef struct hiperiso_patch_vhd +{ + grub_uint8_t part_offset_or_guid[16]; + grub_uint32_t reserved1; + grub_uint32_t part_type; + grub_uint8_t disk_signature_or_guid[16]; + grub_uint8_t reserved2[16]; + grub_uint8_t vhd_file_path[1]; +}hiperiso_patch_vhd; +#pragma pack() + +// El Torito Boot Record Volume Descriptor +#pragma pack(1) +typedef struct eltorito_descriptor +{ + grub_uint8_t type; + grub_uint8_t id[5]; + grub_uint8_t version; + grub_uint8_t system_id[32]; + grub_uint8_t reserved[32]; + grub_uint32_t sector; +}eltorito_descriptor; + +typedef struct hiperiso_iso9660_override +{ + grub_uint32_t first_sector; + grub_uint32_t first_sector_be; + grub_uint32_t size; + grub_uint32_t size_be; +}hiperiso_iso9660_override; + +typedef struct hiperiso_udf_override +{ + grub_uint32_t length; + grub_uint32_t position; +}hiperiso_udf_override; + +typedef struct hiperiso_iso9660_vd +{ + grub_uint8_t type; + grub_uint8_t id[5]; + grub_uint8_t ver; + grub_uint8_t res; + char sys[32]; + char vol[32]; + grub_uint8_t res2[8]; + grub_uint32_t space; +}hiperiso_iso9660_vd; + +/* https://wiki.osdev.org/El-Torito */ +typedef struct boot_info_table +{ + grub_uint32_t bi_data0; + grub_uint32_t bi_data1; + grub_uint32_t bi_PrimaryVolumeDescriptor; + grub_uint32_t bi_BootFileLocation; + grub_uint32_t bi_BootFileLength; + grub_uint32_t bi_Checksum; + grub_uint8_t bi_Reserved[40]; +}boot_info_table; + +#pragma pack() + +#define img_type_start 0 +#define img_type_iso 0 +#define img_type_wim 1 +#define img_type_efi 2 +#define img_type_img 3 +#define img_type_vhd 4 +#define img_type_hiso 5 +#define img_type_max 6 + +typedef struct img_info +{ + int pathlen; + char path[512]; + char name[256]; + + const char *alias; + const char *tip1; + const char *tip2; + const char *class; + const char *menu_prefix; + + int id; + int type; + int plugin_list_index; + grub_uint64_t size; + int select; + int unsupport; + + void *parent; + + struct img_info *next; + struct img_info *prev; +}img_info; + +typedef struct img_iterator_node +{ + struct img_iterator_node *next; + img_info **tail; + char dir[400]; + int dirlen; + int level; + int isocnt; + int done; + int select; + + int plugin_list_index; + + struct img_iterator_node *parent; + struct img_iterator_node *firstchild; + + void *firstiso; +}img_iterator_node; + + + +typedef struct initrd_info +{ + char name[256]; + + grub_uint64_t offset; + grub_uint64_t size; + + grub_uint8_t iso_type; // 0: iso9660 1:udf + grub_uint32_t udf_start_block; + + grub_uint64_t override_offset; + grub_uint32_t override_length; + char override_data[32]; + + struct initrd_info *next; + struct initrd_info *prev; +}initrd_info; + +extern initrd_info *g_initrd_img_list; +extern initrd_info *g_initrd_img_tail; +extern int g_initrd_img_count; +extern int g_valid_initrd_count; + +extern img_info *g_hiperiso_img_list; +extern int g_hiperiso_img_count; + +extern grub_uint8_t *g_hiperiso_cpio_buf; +extern grub_uint32_t g_hiperiso_cpio_size; +extern cpio_newc_header *g_hiperiso_initrd_head; +extern grub_uint8_t *g_hiperiso_runtime_buf; + +extern hiperiso_guid g_hiperiso_guid; + +extern hiperiso_img_chunk_list g_img_chunk_list; +extern hiperiso_img_chunk_list g_wimiso_chunk_list; +extern char *g_wimiso_path; +extern grub_uint32_t g_wimiso_size; +extern char g_arch_mode_suffix[64]; +extern const char *g_menu_prefix[img_type_max]; + +extern int g_hiperiso_debug; +void hiperiso_debug(const char *fmt, ...); +#define debug(fmt, args...) if (g_hiperiso_debug) hiperiso_debug("[HISO]: "fmt, ##args) + +#define hiso_ssprintf(buf, pos, fmt, args...) \ + pos += grub_snprintf(buf + pos, HISO_MAX_SCRIPT_BUF - pos, fmt, ##args) + +#define hiso_len_ssprintf(buf, pos, len, fmt, args...) \ + pos += grub_snprintf(buf + pos, len - pos, fmt, ##args) + +#define browser_ssprintf(mbuf, fmt, args...) \ + (mbuf)->pos += grub_snprintf((mbuf)->buf + (mbuf)->pos, (mbuf)->max - (mbuf)->pos, fmt, ##args) + +#define hiso_dummy_menuentry(buf, pos, len, title, class) \ + hiso_len_ssprintf(buf, pos, len, "menuentry \"%s\" --class=\"%s\" {\n echo \"\"\n}\n", title, class) + + +#define FLAG_HEADER_RESERVED 0x00000001 +#define FLAG_HEADER_COMPRESSION 0x00000002 +#define FLAG_HEADER_READONLY 0x00000004 +#define FLAG_HEADER_SPANNED 0x00000008 +#define FLAG_HEADER_RESOURCE_ONLY 0x00000010 +#define FLAG_HEADER_METADATA_ONLY 0x00000020 +#define FLAG_HEADER_WRITE_IN_PROGRESS 0x00000040 +#define FLAG_HEADER_RP_FIX 0x00000080 // reparse point fixup +#define FLAG_HEADER_COMPRESS_RESERVED 0x00010000 +#define FLAG_HEADER_COMPRESS_XPRESS 0x00020000 +#define FLAG_HEADER_COMPRESS_LZX 0x00040000 +#define FLAG_HEADER_COMPRESS_LZMS 0x00080000 + +#define RESHDR_FLAG_FREE 0x01 +#define RESHDR_FLAG_METADATA 0x02 +#define RESHDR_FLAG_COMPRESSED 0x04 +#define RESHDR_FLAG_SPANNED 0x08 + +#pragma pack(1) + +/* A WIM resource header */ +typedef struct wim_resource_header +{ + grub_uint64_t size_in_wim:56; /* Compressed length */ + grub_uint64_t flags:8; /* flags */ + grub_uint64_t offset; /* Offset */ + grub_uint64_t raw_size; /* Uncompressed length */ +}wim_resource_header; + +/* WIM resource header length mask */ +#define WIM_RESHDR_ZLEN_MASK 0x00ffffffffffffffULL + +/* WIM resource header flags */ +typedef enum wim_resource_header_flags +{ + WIM_RESHDR_METADATA = ( 0x02ULL << 56 ), /* Resource contains metadata */ + WIM_RESHDR_COMPRESSED = ( 0x04ULL << 56 ), /* Resource is compressed */ + WIM_RESHDR_PACKED_STREAMS = ( 0x10ULL << 56 ), /* Resource is compressed using packed streams */ +}wim_resource_header_flags; + +#define WIM_HEAD_SIGNATURE "MSWIM\0\0" + +/* WIM header */ +typedef struct wim_header +{ + grub_uint8_t signature[8]; /* Signature */ + grub_uint32_t header_len; /* Header length */ + grub_uint32_t version; /* Verson */ + grub_uint32_t flags; /* Flags */ + grub_uint32_t chunk_len; /* Chunk length */ + grub_uint8_t guid[16]; /* GUID */ + grub_uint16_t part; /* Part number */ + grub_uint16_t parts; /* Total number of parts */ + grub_uint32_t images; /* number of images */ + wim_resource_header lookup; /* Lookup table */ + wim_resource_header xml; /* XML data */ + wim_resource_header metadata; /* Boot metadata */ + grub_uint32_t boot_index; /* Boot index */ + wim_resource_header integrity; /* Integrity table */ + grub_uint8_t reserved[60]; /* Reserved */ +} wim_header; + +/* WIM header flags */ +typedef enum wim_header_flags +{ + WIM_HDR_XPRESS = 0x00020000, /* WIM uses Xpress compresson */ + WIM_HDR_LZX = 0x00040000, /* WIM uses LZX compression */ +}wim_header_flags; + +/* A WIM file hash */ +typedef struct wim_hash +{ + /* SHA-1 hash */ + grub_uint8_t sha1[20]; +}wim_hash; + +/* A WIM lookup table entry */ +typedef struct wim_lookup_entry +{ + wim_resource_header resource; /* Resource header */ + grub_uint16_t part; /* Part number */ + grub_uint32_t refcnt; /* Reference count */ + wim_hash hash; /* Hash */ +}wim_lookup_entry; + +/* WIM chunk length */ +#define WIM_CHUNK_LEN 32768 + +/* A WIM chunk buffer */ +typedef struct wim_chunk_buffer +{ + grub_uint8_t data[WIM_CHUNK_LEN]; /*Data */ +}wim_chunk_buffer; + +/* Security data */ +typedef struct wim_security_header +{ + grub_uint32_t len; /* Length */ + grub_uint32_t count; /* Number of entries */ +}wim_security_header; + +typedef struct wim_stream_entry +{ + grub_uint64_t len; + grub_uint64_t unused1; + wim_hash hash; + grub_uint16_t name_len; + /* name */ +}wim_stream_entry; + +/* Directory entry */ +typedef struct wim_directory_entry +{ + grub_uint64_t len; /* Length */ + grub_uint32_t attributes; /* Attributes */ + grub_uint32_t security; /* Security ID */ + grub_uint64_t subdir; /* Subdirectory offset */ + grub_uint8_t reserved1[16]; /* Reserved */ + grub_uint64_t created; /* Creation time */ + grub_uint64_t accessed; /* Last access time */ + grub_uint64_t written; /* Last written time */ + wim_hash hash; /* Hash */ + grub_uint8_t reserved2[12]; /* Reserved */ + grub_uint16_t streams; /* Streams */ + grub_uint16_t short_name_len; /* Short name length */ + grub_uint16_t name_len; /* Name length */ +}wim_directory_entry; + +/** Normal file */ +#define WIM_ATTR_NORMAL 0x00000080UL + +/** No security information exists for this file */ +#define WIM_NO_SECURITY 0xffffffffUL + +typedef struct reg_vk +{ + grub_uint32_t res1; + grub_uint16_t sig; + grub_uint16_t namesize; + grub_uint32_t datasize; + grub_uint32_t dataoffset; + grub_uint32_t datatype; + grub_uint16_t flag; + grub_uint16_t res2; +}reg_vk; + +#pragma pack() + + +typedef struct wim_tail +{ + grub_uint32_t wim_raw_size; + grub_uint32_t wim_align_size; + + grub_uint8_t iso_type; + grub_uint64_t file_offset; + grub_uint32_t udf_start_block; + grub_uint64_t fe_entry_size_offset; + grub_uint64_t override_offset; + grub_uint32_t override_len; + grub_uint8_t override_data[32]; + + wim_header wim_header; + + wim_hash bin_hash; + grub_uint32_t jump_exe_len; + grub_uint8_t *jump_bin_data; + grub_uint32_t bin_raw_len; + grub_uint32_t bin_align_len; + grub_uint32_t windata_flag; + + grub_uint8_t *new_meta_data; + grub_uint32_t new_meta_len; + grub_uint32_t new_meta_align_len; + + grub_uint8_t *new_lookup_data; + grub_uint32_t new_lookup_len; + grub_uint32_t new_lookup_align_len; +}wim_tail; + +typedef struct wim_patch +{ + int pathlen; + char path[256]; + + wim_hash old_hash; + wim_tail wim_data; + wim_lookup_entry *replace_look; + + int valid; + + struct wim_patch *next; +}wim_patch; + + +typedef enum _JSON_TYPE +{ + JSON_TYPE_NUMBER = 0, + JSON_TYPE_STRING, + JSON_TYPE_BOOL, + JSON_TYPE_ARRAY, + JSON_TYPE_OBJECT, + JSON_TYPE_NULL, + JSON_TYPE_BUTT +}JSON_TYPE; + + +typedef struct _HISO_JSON +{ + struct _HISO_JSON *pstPrev; + struct _HISO_JSON *pstNext; + struct _HISO_JSON *pstChild; + + JSON_TYPE enDataType; + union + { + char *pcStrVal; + int iNumVal; + grub_uint64_t lValue; + }unData; + + char *pcName; +}HISO_JSON; + +typedef struct _JSON_PARSE +{ + char *pcKey; + void *pDataBuf; + grub_uint32_t uiBufSize; +}JSON_PARSE; + +#define JSON_NEW_ITEM(pstJson, ret) \ +{ \ + (pstJson) = (HISO_JSON *)grub_zalloc(sizeof(HISO_JSON)); \ + if (NULL == (pstJson)) \ + { \ + json_debug("Failed to alloc memory for json.\n"); \ + return (ret); \ + } \ +} + +typedef int (*hiperiso_plugin_entry_pf)(HISO_JSON *json, const char *isodisk); +typedef int (*hiperiso_plugin_check_pf)(HISO_JSON *json, const char *isodisk); + +typedef struct plugin_entry +{ + const char *key; + hiperiso_plugin_entry_pf entryfunc; + hiperiso_plugin_check_pf checkfunc; + int flag; +}plugin_entry; + +typedef struct replace_fs_dir +{ + grub_device_t dev; + grub_fs_t fs; + char fullpath[512]; + char initrd[512]; + int curpos; + int dircnt; + int filecnt; +}replace_fs_dir; + +typedef struct chk_case_fs_dir +{ + grub_device_t dev; + grub_fs_t fs; +}chk_case_fs_dir; + +int hiperiso_str_all_digit(const char *str); +int hiperiso_str_all_alnum(const char *str); +int hiperiso_str_len_alnum(const char *str, int len); +char * hiperiso_str_basename(char *path); +grub_err_t hiperiso_env_int_set(const char *name, int value); +int hiperiso_str_chrcnt(const char *str, char c); +int hiperiso_strcmp(const char *pattern, const char *str); +int hiperiso_strncmp (const char *pattern, const char *str, grub_size_t n); +void hiperiso_fill_os_param(grub_file_t file, hiperiso_os_param *param); +grub_err_t hiperiso_cmd_isolinux_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_grub_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_dump_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_clear_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args); +grub_uint32_t hiperiso_get_iso_boot_catlog(grub_file_t file); +int hiperiso_has_efi_eltorito(grub_file_t file, grub_uint32_t sector); +grub_err_t hiperiso_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_linux_systemd_menu(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_linux_initrd(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_linux_limine_menu(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_append_ext_sector(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_skip_svd(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name); +grub_file_t hiperiso_grub_file_open(enum grub_file_type type, const char *fmt, ...); +grub_uint64_t hiperiso_grub_get_file_size(const char *fmt, ...); +int hiperiso_is_dir_exist(const char *fmt, ...); +int hiperiso_fill_data(grub_uint32_t buflen, char *buffer); +grub_err_t hiperiso_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_is_pe64(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_windows_wimboot_data(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_is_standard_winiso(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_sel_wimboot(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_set_wim_prompt(grub_extcmd_context_t ctxt, int argc, char **args); +grub_ssize_t hiperiso_load_file_with_prompt(grub_file_t file, void *buf, grub_ssize_t size); +int hiperiso_need_prompt_load_file(void); + +HISO_JSON *hiso_json_find_item +( + HISO_JSON *pstJson, + JSON_TYPE enDataType, + const char *szKey +); +int hiso_json_parse_value +( + char *pcNewStart, + char *pcRawStart, + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +); +HISO_JSON * hiso_json_create(void); +int hiso_json_parse(HISO_JSON *pstJson, const char *szJsonData); + +int hiso_json_scan_parse +( + const HISO_JSON *pstJson, + grub_uint32_t uiParseNum, + JSON_PARSE *pstJsonParse +); + +int hiso_json_scan_array +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstArrayItem +); + +int hiso_json_scan_array_ex +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstArrayItem +); +int hiso_json_scan_object +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstObjectItem +); +int hiso_json_get_int +( + HISO_JSON *pstJson, + const char *szKey, + int *piValue +); +int hiso_json_get_uint +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint32_t *puiValue +); +int hiso_json_get_uint64 +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint64_t *pui64Value +); +int hiso_json_get_bool +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint8_t *pbValue +); +int hiso_json_get_string +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint32_t uiBufLen, + char *pcBuf +); +const char * hiso_json_get_string_ex(HISO_JSON *pstJson, const char *szKey); +int hiso_json_destroy(HISO_JSON *pstJson); + + +grub_uint32_t CalculateCrc32 +( + const void *Buffer, + grub_uint32_t Length, + grub_uint32_t InitValue +); + +static inline int hiperiso_isspace (int c) +{ + return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); +} + +static inline int hiperiso_is_word_end(int c) +{ + return (c == 0 || c == ',' || hiperiso_isspace(c)); +} + +#pragma pack(1) +typedef struct hiperiso_part_table +{ + grub_uint8_t Active; // 0x00 0x80 + + grub_uint8_t StartHead; + grub_uint16_t StartSector : 6; + grub_uint16_t StartCylinder : 10; + + grub_uint8_t FsFlag; + + grub_uint8_t EndHead; + grub_uint16_t EndSector : 6; + grub_uint16_t EndCylinder : 10; + + grub_uint32_t StartSectorId; + grub_uint32_t SectorCount; +}hiperiso_part_table; + +typedef struct hiperiso_mbr_head +{ + grub_uint8_t BootCode[446]; + hiperiso_part_table PartTbl[4]; + grub_uint8_t Byte55; + grub_uint8_t ByteAA; +}hiperiso_mbr_head; + +typedef struct hiperiso_gpt_head +{ + char Signature[8]; /* EFI PART */ + grub_uint8_t Version[4]; + grub_uint32_t Length; + grub_uint32_t Crc; + grub_uint8_t Reserved1[4]; + grub_uint64_t EfiStartLBA; + grub_uint64_t EfiBackupLBA; + grub_uint64_t PartAreaStartLBA; + grub_uint64_t PartAreaEndLBA; + grub_uint8_t DiskGuid[16]; + grub_uint64_t PartTblStartLBA; + grub_uint32_t PartTblTotNum; + grub_uint32_t PartTblEntryLen; + grub_uint32_t PartTblCrc; + grub_uint8_t Reserved2[420]; +}hiperiso_gpt_head; + +typedef struct hiperiso_gpt_part_tbl +{ + grub_uint8_t PartType[16]; + grub_uint8_t PartGuid[16]; + grub_uint64_t StartLBA; + grub_uint64_t LastLBA; + grub_uint64_t Attr; + grub_uint16_t Name[36]; +}hiperiso_gpt_part_tbl; + +typedef struct hiperiso_gpt_info +{ + hiperiso_mbr_head MBR; + hiperiso_gpt_head Head; + hiperiso_gpt_part_tbl PartTbl[128]; +}hiperiso_gpt_info; + +typedef struct vhd_footer_t +{ + char cookie[8]; // Cookie + grub_uint32_t features; // Features + grub_uint32_t ffversion; // File format version + grub_uint32_t dataoffset; // Data offset + grub_uint32_t timestamp; // Timestamp + grub_uint32_t creatorapp; // Creator application + grub_uint32_t creatorver; // Creator version + grub_uint32_t creatorhos; // Creator host OS + grub_uint32_t origsize; // Original size + grub_uint32_t currsize; // Current size + grub_uint32_t diskgeom; // Disk geometry + grub_uint32_t disktype; // Disk type + grub_uint32_t checksum; // Checksum + grub_uint8_t uniqueid[16]; // Unique ID + grub_uint8_t savedst; // Saved state +}vhd_footer_t; + +#define VDI_IMAGE_FILE_INFO "<<< Oracle VM VirtualBox Disk Image >>>\n" +#define VDI_IMAGE_FILE_INFO2 "<<< Oracle VirtualBox Disk Image >>>\n" + +/** Image signature. */ +#define VDI_IMAGE_SIGNATURE (0xbeda107f) + +typedef struct VDIPREHEADER +{ + /** Just text info about image type, for eyes only. */ + char szFileInfo[64]; + /** The image signature (VDI_IMAGE_SIGNATURE). */ + grub_uint32_t u32Signature; + /** The image version (VDI_IMAGE_VERSION). */ + grub_uint32_t u32Version; +} VDIPREHEADER, *PVDIPREHEADER; + +#pragma pack() + +typedef struct hiperiso_video_mode +{ + grub_uint32_t width; + grub_uint32_t height; + grub_uint32_t bpp; +}hiperiso_video_mode; + + + +typedef struct file_fullpath +{ + char path[256]; + int vlnk_add; +}file_fullpath; + +typedef struct theme_list +{ + file_fullpath theme; + struct theme_list *next; +}theme_list; + +#define auto_install_type_file 0 +#define auto_install_type_parent 1 +typedef struct install_template +{ + int type; + int pathlen; + char isopath[256]; + + int timeout; + int autosel; + int cursel; + int templatenum; + file_fullpath *templatepath; + + char *filebuf; + int filelen; + + struct install_template *next; +}install_template; + +typedef struct dudfile +{ + int size; + char *buf; +}dudfile; + +typedef struct dud +{ + int pathlen; + char isopath[256]; + + int dudnum; + file_fullpath *dudpath; + dudfile *files; + + struct dud *next; +}dud; + +typedef struct persistence_config +{ + int pathlen; + char isopath[256]; + + int timeout; + int autosel; + int cursel; + int backendnum; + file_fullpath *backendpath; + + struct persistence_config *next; +}persistence_config; + +#define hiso_alias_image_file 0 +#define hiso_alias_directory 1 + +typedef struct menu_alias +{ + int type; + int pathlen; + char isopath[256]; + char alias[256]; + + struct menu_alias *next; +}menu_alias; + +#define hiso_tip_image_file 0 +#define hiso_tip_directory 1 +typedef struct menu_tip +{ + int type; + int pathlen; + char isopath[256]; + char tip1[1024]; + char tip2[1024]; + + struct menu_tip *next; +}menu_tip; + + +#define hiso_class_image_file 0 +#define hiso_class_directory 1 + +typedef struct menu_class +{ + int type; + int patlen; + int parent; + char pattern[256]; + char class[64]; + + struct menu_class *next; +}menu_class; + +#define hiso_custom_boot_image_file 0 +#define hiso_custom_boot_directory 1 + +typedef struct custom_boot +{ + int type; + int pathlen; + char path[256]; + char cfg[256]; + + struct custom_boot *next; +}custom_boot; + +#define hiso_max_replace_file_size (1024 * 1024) +typedef struct conf_replace +{ + int pathlen; + int img; + char isopath[256]; + char orgconf[256]; + char newconf[256]; + + struct conf_replace *next; +}conf_replace; + +#define injection_type_file 0 +#define injection_type_parent 1 +typedef struct injection_config +{ + int type; + int pathlen; + char isopath[256]; + char archive[256]; + + struct injection_config *next; +}injection_config; + +typedef struct auto_memdisk +{ + int pathlen; + char isopath[256]; + + struct auto_memdisk *next; +}auto_memdisk; + +typedef struct image_list +{ + int pathlen; + char isopath[256]; + + struct image_list *next; +}image_list; + +#define HISO_PASSWORD_NONE 0 +#define HISO_PASSWORD_TXT 1 +#define HISO_PASSWORD_MD5 2 +#define HISO_PASSWORD_SALT_MD5 3 + +typedef struct hiso_password +{ + int type; + char text[128]; + char salt[64]; + grub_uint8_t md5[16]; +}hiso_password; + +#define hiso_menu_pwd_file 0 +#define hiso_menu_pwd_parent 1 + +typedef struct menu_password +{ + int type; + int pathlen; + char isopath[256]; + + hiso_password password; + + struct menu_password *next; +}menu_password; + +extern int g_hiperiso_menu_esc; +extern int g_hiperiso_secondary_menu_on; +extern int g_hiperiso_suppress_esc; +extern int g_hiperiso_suppress_esc_default; +extern int g_hiperiso_last_entry; +extern int g_hiperiso_memdisk_mode; +extern int g_hiperiso_iso_raw; +extern int g_hiperiso_grub2_mode; +extern int g_hiperiso_wimboot_mode; +extern int g_hiperiso_iso_uefi_drv; +extern int g_hiperiso_case_insensitive; +extern int g_hiperiso_fn_mutex; +extern grub_uint8_t g_hiperiso_chain_type; +extern int g_vhdboot_enable; +extern int g_default_menu_mode; +extern char g_hiperiso_hotkey_tip[256]; +extern int g_hiperiso_menu_refresh; + +#define HIPERISO_IMG_WHITE_LIST 1 +#define HIPERISO_IMG_BLACK_LIST 2 +extern int g_plugin_image_list; + +extern hiperiso_gpt_info *g_hiperiso_part_info; +extern int g_conf_replace_count; +extern grub_uint64_t g_conf_replace_offset[HISO_MAX_CONF_REPLACE]; +extern grub_uint64_t g_svd_replace_offset; +extern conf_replace *g_conf_replace_node[HISO_MAX_CONF_REPLACE]; +extern grub_uint8_t *g_conf_replace_new_buf[HISO_MAX_CONF_REPLACE]; +extern int g_conf_replace_new_len[HISO_MAX_CONF_REPLACE]; +extern int g_conf_replace_new_len_align[HISO_MAX_CONF_REPLACE]; +extern int g_hiperiso_disk_bios_id; +extern grub_uint64_t g_hiperiso_disk_size; +extern grub_uint64_t g_hiperiso_disk_part_size[2]; +extern grub_uint32_t g_hiperiso_plat_data; + +#define hiperiso_unix_fill_virt(new_data, new_len) \ +{ \ + data_secs = (new_len + 2047) / 2048; \ + cur->mem_sector_start = sector; \ + cur->mem_sector_end = cur->mem_sector_start + data_secs; \ + cur->mem_sector_offset = offset; \ + cur->remap_sector_start = 0; \ + cur->remap_sector_end = 0; \ + cur->org_sector_start = 0; \ + grub_memcpy(override + offset, new_data, new_len); \ + cur++; \ + sector += data_secs; \ + offset += new_len; \ + chain->virt_img_size_in_bytes += data_secs * 2048; \ +} + +#define hiperiso_syscall0(name) grub_##name() +#define hiperiso_syscall1(name, a) grub_##name(a) + +void hiperiso_str_tolower(char *str); +void hiperiso_str_toupper(char *str); +char * hiperiso_get_line(char *start); +char *hiperiso_str_last(char *str, char ch); +int hiperiso_cmp_img(img_info *img1, img_info *img2); +void hiperiso_swap_img(img_info *img1, img_info *img2); +char * hiperiso_plugin_get_cur_install_template(const char *isopath, install_template **cur); +install_template * hiperiso_plugin_find_install_template(const char *isopath); +persistence_config * hiperiso_plugin_find_persistent(const char *isopath); +grub_uint64_t hiperiso_get_hiso_partsize(int part); +void hiperiso_plugin_dump_injection(void); +void hiperiso_plugin_dump_auto_install(void); +int hiperiso_plugin_get_persistent_chunklist(const char *isopath, int index, hiperiso_img_chunk_list *chunk_list); +const char * hiperiso_plugin_get_injection(const char *isopath); +const char * hiperiso_plugin_get_menu_alias(int type, const char *isopath); +const menu_tip * hiperiso_plugin_get_menu_tip(int type, const char *isopath); +const char * hiperiso_plugin_get_menu_class(int type, const char *name, const char *path); +int hiperiso_plugin_check_memdisk(const char *isopath); +int hiperiso_plugin_get_image_list_index(int type, const char *name); +int hiperiso_plugin_find_conf_replace(const char *iso, conf_replace *nodes[HISO_MAX_CONF_REPLACE]); +dud * hiperiso_plugin_find_dud(const char *iso); +int hiperiso_plugin_load_dud(dud *node, const char *isopart); +int hiperiso_get_block_list(grub_file_t file, hiperiso_img_chunk_list *chunklist, grub_disk_addr_t start); +int hiperiso_check_block_list(grub_file_t file, hiperiso_img_chunk_list *chunklist, grub_disk_addr_t start, char *err, grub_uint32_t len); +void hiperiso_plugin_dump_persistence(void); +grub_err_t hiperiso_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_sel_winpe_wim(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature); +grub_err_t hiperiso_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_check_vlnk(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_replace_grub_conf(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_check_device_result(int ret); +int hiperiso_check_device(grub_device_t dev); +void hiperiso_debug_dump_guid(const char *prefix, grub_uint8_t *guid); +grub_err_t hiperiso_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_get_hiso_type(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_check_password(const hiso_password *pwd, int retry); +int hiperiso_plugin_add_custom_boot(const char *vcfgpath); +const char * hiperiso_plugin_get_custom_boot(const char *isopath); +grub_err_t hiperiso_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len); +int hiperiso_load_part_table(const char *diskname); +int hiperiso_env_init(void); +int hiperiso_register_all_cmd(void); +int hiperiso_unregister_all_cmd(void); +int hiperiso_chain_file_size(const char *path); +int hiperiso_chain_file_read(const char *path, int offset, int len, void *buf); + +#define HISO_CMD_CHECK(a) if (33554432 != g_hiperiso_disk_part_size[a]) hiperiso_syscall0(exit) + +#define hiso_theme_random_boot_second 0 +#define hiso_theme_random_boot_day 1 +#define hiso_theme_random_boot_month 2 + +#define hiperiso_env_export(env, name) \ +{\ + grub_env_set((env), (name));\ + grub_env_export(env);\ +} + +#define ret_goto_end(a) ret = a; goto end; + +extern hiperiso_grub_param *g_grub_param; + +#pragma pack(1) +#define HIPERISO_UNIX_SEG_MAGIC0 0x11223344 +#define HIPERISO_UNIX_SEG_MAGIC1 0x55667788 +#define HIPERISO_UNIX_SEG_MAGIC2 0x99aabbcc +#define HIPERISO_UNIX_SEG_MAGIC3 0xddeeff00 +#define HIPERISO_UNIX_MAX_SEGNUM 40960 +struct g_hiperiso_seg { + grub_uint64_t seg_start_bytes; + grub_uint64_t seg_end_bytes; +}; + +struct g_hiperiso_map{ + grub_uint32_t magic1[4]; + grub_uint32_t magic2[4]; + grub_uint64_t segnum; + grub_uint64_t disksize; + grub_uint8_t diskuuid[16]; + struct g_hiperiso_seg seglist[HIPERISO_UNIX_MAX_SEGNUM]; + grub_uint32_t magic3[4]; +}; +#pragma pack() + +typedef struct hiperiso_vlnk_part +{ + grub_uint32_t disksig; + grub_uint64_t partoffset; + char disk[64]; + char device[64]; + grub_device_t dev; + grub_fs_t fs; + int probe; + struct hiperiso_vlnk_part *next; +}hiperiso_vlnk_part; + + +typedef struct browser_mbuf +{ + int max; + int pos; + char *buf; +}browser_mbuf; + +typedef struct browser_node +{ + int dir; + char menuentry[1024]; + char filename[512]; + struct browser_node *prev; + struct browser_node *next; +}browser_node; + +typedef struct var_node +{ + char var[128]; + char val[256]; + + struct var_node *next; +}var_node; + +typedef struct systemd_menu_ctx +{ + char *dev; + char *buf; + const char *initrd_cmd; + int pos; + int len; +}systemd_menu_ctx; + +typedef struct global_var_cfg +{ + const char *name; + const char *defval; + char *value; +}global_var_cfg; + +typedef struct ctrl_var_cfg +{ + const char *name; + char szval[2]; +}ctrl_var_cfg; + +#define hiso_check_goto_out(p) if (!p) goto out + +extern char *g_tree_script_buf; +extern int g_tree_script_pos; +extern int g_tree_script_pre; +extern int g_tree_view_menu_style; +extern int g_sort_case_sensitive; +extern int g_wimboot_enable; +extern int g_filt_dot_underscore_file; +extern int g_filt_trash_dir; +extern int g_hiso_file_flt[HISO_FILE_FLT_BUTT]; +extern const char *g_menu_class[img_type_max]; +extern char g_iso_path[256]; +int hiperiso_add_vlnk_file(char *dir, const char *name); +grub_err_t hiperiso_cmd_browser_dir(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_browser_disk(grub_extcmd_context_t ctxt, int argc, char **args); +int hiperiso_get_fs_type(const char *fs); +int hiperiso_img_name_valid(const char *filename, grub_size_t namelen); +void * hiperiso_alloc_chain(grub_size_t size); +int hiperiso_plugin_load_menu_lang(int init, const char *lang); +const char *hiperiso_get_vmenu_title(const char *vMenu); +grub_err_t hiperiso_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args); +extern int hiperiso_menu_push_key(int code); +int hiperiso_ctrl_var_init(void); +int hiperiso_global_var_init(void); +grub_err_t hiperiso_cmd_push_menulang(grub_extcmd_context_t ctxt, int argc, char **args); +grub_err_t hiperiso_cmd_pop_menulang(grub_extcmd_context_t ctxt, int argc, char **args); +void hiperiso_prompt_end(void); +int hiperiso_set_sb_policy(void); + +#endif /* __HIPERISO_DEF_H__ */ + diff --git a/src/grub2/hiperiso_json.c b/src/grub2/hiperiso_json.c new file mode 100644 index 0000000..04771d2 --- /dev/null +++ b/src/grub2/hiperiso_json.c @@ -0,0 +1,758 @@ +/****************************************************************************** + * hiperiso_json.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +static void json_debug(const char *fmt, ...) +{ + va_list args; + + if (g_hiperiso_debug == 0) + { + return; + } + + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + + grub_printf("\n"); +} + +static void hiso_json_free(HISO_JSON *pstJsonHead) +{ + HISO_JSON *pstNext = NULL; + + while (NULL != pstJsonHead) + { + pstNext = pstJsonHead->pstNext; + if ((pstJsonHead->enDataType < JSON_TYPE_BUTT) && (NULL != pstJsonHead->pstChild)) + { + hiso_json_free(pstJsonHead->pstChild); + } + + grub_free(pstJsonHead); + pstJsonHead = pstNext; + } + + return; +} + +static char *hiso_json_skip(const char *pcData) +{ + while ((NULL != pcData) && ('\0' != *pcData) && (*pcData <= 32)) + { + pcData++; + } + + return (char *)pcData; +} + +HISO_JSON *hiso_json_find_item +( + HISO_JSON *pstJson, + JSON_TYPE enDataType, + const char *szKey +) +{ + while (NULL != pstJson) + { + if ((enDataType == pstJson->enDataType) && + (0 == grub_strcmp(szKey, pstJson->pcName))) + { + return pstJson; + } + pstJson = pstJson->pstNext; + } + + return NULL; +} + +static int hiso_json_parse_number +( + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +) +{ + unsigned long Value; + + Value = grub_strtoul(pcData, (char **)ppcEnd, 10); + if (*ppcEnd == pcData) + { + json_debug("Failed to parse json number %s.", pcData); + return JSON_FAILED; + } + + pstJson->enDataType = JSON_TYPE_NUMBER; + pstJson->unData.lValue = Value; + + return JSON_SUCCESS; +} + +static int hiso_json_parse_string +( + char *pcNewStart, + char *pcRawStart, + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +) +{ + grub_uint32_t uiLen = 0; + const char *pcPos = NULL; + const char *pcTmp = pcData + 1; + + *ppcEnd = pcData; + + if ('\"' != *pcData) + { + return JSON_FAILED; + } + + pcPos = grub_strchr(pcTmp, '\"'); + if ((NULL == pcPos) || (pcPos < pcTmp)) + { + json_debug("Invalid string %s.", pcData); + return JSON_FAILED; + } + + if (*(pcPos - 1) == '\\') + { + for (pcPos++; *pcPos; pcPos++) + { + if (*pcPos == '"' && *(pcPos - 1) != '\\') + { + break; + } + } + + if (*pcPos == 0 || pcPos < pcTmp) + { + json_debug("Invalid quotes string %s.", pcData); + return JSON_FAILED; + } + } + + *ppcEnd = pcPos + 1; + uiLen = (grub_uint32_t)(unsigned long)(pcPos - pcTmp); + + pstJson->enDataType = JSON_TYPE_STRING; + pstJson->unData.pcStrVal = pcNewStart + (pcTmp - pcRawStart); + pstJson->unData.pcStrVal[uiLen] = '\0'; + + return JSON_SUCCESS; +} + +static int hiso_json_parse_array +( + char *pcNewStart, + char *pcRawStart, + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +) +{ + int Ret = JSON_SUCCESS; + HISO_JSON *pstJsonChild = NULL; + HISO_JSON *pstJsonItem = NULL; + const char *pcTmp = pcData + 1; + + *ppcEnd = pcData; + pstJson->enDataType = JSON_TYPE_ARRAY; + + if ('[' != *pcData) + { + return JSON_FAILED; + } + + pcTmp = hiso_json_skip(pcTmp); + + if (']' == *pcTmp) + { + *ppcEnd = pcTmp + 1; + return JSON_SUCCESS; + } + + JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED); + + Ret = hiso_json_parse_value(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + + pstJsonChild = pstJson->pstChild; + pcTmp = hiso_json_skip(*ppcEnd); + while ((NULL != pcTmp) && (',' == *pcTmp)) + { + JSON_NEW_ITEM(pstJsonItem, JSON_FAILED); + pstJsonChild->pstNext = pstJsonItem; + pstJsonItem->pstPrev = pstJsonChild; + pstJsonChild = pstJsonItem; + + Ret = hiso_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, hiso_json_skip(pcTmp + 1), ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + pcTmp = hiso_json_skip(*ppcEnd); + } + + if ((NULL != pcTmp) && (']' == *pcTmp)) + { + *ppcEnd = pcTmp + 1; + return JSON_SUCCESS; + } + else + { + *ppcEnd = pcTmp; + return JSON_FAILED; + } +} + +static int hiso_json_parse_object +( + char *pcNewStart, + char *pcRawStart, + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +) +{ + int Ret = JSON_SUCCESS; + HISO_JSON *pstJsonChild = NULL; + HISO_JSON *pstJsonItem = NULL; + const char *pcTmp = pcData + 1; + + *ppcEnd = pcData; + pstJson->enDataType = JSON_TYPE_OBJECT; + + if ('{' != *pcData) + { + return JSON_FAILED; + } + + pcTmp = hiso_json_skip(pcTmp); + if ('}' == *pcTmp) + { + *ppcEnd = pcTmp + 1; + return JSON_SUCCESS; + } + + JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED); + + Ret = hiso_json_parse_string(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + + pstJsonChild = pstJson->pstChild; + pstJsonChild->pcName = pstJsonChild->unData.pcStrVal; + pstJsonChild->unData.pcStrVal = NULL; + + pcTmp = hiso_json_skip(*ppcEnd); + if ((NULL == pcTmp) || (':' != *pcTmp)) + { + *ppcEnd = pcTmp; + return JSON_FAILED; + } + + Ret = hiso_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, hiso_json_skip(pcTmp + 1), ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + + pcTmp = hiso_json_skip(*ppcEnd); + while ((NULL != pcTmp) && (',' == *pcTmp)) + { + JSON_NEW_ITEM(pstJsonItem, JSON_FAILED); + pstJsonChild->pstNext = pstJsonItem; + pstJsonItem->pstPrev = pstJsonChild; + pstJsonChild = pstJsonItem; + + Ret = hiso_json_parse_string(pcNewStart, pcRawStart, pstJsonChild, hiso_json_skip(pcTmp + 1), ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + + pcTmp = hiso_json_skip(*ppcEnd); + pstJsonChild->pcName = pstJsonChild->unData.pcStrVal; + pstJsonChild->unData.pcStrVal = NULL; + if ((NULL == pcTmp) || (':' != *pcTmp)) + { + *ppcEnd = pcTmp; + return JSON_FAILED; + } + + Ret = hiso_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, hiso_json_skip(pcTmp + 1), ppcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse array child."); + return JSON_FAILED; + } + + pcTmp = hiso_json_skip(*ppcEnd); + } + + if ((NULL != pcTmp) && ('}' == *pcTmp)) + { + *ppcEnd = pcTmp + 1; + return JSON_SUCCESS; + } + else + { + *ppcEnd = pcTmp; + return JSON_FAILED; + } +} + +int hiso_json_parse_value +( + char *pcNewStart, + char *pcRawStart, + HISO_JSON *pstJson, + const char *pcData, + const char **ppcEnd +) +{ + pcData = hiso_json_skip(pcData); + + switch (*pcData) + { + case 'n': + { + if (0 == grub_strncmp(pcData, "null", 4)) + { + pstJson->enDataType = JSON_TYPE_NULL; + *ppcEnd = pcData + 4; + return JSON_SUCCESS; + } + break; + } + case 'f': + { + if (0 == grub_strncmp(pcData, "false", 5)) + { + pstJson->enDataType = JSON_TYPE_BOOL; + pstJson->unData.lValue = 0; + *ppcEnd = pcData + 5; + return JSON_SUCCESS; + } + break; + } + case 't': + { + if (0 == grub_strncmp(pcData, "true", 4)) + { + pstJson->enDataType = JSON_TYPE_BOOL; + pstJson->unData.lValue = 1; + *ppcEnd = pcData + 4; + return JSON_SUCCESS; + } + break; + } + case '\"': + { + return hiso_json_parse_string(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd); + } + case '[': + { + return hiso_json_parse_array(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd); + } + case '{': + { + return hiso_json_parse_object(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd); + } + case '-': + { + return hiso_json_parse_number(pstJson, pcData, ppcEnd); + } + default : + { + if (*pcData >= '0' && *pcData <= '9') + { + return hiso_json_parse_number(pstJson, pcData, ppcEnd); + } + } + } + + *ppcEnd = pcData; + json_debug("Invalid json data %u.", (grub_uint8_t)(*pcData)); + return JSON_FAILED; +} + +HISO_JSON * hiso_json_create(void) +{ + HISO_JSON *pstJson = NULL; + + pstJson = (HISO_JSON *)grub_zalloc(sizeof(HISO_JSON)); + if (NULL == pstJson) + { + return NULL; + } + + return pstJson; +} + +int hiso_json_parse(HISO_JSON *pstJson, const char *szJsonData) +{ + grub_uint32_t uiMemSize = 0; + int Ret = JSON_SUCCESS; + char *pcNewBuf = NULL; + const char *pcEnd = NULL; + + uiMemSize = grub_strlen(szJsonData) + 1; + pcNewBuf = (char *)grub_malloc(uiMemSize); + if (NULL == pcNewBuf) + { + json_debug("Failed to alloc new buf."); + return JSON_FAILED; + } + grub_memcpy(pcNewBuf, szJsonData, uiMemSize); + pcNewBuf[uiMemSize - 1] = 0; + + Ret = hiso_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd); + if (JSON_SUCCESS != Ret) + { + json_debug("Failed to parse json data %s start=%p, end=%p:%s.", + szJsonData, szJsonData, pcEnd, pcEnd); + return JSON_FAILED; + } + + return JSON_SUCCESS; +} + +int hiso_json_scan_parse +( + const HISO_JSON *pstJson, + grub_uint32_t uiParseNum, + JSON_PARSE *pstJsonParse +) +{ + grub_uint32_t i = 0; + const HISO_JSON *pstJsonCur = NULL; + JSON_PARSE *pstCurParse = NULL; + + for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext) + { + if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) || + (JSON_TYPE_ARRAY == pstJsonCur->enDataType)) + { + continue; + } + + for (i = 0, pstCurParse = NULL; i < uiParseNum; i++) + { + if (0 == grub_strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName)) + { + pstCurParse = pstJsonParse + i; + break; + } + } + + if (NULL == pstCurParse) + { + continue; + } + + switch (pstJsonCur->enDataType) + { + case JSON_TYPE_NUMBER: + { + if (sizeof(grub_uint32_t) == pstCurParse->uiBufSize) + { + *(grub_uint32_t *)(pstCurParse->pDataBuf) = (grub_uint32_t)pstJsonCur->unData.lValue; + } + else if (sizeof(grub_uint16_t) == pstCurParse->uiBufSize) + { + *(grub_uint16_t *)(pstCurParse->pDataBuf) = (grub_uint16_t)pstJsonCur->unData.lValue; + } + else if (sizeof(grub_uint8_t) == pstCurParse->uiBufSize) + { + *(grub_uint8_t *)(pstCurParse->pDataBuf) = (grub_uint8_t)pstJsonCur->unData.lValue; + } + else if ((pstCurParse->uiBufSize > sizeof(grub_uint64_t))) + { + grub_snprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu", + (unsigned long long)(pstJsonCur->unData.lValue)); + } + else + { + json_debug("Invalid number data buf size %u.", pstCurParse->uiBufSize); + } + break; + } + case JSON_TYPE_STRING: + { + grub_strncpy((char *)pstCurParse->pDataBuf, pstJsonCur->unData.pcStrVal, pstCurParse->uiBufSize); + break; + } + case JSON_TYPE_BOOL: + { + *(grub_uint8_t *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0; + break; + } + default : + { + break; + } + } + } + + return JSON_SUCCESS; +} + +int hiso_json_scan_array +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstArrayItem +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *ppstArrayItem = pstJsonItem; + + return JSON_SUCCESS; +} + +int hiso_json_scan_array_ex +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstArrayItem +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *ppstArrayItem = pstJsonItem->pstChild; + + return JSON_SUCCESS; +} + +int hiso_json_scan_object +( + HISO_JSON *pstJson, + const char *szKey, + HISO_JSON **ppstObjectItem +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *ppstObjectItem = pstJsonItem; + + return JSON_SUCCESS; +} + +int hiso_json_get_int +( + HISO_JSON *pstJson, + const char *szKey, + int *piValue +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *piValue = (int)pstJsonItem->unData.lValue; + + return JSON_SUCCESS; +} + +int hiso_json_get_uint +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint32_t *puiValue +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *puiValue = (grub_uint32_t)pstJsonItem->unData.lValue; + + return JSON_SUCCESS; +} + +int hiso_json_get_uint64 +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint64_t *pui64Value +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *pui64Value = (grub_uint64_t)pstJsonItem->unData.lValue; + + return JSON_SUCCESS; +} + +int hiso_json_get_bool +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint8_t *pbValue +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_BOOL, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + *pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0; + + return JSON_SUCCESS; +} + +int hiso_json_get_string +( + HISO_JSON *pstJson, + const char *szKey, + grub_uint32_t uiBufLen, + char *pcBuf +) +{ + HISO_JSON *pstJsonItem = NULL; + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_STRING, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return JSON_NOT_FOUND; + } + + grub_strncpy(pcBuf, pstJsonItem->unData.pcStrVal, uiBufLen); + + return JSON_SUCCESS; +} + +const char * hiso_json_get_string_ex(HISO_JSON *pstJson, const char *szKey) +{ + HISO_JSON *pstJsonItem = NULL; + + if ((NULL == pstJson) || (NULL == szKey)) + { + return NULL; + } + + pstJsonItem = hiso_json_find_item(pstJson, JSON_TYPE_STRING, szKey); + if (NULL == pstJsonItem) + { + json_debug("Key %s is not found in json data.", szKey); + return NULL; + } + + return pstJsonItem->unData.pcStrVal; +} + +int hiso_json_destroy(HISO_JSON *pstJson) +{ + if (NULL == pstJson) + { + return JSON_SUCCESS; + } + + if (NULL != pstJson->pstChild) + { + hiso_json_free(pstJson->pstChild); + } + + if (NULL != pstJson->pstNext) + { + hiso_json_free(pstJson->pstNext); + } + + grub_free(pstJson); + + return JSON_SUCCESS; +} + diff --git a/src/grub2/hiperiso_linux.c b/src/grub2/hiperiso_linux.c new file mode 100644 index 0000000..bf55ff4 --- /dev/null +++ b/src/grub2/hiperiso_linux.c @@ -0,0 +1,2120 @@ +/****************************************************************************** + * hiperiso_linux.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define HISO_APPEND_EXT_SIZE 4096 +static int g_append_ext_sector = 0; + +char * hiperiso_get_line(char *start) +{ + if (start == NULL) + { + return NULL; + } + + while (*start && *start != '\n') + { + start++; + } + + if (*start == 0) + { + return NULL; + } + else + { + *start = 0; + return start + 1; + } +} + +static initrd_info * hiperiso_find_initrd_by_name(initrd_info *list, const char *name) +{ + initrd_info *node = list; + + while (node) + { + if (grub_strcmp(node->name, name) == 0) + { + return node; + } + node = node->next; + } + + return NULL; +} + +grub_err_t hiperiso_cmd_clear_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args) +{ + initrd_info *node = g_initrd_img_list; + initrd_info *next; + + (void)ctxt; + (void)argc; + (void)args; + + while (node) + { + next = node->next; + grub_free(node); + node = next; + } + + g_initrd_img_list = NULL; + g_initrd_img_tail = NULL; + g_initrd_img_count = 0; + g_valid_initrd_count = 0; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_dump_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + initrd_info *node = g_initrd_img_list; + + (void)ctxt; + (void)argc; + (void)args; + + grub_printf("###################\n"); + grub_printf("initrd info list: valid count:%d\n", g_valid_initrd_count); + + while (node) + { + grub_printf("%s ", node->size > 0 ? "*" : " "); + grub_printf("%02u %s offset:%llu size:%llu \n", i++, node->name, (unsigned long long)node->offset, + (unsigned long long)node->size); + node = node->next; + } + + grub_printf("###################\n"); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static void hiperiso_parse_directory(char *path, char *dir, int buflen) +{ + int end; + char *pos; + + pos = grub_strstr(path, ")"); + if (!pos) + { + pos = path; + } + + end = grub_snprintf(dir, buflen, "%s", pos + 1); + while (end > 0) + { + if (dir[end] == '/') + { + dir[end + 1] = 0; + break; + } + end--; + } +} + +static grub_err_t hiperiso_isolinux_initrd_collect(grub_file_t file, const char *prefix) +{ + int i = 0; + int offset; + int prefixlen = 0; + char *buf = NULL; + char *pos = NULL; + char *start = NULL; + char *nextline = NULL; + initrd_info *img = NULL; + + prefixlen = grub_strlen(prefix); + + buf = grub_zalloc(file->size + 2); + if (!buf) + { + return 0; + } + + grub_file_read(file, buf, file->size); + + for (start = buf; start; start = nextline) + { + nextline = hiperiso_get_line(start); + + HISO_SKIP_SPACE(start); + + offset = 7; // strlen("initrd=") or "INITRD " or "initrd " + pos = grub_strstr(start, "initrd="); + if (pos == NULL) + { + pos = start; + + if (grub_strncmp(start, "INITRD", 6) != 0 && grub_strncmp(start, "initrd", 6) != 0) + { + if (grub_strstr(start, "xen") && + ((pos = grub_strstr(start, "--- /install.img")) != NULL || + (pos = grub_strstr(start, "--- initrd.img")) != NULL + )) + { + offset = 4; // "--- " + } + else + { + continue; + } + } + } + + pos += offset; + + while (1) + { + i = 0; + img = grub_zalloc(sizeof(initrd_info)); + if (!img) + { + break; + } + + if (*pos != '/') + { + grub_strcpy(img->name, prefix); + i = prefixlen; + } + + while (i < 255 && (0 == hiperiso_is_word_end(*pos))) + { + img->name[i++] = *pos++; + } + + if (hiperiso_find_initrd_by_name(g_initrd_img_list, img->name)) + { + grub_free(img); + } + else + { + if (g_initrd_img_list) + { + img->prev = g_initrd_img_tail; + g_initrd_img_tail->next = img; + } + else + { + g_initrd_img_list = img; + } + + g_initrd_img_tail = img; + g_initrd_img_count++; + } + + if (*pos == ',') + { + pos++; + } + else + { + break; + } + } + } + + grub_free(buf); + return GRUB_ERR_NONE; +} + +static int hiperiso_isolinux_initrd_hook(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + grub_file_t file = NULL; + hiperiso_initrd_ctx *ctx = (hiperiso_initrd_ctx *)data; + + (void)info; + + if (NULL == grub_strstr(filename, ".cfg") && NULL == grub_strstr(filename, ".CFG")) + { + return 0; + } + + debug("init hook dir <%s%s>\n", ctx->path_prefix, filename); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", ctx->path_prefix, filename); + if (!file) + { + return 0; + } + + hiperiso_isolinux_initrd_collect(file, ctx->dir_prefix); + grub_file_close(file); + + return 0; +} + +grub_err_t hiperiso_cmd_isolinux_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_fs_t fs; + grub_device_t dev = NULL; + char *device_name = NULL; + hiperiso_initrd_ctx ctx; + char directory[256]; + + (void)ctxt; + (void)argc; + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + goto end; + } + + debug("isolinux initrd collect %s\n", args[0]); + + hiperiso_parse_directory(args[0], directory, sizeof(directory) - 1); + ctx.path_prefix = args[0]; + ctx.dir_prefix = (argc > 1) ? args[1] : directory; + + debug("path_prefix=<%s> dir_prefix=<%s>\n", ctx.path_prefix, ctx.dir_prefix); + + fs->fs_dir(dev, directory, hiperiso_isolinux_initrd_hook, &ctx); + +end: + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_linux_initrd_collect_hook(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + int len; + initrd_info *img = NULL; + + (void)data; + + if (0 == info->dir) + { + if (grub_strncmp(filename, "initrd", 6) == 0) + { + len = (int)grub_strlen(filename); + if (grub_strcmp(filename + len - 4, ".img") == 0) + { + img = grub_zalloc(sizeof(initrd_info)); + if (img) + { + grub_snprintf(img->name, sizeof(img->name), "/boot/%s", filename); + + if (hiperiso_find_initrd_by_name(g_initrd_img_list, img->name)) + { + grub_free(img); + } + else + { + if (g_initrd_img_list) + { + img->prev = g_initrd_img_tail; + g_initrd_img_tail->next = img; + } + else + { + g_initrd_img_list = img; + } + + g_initrd_img_tail = img; + g_initrd_img_count++; + } + } + } + } + } + + return 0; +} + +static int hiperiso_linux_collect_boot_initrds(void) +{ + grub_fs_t fs; + grub_device_t dev = NULL; + + dev = grub_device_open("loop"); + if (!dev) + { + debug("failed to open device loop\n"); + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + debug("failed to probe fs %d\n", grub_errno); + goto end; + } + + fs->fs_dir(dev, "/boot", hiperiso_linux_initrd_collect_hook, NULL); + +end: + return 0; +} + +static grub_err_t hiperiso_grub_cfg_initrd_collect(const char *fileName) +{ + int i = 0; + int len = 0; + int dollar = 0; + int quotation = 0; + int initrd_dollar = 0; + grub_file_t file = NULL; + char *buf = NULL; + char *start = NULL; + char *nextline = NULL; + initrd_info *img = NULL; + + debug("grub initrd collect %s\n", fileName); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", fileName); + if (!file) + { + return 0; + } + + buf = grub_zalloc(file->size + 2); + if (!buf) + { + grub_file_close(file); + return 0; + } + + grub_file_read(file, buf, file->size); + + for (start = buf; start; start = nextline) + { + nextline = hiperiso_get_line(start); + + HISO_SKIP_SPACE(start); + + if (grub_strncmp(start, "initrd", 6) != 0) + { + continue; + } + + start += 6; + while (*start && (!hiperiso_isspace(*start))) + { + start++; + } + + HISO_SKIP_SPACE(start); + + if (*start == '"') + { + quotation = 1; + start++; + } + + while (*start) + { + img = grub_zalloc(sizeof(initrd_info)); + if (!img) + { + break; + } + + dollar = 0; + for (i = 0; i < 255 && (0 == hiperiso_is_word_end(*start)); i++) + { + img->name[i] = *start++; + if (img->name[i] == '$') + { + dollar = 1; + } + } + + if (quotation) + { + len = (int)grub_strlen(img->name); + if (len > 2 && img->name[len - 1] == '"') + { + img->name[len - 1] = 0; + } + debug("Remove quotation <%s>\n", img->name); + } + + /* special process for /boot/initrd$XXX.img */ + if (dollar == 1) + { + if (grub_strncmp(img->name, "/boot/initrd$", 13) == 0) + { + len = (int)grub_strlen(img->name); + if (grub_strcmp(img->name + len - 4, ".img") == 0) + { + initrd_dollar++; + } + } + } + + if (dollar == 1 || hiperiso_find_initrd_by_name(g_initrd_img_list, img->name)) + { + grub_free(img); + } + else + { + if (g_initrd_img_list) + { + img->prev = g_initrd_img_tail; + g_initrd_img_tail->next = img; + } + else + { + g_initrd_img_list = img; + } + + g_initrd_img_tail = img; + g_initrd_img_count++; + } + + if (*start == ' ' || *start == '\t') + { + HISO_SKIP_SPACE(start); + } + else + { + break; + } + } + } + + grub_free(buf); + grub_file_close(file); + + if (initrd_dollar > 0 && grub_strncmp(fileName, "(loop)/", 7) == 0) + { + debug("collect initrd variable %d\n", initrd_dollar); + hiperiso_linux_collect_boot_initrds(); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_grub_initrd_hook(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + char filePath[256]; + hiperiso_initrd_ctx *ctx = (hiperiso_initrd_ctx *)data; + + (void)info; + + debug("hiperiso_grub_initrd_hook %s\n", filename); + + if (NULL == grub_strstr(filename, ".cfg") && + NULL == grub_strstr(filename, ".CFG") && + NULL == grub_strstr(filename, ".conf")) + { + return 0; + } + + debug("init hook dir <%s%s>\n", ctx->path_prefix, filename); + + grub_snprintf(filePath, sizeof(filePath) - 1, "%s%s", ctx->dir_prefix, filename); + hiperiso_grub_cfg_initrd_collect(filePath); + + return 0; +} + +grub_err_t hiperiso_cmd_grub_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_fs_t fs; + grub_device_t dev = NULL; + char *device_name = NULL; + hiperiso_initrd_ctx ctx; + + (void)ctxt; + (void)argc; + + if (argc != 2) + { + return 0; + } + + debug("grub initrd collect %s %s\n", args[0], args[1]); + + if (grub_strcmp(args[0], "file") == 0) + { + return hiperiso_grub_cfg_initrd_collect(args[1]); + } + + device_name = grub_file_get_device_name(args[1]); + if (!device_name) + { + debug("failed to get device name %s\n", args[1]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("failed to open device %s\n", device_name); + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + debug("failed to probe fs %d\n", grub_errno); + goto end; + } + + ctx.dir_prefix = args[1]; + ctx.path_prefix = grub_strstr(args[1], device_name); + if (ctx.path_prefix) + { + ctx.path_prefix += grub_strlen(device_name) + 1; + } + else + { + ctx.path_prefix = args[1]; + } + + debug("ctx.path_prefix:<%s>\n", ctx.path_prefix); + + fs->fs_dir(dev, ctx.path_prefix, hiperiso_grub_initrd_hook, &ctx); + +end: + check_free(device_name, grub_free); + check_free(dev, grub_device_close); + + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc, char **args) +{ + initrd_info *img = NULL; + + (void)ctxt; + (void)argc; + + debug("hiperiso_cmd_specify_initrd_file %s\n", args[0]); + + img = grub_zalloc(sizeof(initrd_info)); + if (!img) + { + return 1; + } + + grub_strncpy(img->name, args[0], sizeof(img->name)); + if (hiperiso_find_initrd_by_name(g_initrd_img_list, img->name)) + { + debug("%s is already exist\n", args[0]); + grub_free(img); + } + else + { + if (g_initrd_img_list) + { + img->prev = g_initrd_img_tail; + g_initrd_img_tail->next = img; + } + else + { + g_initrd_img_list = img; + } + + g_initrd_img_tail = img; + g_initrd_img_count++; + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_cpio_newc_get_int(char *value) +{ + char buf[16] = {0}; + + grub_memcpy(buf, value, 8); + return (int)grub_strtoul(buf, NULL, 16); +} + +static void hiperiso_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen) +{ + int i; + int len; + char intbuf[32]; + + len = grub_snprintf(intbuf, sizeof(intbuf), "%x", value); + + for (i = 0; i < buflen; i++) + { + buf[i] = '0'; + } + + if (len > buflen) + { + grub_printf("int buf len overflow %d %d\n", len, buflen); + } + else + { + grub_memcpy(buf + buflen - len, intbuf, len); + } +} + +int hiperiso_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name) +{ + int namelen = 0; + int headlen = 0; + static grub_uint32_t cpio_ino = 0xFFFFFFF0; + cpio_newc_header *cpio = (cpio_newc_header *)buf; + + namelen = grub_strlen(name) + 1; + headlen = sizeof(cpio_newc_header) + namelen; + headlen = hiperiso_align(headlen, 4); + + grub_memset(cpio, '0', sizeof(cpio_newc_header)); + grub_memset(cpio + 1, 0, headlen - sizeof(cpio_newc_header)); + + grub_memcpy(cpio->c_magic, "070701", 6); + hiperiso_cpio_newc_fill_int(cpio_ino--, cpio->c_ino, 8); + hiperiso_cpio_newc_fill_int(0100777, cpio->c_mode, 8); + hiperiso_cpio_newc_fill_int(1, cpio->c_nlink, 8); + hiperiso_cpio_newc_fill_int(filesize, cpio->c_filesize, 8); + hiperiso_cpio_newc_fill_int(namelen, cpio->c_namesize, 8); + grub_memcpy(cpio + 1, name, namelen); + + if (filedata) + { + grub_memcpy((char *)cpio + headlen, filedata, filesize); + } + + return headlen; +} + +static grub_uint32_t hiperiso_linux_get_virt_chunk_count(void) +{ + int i; + grub_uint32_t count = g_valid_initrd_count; + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + count++; + } + } + } + + if (g_append_ext_sector > 0) + { + count++; + } + + return count; +} + +static grub_uint32_t hiperiso_linux_get_virt_chunk_size(void) +{ + int i; + grub_uint32_t size; + + size = (sizeof(hiperiso_virt_chunk) + g_hiperiso_cpio_size) * g_valid_initrd_count; + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + size += sizeof(hiperiso_virt_chunk) + g_conf_replace_new_len_align[i]; + } + } + } + + if (g_append_ext_sector > 0) + { + size += sizeof(hiperiso_virt_chunk) + HISO_APPEND_EXT_SIZE; + } + + return size; +} + +static void hiperiso_linux_fill_virt_data( grub_uint64_t isosize, hiperiso_chain_head *chain) +{ + int i = 0; + int id = 0; + int virtid = 0; + initrd_info *node; + grub_uint64_t sector; + grub_uint32_t offset; + grub_uint32_t cpio_secs; + grub_uint32_t initrd_secs; + char *override; + hiperiso_virt_chunk *cur; + hiperiso_grub_param_file_replace *replace = NULL; + char name[32]; + + override = (char *)chain + chain->virt_chunk_offset; + sector = (isosize + 2047) / 2048; + cpio_secs = g_hiperiso_cpio_size / 2048; + + offset = hiperiso_linux_get_virt_chunk_count() * sizeof(hiperiso_virt_chunk); + cur = (hiperiso_virt_chunk *)override; + + for (node = g_initrd_img_list; node; node = node->next) + { + if (node->size == 0) + { + continue; + } + + initrd_secs = (grub_uint32_t)((node->size + 2047) / 2048); + + cur->mem_sector_start = sector; + cur->mem_sector_end = cur->mem_sector_start + cpio_secs; + cur->mem_sector_offset = offset; + cur->remap_sector_start = cur->mem_sector_end; + cur->remap_sector_end = cur->remap_sector_start + initrd_secs; + cur->org_sector_start = (grub_uint32_t)(node->offset / 2048); + + grub_memcpy(g_hiperiso_runtime_buf, &chain->os_param, sizeof(hiperiso_os_param)); + + grub_memset(name, 0, 16); + grub_snprintf(name, sizeof(name), "initrd%03d", ++id); + + grub_memcpy(g_hiperiso_initrd_head + 1, name, 16); + hiperiso_cpio_newc_fill_int((grub_uint32_t)node->size, g_hiperiso_initrd_head->c_filesize, 8); + + grub_memcpy(override + offset, g_hiperiso_cpio_buf, g_hiperiso_cpio_size); + + chain->virt_img_size_in_bytes += g_hiperiso_cpio_size + initrd_secs * 2048; + + offset += g_hiperiso_cpio_size; + sector += cpio_secs + initrd_secs; + cur++; + virtid++; + } + + /* Lenovo EasyStartup need an addional sector for boundary check */ + if (g_append_ext_sector > 0) + { + cpio_secs = HISO_APPEND_EXT_SIZE / 2048; + + cur->mem_sector_start = sector; + cur->mem_sector_end = cur->mem_sector_start + cpio_secs; + cur->mem_sector_offset = offset; + cur->remap_sector_start = 0; + cur->remap_sector_end = 0; + cur->org_sector_start = 0; + + grub_memset(override + offset, 0, HISO_APPEND_EXT_SIZE); + + chain->virt_img_size_in_bytes += HISO_APPEND_EXT_SIZE; + + offset += HISO_APPEND_EXT_SIZE; + sector += cpio_secs; + cur++; + virtid++; + } + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + cpio_secs = g_conf_replace_new_len_align[i] / 2048; + + cur->mem_sector_start = sector; + cur->mem_sector_end = cur->mem_sector_start + cpio_secs; + cur->mem_sector_offset = offset; + cur->remap_sector_start = 0; + cur->remap_sector_end = 0; + cur->org_sector_start = 0; + + grub_memcpy(override + offset, g_conf_replace_new_buf[i], g_conf_replace_new_len[i]); + + chain->virt_img_size_in_bytes += g_conf_replace_new_len_align[i]; + + replace = g_grub_param->img_replace + i; + if (replace->magic == GRUB_IMG_REPLACE_MAGIC) + { + replace->new_file_virtual_id = virtid; + } + + offset += g_conf_replace_new_len_align[i]; + sector += cpio_secs; + cur++; + virtid++; + } + } + } + + return; +} + +static grub_uint32_t hiperiso_linux_get_override_chunk_count(void) +{ + int i; + grub_uint32_t count = g_valid_initrd_count; + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + count++; + } + } + } + + if (g_svd_replace_offset > 0) + { + count++; + } + + return count; +} + +static grub_uint32_t hiperiso_linux_get_override_chunk_size(void) +{ + int i; + int count = g_valid_initrd_count; + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + count++; + } + } + } + + if (g_svd_replace_offset > 0) + { + count++; + } + + return sizeof(hiperiso_override_chunk) * count; +} + +static void hiperiso_linux_fill_override_data( grub_uint64_t isosize, void *override) +{ + int i; + initrd_info *node; + grub_uint32_t mod; + grub_uint32_t newlen; + grub_uint64_t sector; + hiperiso_override_chunk *cur; + hiperiso_iso9660_override *dirent; + hiperiso_udf_override *udf; + + sector = (isosize + 2047) / 2048; + + cur = (hiperiso_override_chunk *)override; + for (node = g_initrd_img_list; node; node = node->next) + { + if (node->size == 0) + { + continue; + } + + newlen = (grub_uint32_t)(node->size + g_hiperiso_cpio_size); + mod = newlen % 4; + if (mod > 0) + { + newlen += 4 - mod; /* cpio must align with 4 */ + } + + if (node->iso_type == 0) + { + dirent = (hiperiso_iso9660_override *)node->override_data; + + node->override_length = sizeof(hiperiso_iso9660_override); + dirent->first_sector = (grub_uint32_t)sector; + dirent->size = newlen; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + + sector += (dirent->size + 2047) / 2048; + } + else + { + udf = (hiperiso_udf_override *)node->override_data; + + node->override_length = sizeof(hiperiso_udf_override); + udf->length = newlen; + udf->position = (grub_uint32_t)sector - node->udf_start_block; + + sector += (udf->length + 2047) / 2048; + } + + cur->img_offset = node->override_offset; + cur->override_size = node->override_length; + grub_memcpy(cur->override_data, node->override_data, cur->override_size); + cur++; + } + + if (g_conf_replace_count > 0) + { + for (i = 0; i < g_conf_replace_count; i++) + { + if (g_conf_replace_offset[i] > 0) + { + cur->img_offset = g_conf_replace_offset[i]; + cur->override_size = sizeof(hiperiso_iso9660_override); + + newlen = (grub_uint32_t)(g_conf_replace_new_len[i]); + + dirent = (hiperiso_iso9660_override *)cur->override_data; + dirent->first_sector = (grub_uint32_t)sector; + dirent->size = newlen; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + + sector += (dirent->size + 2047) / 2048; + cur++; + } + } + } + + if (g_svd_replace_offset > 0) + { + cur->img_offset = g_svd_replace_offset; + cur->override_size = 1; + cur->override_data[0] = 0xFF; + cur++; + } + + return; +} + +grub_err_t hiperiso_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char buf[32] = {0}; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc == 1) + { + grub_snprintf(buf, sizeof(buf), "%d", g_initrd_img_count); + grub_env_set(args[0], buf); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char buf[32] = {0}; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc == 1) + { + grub_snprintf(buf, sizeof(buf), "%d", g_valid_initrd_count); + grub_env_set(args[0], buf); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_linux_locate_initrd(int filt, int *filtcnt) +{ + int data; + int filtbysize = 1; + int sizefilt = 0; + grub_file_t file; + initrd_info *node; + + debug("hiperiso_linux_locate_initrd %d\n", filt); + + g_valid_initrd_count = 0; + + if (grub_env_get("INITRD_NO_SIZE_FILT")) + { + filtbysize = 0; + } + + for (node = g_initrd_img_list; node; node = node->next) + { + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(loop)%s", node->name); + if (!file) + { + continue; + } + + debug("file <%s> size:%d\n", node->name, (int)file->size); + + /* initrd file too small */ + if (filtbysize + && (NULL == grub_strstr(node->name, "minirt.gz")) + && (NULL == grub_strstr(node->name, "initrd.xz")) + && (NULL == grub_strstr(node->name, "initrd.gz")) + ) + { + if (filt > 0 && file->size <= g_hiperiso_cpio_size + 2048) + { + debug("file size too small %d\n", (int)g_hiperiso_cpio_size); + grub_file_close(file); + sizefilt++; + continue; + } + } + + /* skip hdt.img */ + if (file->size <= HISO_SIZE_1MB && grub_strcmp(node->name, "/boot/hdt.img") == 0) + { + continue; + } + + if (grub_strcmp(file->fs->name, "iso9660") == 0) + { + node->iso_type = 0; + node->override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2; + + grub_file_read(file, &data, 1); // just read for hook trigger + node->offset = grub_iso9660_get_last_read_pos(file); + } + else + { + /* TBD */ + } + + node->size = file->size; + g_valid_initrd_count++; + + grub_file_close(file); + } + + *filtcnt = sizefilt; + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + + +grub_err_t hiperiso_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int index = 0; + char buf[32]; + initrd_info *node = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 1) + { + return 1; + } + + if (g_initrd_img_count == 1) + { + hiperiso_set_env(args[0], "0"); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); + } + + for (node = g_initrd_img_list; node; node = node->next) + { + if (node->size <= 0) + { + continue; + } + + if (grub_strstr(node->name, "ucode") || grub_strstr(node->name, "-firmware")) + { + index++; + continue; + } + + grub_snprintf(buf, sizeof(buf), "%d", index); + hiperiso_set_env(args[0], buf); + break; + } + + debug("main initrd index:%d\n", index); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int sizefilt = 0; + + (void)ctxt; + (void)argc; + (void)args; + + hiperiso_linux_locate_initrd(1, &sizefilt); + + if (g_valid_initrd_count == 0 && sizefilt > 0) + { + hiperiso_linux_locate_initrd(0, &sizefilt); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_cpio_busybox64(cpio_newc_header *head, const char *file) +{ + char *name; + int namelen; + int offset; + int count = 0; + char filepath[128]; + + grub_snprintf(filepath, sizeof(filepath), "hiperiso/busybox/%s", file); + + name = (char *)(head + 1); + while (name[0] && count < 2) + { + if (grub_strcmp(name, "hiperiso/busybox/ash") == 0) + { + grub_memcpy(name, "hiperiso/busybox/32h", 18); + count++; + } + else if (grub_strcmp(name, filepath) == 0) + { + grub_memcpy(name, "hiperiso/busybox/ash", 18); + count++; + } + + namelen = hiperiso_cpio_newc_get_int(head->c_namesize); + offset = sizeof(cpio_newc_header) + namelen; + offset = hiperiso_align(offset, 4); + offset += hiperiso_cpio_newc_get_int(head->c_filesize); + offset = hiperiso_align(offset, 4); + + head = (cpio_newc_header *)((char *)head + offset); + name = (char *)(head + 1); + } + + return 0; +} + + +grub_err_t hiperiso_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + debug("hiperiso_cmd_busybox_64 %d\n", argc); + hiperiso_cpio_busybox64((cpio_newc_header *)g_hiperiso_cpio_buf, args[0]); + return 0; +} + +grub_err_t hiperiso_cmd_skip_svd(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + grub_file_t file; + char buf[16]; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]); + } + + for (i = 0; i < 10; i++) + { + buf[0] = 0; + grub_file_seek(file, (17 + i) * 2048); + grub_file_read(file, buf, 16); + + if (buf[0] == 2 && grub_strncmp(buf + 1, "CD001", 5) == 0) + { + debug("Find SVD at VD %d\n", i); + g_svd_replace_offset = (17 + i) * 2048; + break; + } + } + + if (i >= 10) + { + debug("SVD not found %d\n", (int)g_svd_replace_offset); + } + + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_append_ext_sector(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + if (args[0][0] == '1') + { + g_append_ext_sector = 1; + } + else + { + g_append_ext_sector = 0; + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int rc; + char *pos = NULL; + char *template_file = NULL; + char *template_buf = NULL; + char *persistent_buf = NULL; + char *injection_buf = NULL; + dud *dudnode = NULL; + char tmpname[128]; + const char *injection_file = NULL; + grub_uint8_t *buf = NULL; + grub_uint32_t mod; + grub_uint32_t headlen; + grub_uint32_t initrd_head_len; + grub_uint32_t padlen; + grub_uint32_t img_chunk_size; + grub_uint32_t template_size = 0; + grub_uint32_t persistent_size = 0; + grub_uint32_t injection_size = 0; + grub_uint32_t dud_size = 0; + grub_file_t file; + grub_file_t archfile; + grub_file_t tmpfile; + install_template *template_node = NULL; + hiperiso_img_chunk_list chunk_list; + + (void)ctxt; + (void)argc; + + if (argc != 4) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s cpiofile\n", cmd_raw_name); + } + + if (g_img_chunk_list.chunk == NULL || g_img_chunk_list.cur_chunk == 0) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "image chunk is null\n"); + } + + img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/%s", args[0], HISO_COMM_CPIO); + if (!file) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s/%s\n", args[0], HISO_COMM_CPIO); + } + + archfile = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/%s", args[0], HISO_ARCH_CPIO); + if (!archfile) + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s/%s\n", args[0], HISO_ARCH_CPIO); + grub_file_close(file); + } + + debug("load %s %s success\n", HISO_COMM_CPIO, HISO_ARCH_CPIO); + + if (g_hiperiso_cpio_buf) + { + grub_free(g_hiperiso_cpio_buf); + g_hiperiso_cpio_buf = NULL; + g_hiperiso_cpio_size = 0; + } + + rc = hiperiso_plugin_get_persistent_chunklist(args[1], -1, &chunk_list); + if (rc == 0 && chunk_list.cur_chunk > 0 && chunk_list.chunk) + { + persistent_size = chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + persistent_buf = (char *)(chunk_list.chunk); + } + + template_file = hiperiso_plugin_get_cur_install_template(args[1], &template_node); + if (template_file) + { + debug("auto install template: <%s> \n", + template_file, template_node->filebuf, template_node->filelen); + + template_size = template_node->filelen; + template_buf = grub_malloc(template_size); + if (template_buf) + { + grub_memcpy(template_buf, template_node->filebuf, template_size); + } + } + else + { + debug("auto install script skipped or not configed %s\n", args[1]); + } + + injection_file = hiperiso_plugin_get_injection(args[1]); + if (injection_file) + { + debug("injection archive: <%s>\n", injection_file); + tmpfile = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", args[2], injection_file); + if (tmpfile) + { + debug("injection archive size:%d\n", (int)tmpfile->size); + injection_size = tmpfile->size; + injection_buf = grub_malloc(injection_size); + if (injection_buf) + { + grub_file_read(tmpfile, injection_buf, injection_size); + } + + grub_file_close(tmpfile); + } + else + { + debug("Failed to open injection archive %s%s\n", args[2], injection_file); + } + } + else + { + debug("injection not configed %s\n", args[1]); + } + + dudnode = hiperiso_plugin_find_dud(args[1]); + if (dudnode) + { + debug("dud file: <%d>\n", dudnode->dudnum); + hiperiso_plugin_load_dud(dudnode, args[2]); + for (i = 0; i < dudnode->dudnum; i++) + { + if (dudnode->files[i].size > 0) + { + dud_size += dudnode->files[i].size + sizeof(cpio_newc_header); + } + } + } + else + { + debug("dud not configed %s\n", args[1]); + } + + g_hiperiso_cpio_buf = grub_malloc(file->size + archfile->size + 40960 + template_size + + persistent_size + injection_size + dud_size + img_chunk_size); + if (NULL == g_hiperiso_cpio_buf) + { + grub_file_close(file); + grub_file_close(archfile); + return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size); + } + + grub_file_read(file, g_hiperiso_cpio_buf, file->size); + buf = (grub_uint8_t *)(g_hiperiso_cpio_buf + file->size - 4); + while (*((grub_uint32_t *)buf) != 0x37303730) + { + buf -= 4; + } + + grub_file_read(archfile, buf, archfile->size); + buf += (archfile->size - 4); + while (*((grub_uint32_t *)buf) != 0x37303730) + { + buf -= 4; + } + + /* get initrd head len */ + initrd_head_len = hiperiso_cpio_newc_fill_head(buf, 0, NULL, "initrd000.xx"); + + /* step1: insert image chunk data to cpio */ + headlen = hiperiso_cpio_newc_fill_head(buf, img_chunk_size, g_img_chunk_list.chunk, "hiperiso/hiperiso_image_map"); + buf += headlen + hiperiso_align(img_chunk_size, 4); + + if (template_buf) + { + headlen = hiperiso_cpio_newc_fill_head(buf, template_size, template_buf, "hiperiso/autoinstall"); + buf += headlen + hiperiso_align(template_size, 4); + grub_check_free(template_buf); + } + + if (persistent_size > 0 && persistent_buf) + { + headlen = hiperiso_cpio_newc_fill_head(buf, persistent_size, persistent_buf, "hiperiso/hiperiso_persistent_map"); + buf += headlen + hiperiso_align(persistent_size, 4); + grub_check_free(persistent_buf); + } + + if (injection_size > 0 && injection_buf) + { + headlen = hiperiso_cpio_newc_fill_head(buf, injection_size, injection_buf, "hiperiso/hiperiso_injection"); + buf += headlen + hiperiso_align(injection_size, 4); + + grub_free(injection_buf); + injection_buf = NULL; + } + + if (dud_size > 0) + { + for (i = 0; i < dudnode->dudnum; i++) + { + pos = grub_strrchr(dudnode->dudpath[i].path, '.'); + grub_snprintf(tmpname, sizeof(tmpname), "hiperiso/hiperiso_dud%d%s", i, (pos ? pos : ".iso")); + dud_size = dudnode->files[i].size; + headlen = hiperiso_cpio_newc_fill_head(buf, dud_size, dudnode->files[i].buf, tmpname); + buf += headlen + hiperiso_align(dud_size, 4); + } + } + + /* step2: insert os param to cpio */ + headlen = hiperiso_cpio_newc_fill_head(buf, 0, NULL, "hiperiso/hiperiso_os_param"); + padlen = sizeof(hiperiso_os_param); + g_hiperiso_cpio_size = (grub_uint32_t)(buf - g_hiperiso_cpio_buf) + headlen + padlen + initrd_head_len; + mod = g_hiperiso_cpio_size % 2048; + if (mod) + { + g_hiperiso_cpio_size += 2048 - mod; + padlen += 2048 - mod; + } + + /* update os param data size, the data will be updated before chain boot */ + hiperiso_cpio_newc_fill_int(padlen, ((cpio_newc_header *)buf)->c_filesize, 8); + g_hiperiso_runtime_buf = (grub_uint8_t *)buf + headlen; + + /* step3: fill initrd cpio head, the file size will be updated before chain boot */ + g_hiperiso_initrd_head = (cpio_newc_header *)(g_hiperiso_runtime_buf + padlen); + hiperiso_cpio_newc_fill_head(g_hiperiso_initrd_head, 0, NULL, "initrd000.xx"); + + grub_file_close(file); + grub_file_close(archfile); + + if (grub_strcmp(args[3], "busybox=64") == 0) + { + debug("cpio busybox proc %s\n", args[3]); + hiperiso_cpio_busybox64((cpio_newc_header *)g_hiperiso_cpio_buf, "64h"); + } + else if (grub_strcmp(args[3], "busybox=a64") == 0) + { + debug("cpio busybox proc %s\n", args[3]); + hiperiso_cpio_busybox64((cpio_newc_header *)g_hiperiso_cpio_buf, "a64"); + } + else if (grub_strcmp(args[3], "busybox=m64") == 0) + { + debug("cpio busybox proc %s\n", args[3]); + hiperiso_cpio_busybox64((cpio_newc_header *)g_hiperiso_cpio_buf, "m64"); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int mod; + int bufsize; + int namelen; + int offset; + char *name; + grub_uint8_t *bufend; + cpio_newc_header *head; + grub_file_t file; + const grub_uint8_t trailler[124] = { + 0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52, + 0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00 + }; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", args[0], args[1]); + if (!file) + { + return 1; + } + + grub_memset(g_hiperiso_runtime_buf, 0, sizeof(hiperiso_os_param)); + hiperiso_fill_os_param(file, (hiperiso_os_param *)g_hiperiso_runtime_buf); + + grub_file_close(file); + + grub_memcpy(g_hiperiso_initrd_head, trailler, sizeof(trailler)); + bufend = (grub_uint8_t *)g_hiperiso_initrd_head + sizeof(trailler); + + bufsize = (int)(bufend - g_hiperiso_cpio_buf); + mod = bufsize % 512; + if (mod) + { + grub_memset(bufend, 0, 512 - mod); + bufsize += 512 - mod; + } + + if (argc > 1 && grub_strcmp(args[2], "noinit") == 0) + { + head = (cpio_newc_header *)g_hiperiso_cpio_buf; + name = (char *)(head + 1); + + while (grub_strcmp(name, "TRAILER!!!")) + { + if (grub_strcmp(name, "init") == 0) + { + grub_memcpy(name, "xxxx", 4); + } + else if (grub_strcmp(name, "linuxrc") == 0) + { + grub_memcpy(name, "hisoxrc", 7); + } + else if (grub_strcmp(name, "sbin") == 0) + { + grub_memcpy(name, "hiso", 4); + } + else if (grub_strcmp(name, "sbin/init") == 0) + { + grub_memcpy(name, "hiso/hiso", 9); + } + + namelen = hiperiso_cpio_newc_get_int(head->c_namesize); + offset = sizeof(cpio_newc_header) + namelen; + offset = hiperiso_align(offset, 4); + offset += hiperiso_cpio_newc_get_int(head->c_filesize); + offset = hiperiso_align(offset, 4); + + head = (cpio_newc_header *)((char *)head + offset); + name = (char *)(head + 1); + } + } + + hiperiso_memfile_env_set("hiperiso_cpio", g_hiperiso_cpio_buf, (ulonglong)bufsize); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 0; + int hiperiso_compatible = 0; + grub_uint32_t size = 0; + grub_uint64_t isosize = 0; + grub_uint32_t boot_catlog = 0; + grub_uint32_t img_chunk_size = 0; + grub_uint32_t override_count = 0; + grub_uint32_t override_size = 0; + grub_uint32_t virt_chunk_count = 0; + grub_uint32_t virt_chunk_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + const char *compatible; + hiperiso_chain_head *chain; + + (void)ctxt; + (void)argc; + + compatible = grub_env_get("hiperiso_compatible"); + if (compatible && compatible[0] == 'Y') + { + hiperiso_compatible = 1; + } + + if ((NULL == g_img_chunk_list.chunk) || (0 == hiperiso_compatible && g_hiperiso_cpio_buf == NULL)) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return 1; + } + + isosize = file->size; + + len = (int)grub_strlen(args[0]); + if (len >= 4 && 0 == grub_strcasecmp(args[0] + len - 4, ".img")) + { + debug("boot catlog %u for img file\n", boot_catlog); + } + else + { + boot_catlog = hiperiso_get_iso_boot_catlog(file); + if (boot_catlog) + { + if (hiperiso_is_efi_os() && (!hiperiso_has_efi_eltorito(file, boot_catlog))) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + } + else + { + if (hiperiso_is_efi_os()) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + else + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]); + } + } + } + + img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + override_count = hiperiso_linux_get_override_chunk_count(); + virt_chunk_count = hiperiso_linux_get_virt_chunk_count(); + + if (hiperiso_compatible) + { + size = sizeof(hiperiso_chain_head) + img_chunk_size; + } + else + { + override_size = hiperiso_linux_get_override_chunk_size(); + virt_chunk_size = hiperiso_linux_get_virt_chunk_size(); + size = sizeof(hiperiso_chain_head) + img_chunk_size + override_size + virt_chunk_size; + } + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain linux memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_linux; + hiperiso_fill_os_param(file, &(chain->os_param)); + + /* part 2: chain head */ + disk = file->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + chain->real_img_size_in_bytes = file->size; + chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048; + chain->boot_catalog = boot_catlog; + + if (!hiperiso_is_efi_os()) + { + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector)); + } + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_img_chunk_list.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size); + + if (hiperiso_compatible) + { + return 0; + } + + /* part 4: override chunk */ + if (override_count > 0) + { + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size; + chain->override_chunk_num = override_count; + hiperiso_linux_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset); + } + + /* part 5: virt chunk */ + if (virt_chunk_count > 0) + { + chain->virt_chunk_offset = chain->override_chunk_offset + override_size; + chain->virt_chunk_num = virt_chunk_count; + hiperiso_linux_fill_virt_data(isosize, chain); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static char *hiperiso_systemd_conf_tag(char *buf, const char *tag, int optional) +{ + int taglen = 0; + char *start = NULL; + char *nextline = NULL; + + taglen = grub_strlen(tag); + for (start = buf; start; start = nextline) + { + nextline = hiperiso_get_line(start); + HISO_SKIP_SPACE(start); + + if (grub_strncmp(start, tag, taglen) == 0 && (start[taglen] == ' ' || start[taglen] == '\t')) + { + start += taglen; + HISO_SKIP_SPACE(start); + return start; + } + } + + if (optional == 0) + { + debug("tag<%s> NOT found\n", tag); + } + return NULL; +} + +static int hiperiso_systemd_conf_hook(const char *filename, const struct grub_dirhook_info *info, void *data) +{ + int oldpos = 0; + char *tag = NULL; + char *bkbuf = NULL; + char *filebuf = NULL; + grub_file_t file = NULL; + systemd_menu_ctx *ctx = (systemd_menu_ctx *)data; + + debug("hiperiso_systemd_conf_hook %s\n", filename); + + if (info->dir || NULL == grub_strstr(filename, ".conf")) + { + return 0; + } + + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/loader/entries/%s", ctx->dev, filename); + if (!file) + { + return 0; + } + + filebuf = grub_zalloc(2 * file->size + 8); + if (!filebuf) + { + goto out; + } + + bkbuf = filebuf + file->size + 4; + grub_file_read(file, bkbuf, file->size); + + oldpos = ctx->pos; + + /* title --> menuentry */ + grub_memcpy(filebuf, bkbuf, file->size); + tag = hiperiso_systemd_conf_tag(filebuf, "title", 0); + hiso_check_goto_out(tag); + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, "menuentry \"%s\" {\n", tag); + + /* linux xxx */ + grub_memcpy(filebuf, bkbuf, file->size); + tag = hiperiso_systemd_conf_tag(filebuf, "linux", 0); + if (!tag) + { + ctx->pos = oldpos; + goto out; + } + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, " echo \"Loading kernel ...\"\n linux %s ", tag); + + /* kernel options */ + grub_memcpy(filebuf, bkbuf, file->size); + tag = hiperiso_systemd_conf_tag(filebuf, "options", 0); + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, "%s \n", tag ? tag : ""); + + + /* initrd xxx xxx xxx */ + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, " echo \"Loading initrd ...\"\n %s ", ctx->initrd_cmd); + grub_memcpy(filebuf, bkbuf, file->size); + tag = hiperiso_systemd_conf_tag(filebuf, "initrd", 1); + while (tag) + { + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, "%s ", tag); + tag = hiperiso_systemd_conf_tag(tag + grub_strlen(tag) + 1, "initrd", 1); + } + + hiso_len_ssprintf(ctx->buf, ctx->pos, ctx->len, "\n boot\n}\n"); + +out: + grub_check_free(filebuf); + grub_file_close(file); + return 0; +} + +grub_err_t hiperiso_cmd_linux_initrd(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int pos = 0; + char *buf = NULL; + + (void)ctxt; + + buf = (char *)grub_malloc(HISO_SIZE_4KB); + if (!buf) + { + return 1; + } + + pos += grub_snprintf(buf + pos, HISO_SIZE_4KB - pos, "initrd mem:%s:size:%s", + grub_env_get("hiperiso_cpio_addr"), grub_env_get("hiperiso_cpio_size")); + + for (i = 0; i < argc; i++) + { + pos += grub_snprintf(buf + pos, HISO_SIZE_4KB - pos, " newc:initrd%03d:%s", i + 1, args[i]); + } + + grub_script_execute_sourcecode(buf); + grub_free(buf); + + return 0; +} + +grub_err_t hiperiso_cmd_linux_systemd_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + static char *buf = NULL; + grub_fs_t fs; + char *device_name = NULL; + grub_device_t dev = NULL; + systemd_menu_ctx ctx; + + (void)ctxt; + (void)argc; + + if (!buf) + { + buf = grub_malloc(HISO_LINUX_SYSTEMD_MENU_MAX_BUF); + if (!buf) + { + goto end; + } + } + + device_name = grub_file_get_device_name(args[0]); + if (!device_name) + { + debug("failed to get device name %s\n", args[0]); + goto end; + } + + dev = grub_device_open(device_name); + if (!dev) + { + debug("failed to open device %s\n", device_name); + goto end; + } + + fs = grub_fs_probe(dev); + if (!fs) + { + debug("failed to probe fs %d\n", grub_errno); + goto end; + } + + ctx.dev = args[0]; + ctx.buf = buf; + ctx.initrd_cmd = args[2] ? args[2] : "initrd"; + ctx.pos = 0; + ctx.len = HISO_LINUX_SYSTEMD_MENU_MAX_BUF; + fs->fs_dir(dev, "/loader/entries", hiperiso_systemd_conf_hook, &ctx); + + hiperiso_memfile_env_set(args[1], buf, (ulonglong)(ctx.pos)); + +end: + grub_check_free(device_name); + check_free(dev, grub_device_close); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_limine_path_convert(char *path) +{ + char newpath[256] = {0}; + + if (grub_strncmp(path, "boot://2/", 9) == 0) + { + grub_snprintf(newpath, sizeof(newpath), "(vtimghd,2)/%s", path + 9); + } + else if (grub_strncmp(path, "boot://1/", 9) == 0) + { + grub_snprintf(newpath, sizeof(newpath), "(vtimghd,1)/%s", path + 9); + } + + if (newpath[0]) + { + grub_snprintf(path, 1024, "%s", newpath); + } + + return 0; +} + +grub_err_t hiperiso_cmd_linux_limine_menu(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int pos = 0; + int sub = 0; + int len = HISO_LINUX_SYSTEMD_MENU_MAX_BUF; + char *filebuf = NULL; + char *start = NULL; + char *nextline = NULL; + grub_file_t file = NULL; + char *title = NULL; + char *kernel = NULL; + char *initrd = NULL; + char *param = NULL; + static char *buf = NULL; + + (void)ctxt; + (void)argc; + + if (!buf) + { + buf = grub_malloc(len + 4 * 1024); + if (!buf) + { + goto end; + } + } + + title = buf + len; + kernel = title + 1024; + initrd = kernel + 1024; + param = initrd + 1024; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, args[0]); + if (!file) + { + return 0; + } + + filebuf = grub_zalloc(file->size + 8); + if (!filebuf) + { + goto end; + } + + grub_file_read(file, filebuf, file->size); + grub_file_close(file); + + + title[0] = kernel[0] = initrd[0] = param[0] = 0; + for (start = filebuf; start; start = nextline) + { + nextline = hiperiso_get_line(start); + HISO_SKIP_SPACE(start); + + if (start[0] == ':') + { + if (start[1] == ':') + { + grub_snprintf(title, 1024, "%s", start + 2); + } + else + { + if (sub) + { + hiso_len_ssprintf(buf, pos, len, "}\n"); + sub = 0; + } + + if (nextline && nextline[0] == ':' && nextline[1] == ':') + { + hiso_len_ssprintf(buf, pos, len, "submenu \"[+] %s\" {\n", start + 2); + sub = 1; + title[0] = 0; + } + else + { + grub_snprintf(title, 1024, "%s", start + 1); + } + } + } + else if (grub_strncmp(start, "KERNEL_PATH=", 12) == 0) + { + grub_snprintf(kernel, 1024, "%s", start + 12); + } + else if (grub_strncmp(start, "MODULE_PATH=", 12) == 0) + { + grub_snprintf(initrd, 1024, "%s", start + 12); + } + else if (grub_strncmp(start, "KERNEL_CMDLINE=", 15) == 0) + { + grub_snprintf(param, 1024, "%s", start + 15); + } + + if (title[0] && kernel[0] && initrd[0] && param[0]) + { + hiperiso_limine_path_convert(kernel); + hiperiso_limine_path_convert(initrd); + + hiso_len_ssprintf(buf, pos, len, "menuentry \"%s\" {\n", title); + hiso_len_ssprintf(buf, pos, len, " echo \"Downloading kernel ...\"\n linux %s %s\n", kernel, param); + hiso_len_ssprintf(buf, pos, len, " echo \"Downloading initrd ...\"\n initrd %s\n", initrd); + hiso_len_ssprintf(buf, pos, len, "}\n"); + + title[0] = kernel[0] = initrd[0] = param[0] = 0; + } + } + + if (sub) + { + hiso_len_ssprintf(buf, pos, len, "}\n"); + sub = 0; + } + + hiperiso_memfile_env_set(args[1], buf, (ulonglong)pos); + +end: + grub_check_free(filebuf); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + diff --git a/src/grub2/hiperiso_plugin.c b/src/grub2/hiperiso_plugin.c new file mode 100644 index 0000000..665d745 --- /dev/null +++ b/src/grub2/hiperiso_plugin.c @@ -0,0 +1,3657 @@ +/****************************************************************************** + * hiperiso_plugin.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +char g_arch_mode_suffix[64]; +static char g_iso_disk_name[128]; +static hiso_password g_boot_pwd; +static hiso_password g_file_type_pwd[img_type_max]; +static install_template *g_install_template_head = NULL; +static dud *g_dud_head = NULL; +static menu_password *g_pwd_head = NULL; +static persistence_config *g_persistence_head = NULL; +static menu_tip *g_menu_tip_head = NULL; +static menu_alias *g_menu_alias_head = NULL; +static menu_class *g_menu_class_head = NULL; +static custom_boot *g_custom_boot_head = NULL; +static injection_config *g_injection_head = NULL; +static auto_memdisk *g_auto_memdisk_head = NULL; +static image_list *g_image_list_head = NULL; +static conf_replace *g_conf_replace_head = NULL; +static HISO_JSON *g_menu_lang_json = NULL; + +static int g_theme_id = 0; +static int g_theme_res_fit = 0; +static int g_theme_num = 0; +static theme_list *g_theme_head = NULL; +static int g_theme_random = hiso_theme_random_boot_second; +static char g_theme_single_file[256]; +static char g_cur_menu_language[32] = {0}; +static char g_push_menu_language[32] = {0}; + +static int hiperiso_plugin_is_parent(const char *pat, int patlen, const char *isopath) +{ + if (patlen > 1) + { + if (isopath[patlen] == '/' && hiperiso_strncmp(pat, isopath, patlen) == 0 && + grub_strchr(isopath + patlen + 1, '/') == NULL) + { + return 1; + } + } + else + { + if (pat[0] == '/' && grub_strchr(isopath + 1, '/') == NULL) + { + return 1; + } + } + + return 0; +} + +static int hiperiso_plugin_control_check(HISO_JSON *json, const char *isodisk) +{ + int rc = 0; + HISO_JSON *pNode = NULL; + HISO_JSON *pChild = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array type %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_OBJECT) + { + pChild = pNode->pstChild; + if (pChild->enDataType == JSON_TYPE_STRING) + { + if (grub_strcmp(pChild->pcName, "HISO_DEFAULT_IMAGE") == 0) + { + grub_printf("%s: %s [%s]\n", pChild->pcName, pChild->unData.pcStrVal, + hiperiso_check_file_exist("%s%s", isodisk, pChild->unData.pcStrVal) ? "OK" : "NOT EXIST"); + } + else + { + grub_printf("%s: %s\n", pChild->pcName, pChild->unData.pcStrVal); + } + } + else + { + grub_printf("%s is NOT string type\n", pChild->pcName); + rc = 1; + } + } + else + { + grub_printf("%s is not an object\n", pNode->pcName); + rc = 1; + } + } + + return rc; +} + +static int hiperiso_plugin_control_entry(HISO_JSON *json, const char *isodisk) +{ + HISO_JSON *pNode = NULL; + HISO_JSON *pChild = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_OBJECT) + { + pChild = pNode->pstChild; + if (pChild->enDataType == JSON_TYPE_STRING && pChild->pcName && pChild->unData.pcStrVal) + { + hiperiso_set_env(pChild->pcName, pChild->unData.pcStrVal); + } + } + } + + return 0; +} + +static int hiperiso_plugin_theme_check(HISO_JSON *json, const char *isodisk) +{ + int exist = 0; + const char *value; + HISO_JSON *node; + + value = hiso_json_get_string_ex(json->pstChild, "file"); + if (value) + { + grub_printf("file: %s\n", value); + if (value[0] == '/') + { + exist = hiperiso_check_file_exist("%s%s", isodisk, value); + } + else + { + exist = hiperiso_check_file_exist("%s/hiperiso/%s", isodisk, value); + } + + if (exist == 0) + { + grub_printf("Theme file %s does NOT exist\n", value); + return 1; + } + } + else + { + node = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "file"); + if (node) + { + for (node = node->pstChild; node; node = node->pstNext) + { + value = node->unData.pcStrVal; + grub_printf("file: %s\n", value); + if (value[0] == '/') + { + exist = hiperiso_check_file_exist("%s%s", isodisk, value); + } + else + { + exist = hiperiso_check_file_exist("%s/hiperiso/%s", isodisk, value); + } + + if (exist == 0) + { + grub_printf("Theme file %s does NOT exist\n", value); + return 1; + } + } + + value = hiso_json_get_string_ex(json->pstChild, "random"); + if (value) + { + grub_printf("random: %s\n", value); + } + } + } + + value = hiso_json_get_string_ex(json->pstChild, "gfxmode"); + if (value) + { + grub_printf("gfxmode: %s\n", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "display_mode"); + if (value) + { + grub_printf("display_mode: %s\n", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "serial_param"); + if (value) + { + grub_printf("serial_param %s\n", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_left"); + if (value) + { + grub_printf("hiperiso_left: %s\n", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_top"); + if (value) + { + grub_printf("hiperiso_top: %s\n", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_color"); + if (value) + { + grub_printf("hiperiso_color: %s\n", value); + } + + node = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts"); + if (node) + { + for (node = node->pstChild; node; node = node->pstNext) + { + if (node->enDataType == JSON_TYPE_STRING) + { + if (hiperiso_check_file_exist("%s%s", isodisk, node->unData.pcStrVal)) + { + grub_printf("%s [OK]\n", node->unData.pcStrVal); + } + else + { + grub_printf("%s [NOT EXIST]\n", node->unData.pcStrVal); + } + } + } + } + else + { + grub_printf("fonts NOT found\n"); + } + + return 0; +} + +static int hiperiso_plugin_theme_entry(HISO_JSON *json, const char *isodisk) +{ + const char *value; + char val[64]; + char filepath[256]; + HISO_JSON *node = NULL; + theme_list *tail = NULL; + theme_list *themenode = NULL; + + value = hiso_json_get_string_ex(json->pstChild, "file"); + if (value) + { + if (value[0] == '/') + { + grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value); + } + else + { + grub_snprintf(filepath, sizeof(filepath), "%s/hiperiso/%s", isodisk, value); + } + + if (hiperiso_check_file_exist(filepath) == 0) + { + debug("Theme file %s does not exist\n", filepath); + return 0; + } + + debug("hiso_theme %s\n", filepath); + hiperiso_env_export("hiso_theme", filepath); + grub_snprintf(g_theme_single_file, sizeof(g_theme_single_file), "%s", filepath); + } + else + { + node = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "file"); + if (node) + { + for (node = node->pstChild; node; node = node->pstNext) + { + value = node->unData.pcStrVal; + if (value[0] == '/') + { + grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value); + } + else + { + grub_snprintf(filepath, sizeof(filepath), "%s/hiperiso/%s", isodisk, value); + } + + if (hiperiso_check_file_exist(filepath) == 0) + { + continue; + } + + themenode = grub_zalloc(sizeof(theme_list)); + if (themenode) + { + grub_snprintf(themenode->theme.path, sizeof(themenode->theme.path), "%s", filepath); + if (g_theme_head) + { + tail->next = themenode; + } + else + { + g_theme_head = themenode; + } + tail = themenode; + g_theme_num++; + } + } + + hiperiso_env_export("hiso_theme", "random"); + value = hiso_json_get_string_ex(json->pstChild, "random"); + if (value) + { + if (grub_strcmp(value, "boot_second") == 0) + { + g_theme_random = hiso_theme_random_boot_second; + } + else if (grub_strcmp(value, "boot_day") == 0) + { + g_theme_random = hiso_theme_random_boot_day; + } + else if (grub_strcmp(value, "boot_month") == 0) + { + g_theme_random = hiso_theme_random_boot_month; + } + } + } + } + + grub_snprintf(val, sizeof(val), "%d", g_theme_num); + grub_env_set("HISO_THEME_COUNT", val); + grub_env_export("HISO_THEME_COUNT"); + if (g_theme_num > 0) + { + hiso_json_get_int(json->pstChild, "default_file", &g_theme_id); + if (g_theme_id == 0) + { + hiso_json_get_int(json->pstChild, "resolution_fit", &g_theme_res_fit); + if (g_theme_res_fit != 1) + { + g_theme_res_fit = 0; + } + + grub_snprintf(val, sizeof(val), "%d", g_theme_res_fit); + hiperiso_env_export("hiso_res_fit", val); + } + + if (g_theme_id > g_theme_num || g_theme_id < 0) + { + g_theme_id = 0; + } + } + + value = hiso_json_get_string_ex(json->pstChild, "gfxmode"); + if (value) + { + debug("hiso_gfxmode %s\n", value); + hiperiso_env_export("hiso_gfxmode", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "display_mode"); + if (value) + { + debug("display_mode %s\n", value); + hiperiso_env_export("hiso_display_mode", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "serial_param"); + if (value) + { + debug("serial_param %s\n", value); + hiperiso_env_export("hiso_serial_param", value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_left"); + if (value) + { + hiperiso_env_export(hiperiso_left_key, value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_top"); + if (value) + { + hiperiso_env_export(hiperiso_top_key, value); + } + + value = hiso_json_get_string_ex(json->pstChild, "hiperiso_color"); + if (value) + { + hiperiso_env_export(hiperiso_color_key, value); + } + + node = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts"); + if (node) + { + for (node = node->pstChild; node; node = node->pstNext) + { + if (node->enDataType == JSON_TYPE_STRING && + hiperiso_check_file_exist("%s%s", isodisk, node->unData.pcStrVal)) + { + grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, node->unData.pcStrVal); + grub_font_load(filepath); + } + } + } + + return 0; +} + +static int hiperiso_plugin_check_path(const char *path, const char *file) +{ + if (file[0] != '/') + { + grub_printf("%s is NOT begin with '/' \n", file); + return 1; + } + + if (grub_strchr(file, '\\')) + { + grub_printf("%s contains invalid '\\' \n", file); + return 1; + } + + if (grub_strstr(file, "//")) + { + grub_printf("%s contains invalid double slash\n", file); + return 1; + } + + if (grub_strstr(file, "../")) + { + grub_printf("%s contains invalid '../' \n", file); + return 1; + } + + if (!hiperiso_check_file_exist("%s%s", path, file)) + { + grub_printf("%s%s does NOT exist\n", path, file); + return 1; + } + + return 0; +} + +static int hiperiso_plugin_check_fullpath +( + HISO_JSON *json, + const char *isodisk, + const char *key, + int *pathnum +) +{ + int rc = 0; + int ret = 0; + int cnt = 0; + HISO_JSON *node = json; + HISO_JSON *child = NULL; + + while (node) + { + if (0 == grub_strcmp(key, node->pcName)) + { + break; + } + node = node->pstNext; + } + + if (!node) + { + return 1; + } + + if (JSON_TYPE_STRING == node->enDataType) + { + cnt = 1; + ret = hiperiso_plugin_check_path(isodisk, node->unData.pcStrVal); + grub_printf("%s: %s [%s]\n", key, node->unData.pcStrVal, ret ? "FAIL" : "OK"); + } + else if (JSON_TYPE_ARRAY == node->enDataType) + { + for (child = node->pstChild; child; child = child->pstNext) + { + if (JSON_TYPE_STRING != child->enDataType) + { + grub_printf("Non string json type\n"); + } + else + { + rc = hiperiso_plugin_check_path(isodisk, child->unData.pcStrVal); + grub_printf("%s: %s [%s]\n", key, child->unData.pcStrVal, rc ? "FAIL" : "OK"); + ret += rc; + cnt++; + } + } + } + + *pathnum = cnt; + return ret; +} + +static int hiperiso_plugin_parse_fullpath +( + HISO_JSON *json, + const char *isodisk, + const char *key, + file_fullpath **fullpath, + int *pathnum +) +{ + int rc = 1; + int count = 0; + HISO_JSON *node = json; + HISO_JSON *child = NULL; + file_fullpath *path = NULL; + + while (node) + { + if (0 == grub_strcmp(key, node->pcName)) + { + break; + } + node = node->pstNext; + } + + if (!node) + { + return 1; + } + + if (JSON_TYPE_STRING == node->enDataType) + { + debug("%s is string type data\n", node->pcName); + + if ((node->unData.pcStrVal[0] != '/') || (!hiperiso_check_file_exist("%s%s", isodisk, node->unData.pcStrVal))) + { + debug("%s%s file not found\n", isodisk, node->unData.pcStrVal); + return 1; + } + + path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath)); + if (path) + { + grub_snprintf(path->path, sizeof(path->path), "%s", node->unData.pcStrVal); + *fullpath = path; + *pathnum = 1; + rc = 0; + } + } + else if (JSON_TYPE_ARRAY == node->enDataType) + { + for (child = node->pstChild; child; child = child->pstNext) + { + if ((JSON_TYPE_STRING != child->enDataType) || (child->unData.pcStrVal[0] != '/')) + { + debug("Invalid data type:%d\n", child->enDataType); + return 1; + } + count++; + } + debug("%s is array type data, count=%d\n", node->pcName, count); + + path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath) * count); + if (path) + { + *fullpath = path; + + for (count = 0, child = node->pstChild; child; child = child->pstNext) + { + if (hiperiso_check_file_exist("%s%s", isodisk, child->unData.pcStrVal)) + { + grub_snprintf(path->path, sizeof(path->path), "%s", child->unData.pcStrVal); + path++; + count++; + } + } + + *pathnum = count; + rc = 0; + } + } + + return rc; +} + +static int hiperiso_plugin_auto_install_check(HISO_JSON *json, const char *isodisk) +{ + int pathnum = 0; + int autosel = 0; + int timeout = 0; + char *pos = NULL; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array type %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("NOT object type\n"); + } + + if ((iso = hiso_json_get_string_ex(pNode->pstChild, "image")) != NULL) + { + pos = grub_strchr(iso, '*'); + if (pos || 0 == hiperiso_plugin_check_path(isodisk, iso)) + { + grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK")); + hiperiso_plugin_check_fullpath(pNode->pstChild, isodisk, "template", &pathnum); + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + grub_printf("autosel: %d [OK]\n", autosel); + } + else + { + grub_printf("autosel: %d [FAIL]\n", autosel); + } + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "timeout", &timeout)) + { + if (timeout >= 0) + { + grub_printf("timeout: %d [OK]\n", timeout); + } + else + { + grub_printf("timeout: %d [FAIL]\n", timeout); + } + } + } + else + { + grub_printf("image: %s [FAIL]\n", iso); + } + } + else if ((iso = hiso_json_get_string_ex(pNode->pstChild, "parent")) != NULL) + { + if (hiperiso_is_dir_exist("%s%s", isodisk, iso)) + { + grub_printf("parent: %s [OK]\n", iso); + hiperiso_plugin_check_fullpath(pNode->pstChild, isodisk, "template", &pathnum); + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + grub_printf("autosel: %d [OK]\n", autosel); + } + else + { + grub_printf("autosel: %d [FAIL]\n", autosel); + } + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "timeout", &timeout)) + { + if (timeout >= 0) + { + grub_printf("timeout: %d [OK]\n", timeout); + } + else + { + grub_printf("timeout: %d [FAIL]\n", timeout); + } + } + } + else + { + grub_printf("parent: %s [FAIL]\n", iso); + } + } + else + { + grub_printf("image not found\n"); + } + } + + return 0; +} + +static int hiperiso_plugin_auto_install_entry(HISO_JSON *json, const char *isodisk) +{ + int type = 0; + int pathnum = 0; + int autosel = 0; + int timeout = 0; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + install_template *node = NULL; + install_template *next = NULL; + file_fullpath *templatepath = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_install_template_head) + { + for (node = g_install_template_head; node; node = next) + { + next = node->next; + grub_check_free(node->templatepath); + grub_free(node); + } + + g_install_template_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = auto_install_type_file; + iso = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!iso) + { + type = auto_install_type_parent; + iso = hiso_json_get_string_ex(pNode->pstChild, "parent"); + } + + if (iso && iso[0] == '/') + { + if (0 == hiperiso_plugin_parse_fullpath(pNode->pstChild, isodisk, "template", &templatepath, &pathnum)) + { + node = grub_zalloc(sizeof(install_template)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso); + node->templatepath = templatepath; + node->templatenum = pathnum; + + node->autosel = -1; + node->timeout = -1; + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + node->autosel = autosel; + } + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "timeout", &timeout)) + { + if (timeout >= 0) + { + node->timeout = timeout; + } + } + + if (g_install_template_head) + { + node->next = g_install_template_head; + } + + g_install_template_head = node; + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_dud_check(HISO_JSON *json, const char *isodisk) +{ + int pathnum = 0; + char *pos = NULL; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array type %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("NOT object type\n"); + } + + iso = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (iso) + { + pos = grub_strchr(iso, '*'); + if (pos || 0 == hiperiso_plugin_check_path(isodisk, iso)) + { + grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK")); + hiperiso_plugin_check_fullpath(pNode->pstChild, isodisk, "dud", &pathnum); + } + else + { + grub_printf("image: %s [FAIL]\n", iso); + } + } + else + { + grub_printf("image not found\n"); + } + } + + return 0; +} + +static int hiperiso_plugin_dud_entry(HISO_JSON *json, const char *isodisk) +{ + int pathnum = 0; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + dud *node = NULL; + dud *next = NULL; + file_fullpath *dudpath = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_dud_head) + { + for (node = g_dud_head; node; node = next) + { + next = node->next; + grub_check_free(node->dudpath); + grub_free(node); + } + + g_dud_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + iso = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (iso && iso[0] == '/') + { + if (0 == hiperiso_plugin_parse_fullpath(pNode->pstChild, isodisk, "dud", &dudpath, &pathnum)) + { + node = grub_zalloc(sizeof(dud)); + if (node) + { + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso); + node->dudpath = dudpath; + node->dudnum = pathnum; + node->files = grub_zalloc(sizeof(dudfile) * pathnum); + + if (node->files) + { + if (g_dud_head) + { + node->next = g_dud_head; + } + + g_dud_head = node; + } + else + { + grub_free(node); + } + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_parse_pwdstr(char *pwdstr, hiso_password *pwd) +{ + int i; + int len; + char ch; + char *pos; + char bytes[3]; + hiso_password tmpPwd; + + len = (int)grub_strlen(pwdstr); + if (len > 64) + { + if (NULL == pwd) grub_printf("Password too long %d\n", len); + return 1; + } + + grub_memset(&tmpPwd, 0, sizeof(tmpPwd)); + + if (grub_strncmp(pwdstr, "txt#", 4) == 0) + { + tmpPwd.type = HISO_PASSWORD_TXT; + grub_snprintf(tmpPwd.text, sizeof(tmpPwd.text), "%s", pwdstr + 4); + } + else if (grub_strncmp(pwdstr, "md5#", 4) == 0) + { + if ((len - 4) == 32) + { + for (i = 0; i < 16; i++) + { + bytes[0] = pwdstr[4 + i * 2]; + bytes[1] = pwdstr[4 + i * 2 + 1]; + bytes[2] = 0; + + if (grub_isxdigit(bytes[0]) && grub_isxdigit(bytes[1])) + { + tmpPwd.md5[i] = (grub_uint8_t)grub_strtoul(bytes, NULL, 16); + } + else + { + if (NULL == pwd) grub_printf("Invalid md5 hex format %s %d\n", pwdstr, i); + return 1; + } + } + tmpPwd.type = HISO_PASSWORD_MD5; + } + else if ((len - 4) > 32) + { + pos = grub_strchr(pwdstr + 4, '#'); + if (!pos) + { + if (NULL == pwd) grub_printf("Invalid md5 password format %s\n", pwdstr); + return 1; + } + + if (len - 1 - ((long)pos - (long)pwdstr) != 32) + { + if (NULL == pwd) grub_printf("Invalid md5 salt password format %s\n", pwdstr); + return 1; + } + + ch = *pos; + *pos = 0; + grub_snprintf(tmpPwd.salt, sizeof(tmpPwd.salt), "%s", pwdstr + 4); + *pos = ch; + + pos++; + for (i = 0; i < 16; i++) + { + bytes[0] = pos[i * 2]; + bytes[1] = pos[i * 2 + 1]; + bytes[2] = 0; + + if (grub_isxdigit(bytes[0]) && grub_isxdigit(bytes[1])) + { + tmpPwd.md5[i] = (grub_uint8_t)grub_strtoul(bytes, NULL, 16); + } + else + { + if (NULL == pwd) grub_printf("Invalid md5 hex format %s %d\n", pwdstr, i); + return 1; + } + } + + tmpPwd.type = HISO_PASSWORD_SALT_MD5; + } + else + { + if (NULL == pwd) grub_printf("Invalid md5 password format %s\n", pwdstr); + return 1; + } + } + else + { + if (NULL == pwd) grub_printf("Invalid password format %s\n", pwdstr); + return 1; + } + + if (pwd) + { + grub_memcpy(pwd, &tmpPwd, sizeof(tmpPwd)); + } + + return 0; +} + +static int hiperiso_plugin_get_pwd_type(const char *pwd) +{ + int i; + char pwdtype[64]; + + for (i = 0; pwd && i < (int)ARRAY_SIZE(g_menu_prefix); i++) + { + grub_snprintf(pwdtype, sizeof(pwdtype), "%spwd", g_menu_prefix[i]); + if (grub_strcmp(pwdtype, pwd) == 0) + { + return img_type_start + i; + } + } + + return -1; +} + +static int hiperiso_plugin_pwd_entry(HISO_JSON *json, const char *isodisk) +{ + int type = -1; + const char *iso = NULL; + const char *pwd = NULL; + HISO_JSON *pNode = NULL; + HISO_JSON *pCNode = NULL; + menu_password *node = NULL; + menu_password *tail = NULL; + menu_password *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_OBJECT) + { + debug("Not object %d\n", json->enDataType); + return 0; + } + + if (g_pwd_head) + { + for (node = g_pwd_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_pwd_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->pcName && grub_strcmp("bootpwd", pNode->pcName) == 0) + { + hiperiso_plugin_parse_pwdstr(pNode->unData.pcStrVal, &g_boot_pwd); + } + else if ((type = hiperiso_plugin_get_pwd_type(pNode->pcName)) >= 0) + { + hiperiso_plugin_parse_pwdstr(pNode->unData.pcStrVal, g_file_type_pwd + type); + } + else if (pNode->pcName && grub_strcmp("menupwd", pNode->pcName) == 0) + { + for (pCNode = pNode->pstChild; pCNode; pCNode = pCNode->pstNext) + { + if (pCNode->enDataType != JSON_TYPE_OBJECT) + { + continue; + } + + type = hiso_menu_pwd_file; + iso = hiso_json_get_string_ex(pCNode->pstChild, "file"); + if (!iso) + { + type = hiso_menu_pwd_parent; + iso = hiso_json_get_string_ex(pCNode->pstChild, "parent"); + } + + pwd = hiso_json_get_string_ex(pCNode->pstChild, "pwd"); + if (iso && pwd && iso[0] == '/') + { + node = grub_zalloc(sizeof(menu_password)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso); + + if (hiperiso_plugin_parse_pwdstr((char *)pwd, &(node->password))) + { + grub_free(node); + continue; + } + + if (g_pwd_head) + { + tail->next = node; + } + else + { + g_pwd_head = node; + } + tail = node; + } + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_pwd_check(HISO_JSON *json, const char *isodisk) +{ + int type = -1; + char *pos = NULL; + const char *iso = NULL; + const char *pwd = NULL; + HISO_JSON *pNode = NULL; + HISO_JSON *pCNode = NULL; + + if (json->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("Not object %d\n", json->enDataType); + return 0; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->pcName && grub_strcmp("bootpwd", pNode->pcName) == 0) + { + if (0 == hiperiso_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL)) + { + grub_printf("bootpwd:<%s>\n", pNode->unData.pcStrVal); + } + else + { + grub_printf("Invalid bootpwd.\n"); + } + } + else if ((type = hiperiso_plugin_get_pwd_type(pNode->pcName)) >= 0) + { + if (0 == hiperiso_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL)) + { + grub_printf("%s:<%s>\n", pNode->pcName, pNode->unData.pcStrVal); + } + else + { + grub_printf("Invalid pwd <%s>\n", pNode->unData.pcStrVal); + } + } + else if (pNode->pcName && grub_strcmp("menupwd", pNode->pcName) == 0) + { + grub_printf("\n"); + for (pCNode = pNode->pstChild; pCNode; pCNode = pCNode->pstNext) + { + if (pCNode->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("Not object %d\n", pCNode->enDataType); + continue; + } + + if ((iso = hiso_json_get_string_ex(pCNode->pstChild, "file")) != NULL) + { + pos = grub_strchr(iso, '*'); + if (pos || 0 == hiperiso_plugin_check_path(isodisk, iso)) + { + pwd = hiso_json_get_string_ex(pCNode->pstChild, "pwd"); + + if (0 == hiperiso_plugin_parse_pwdstr((char *)pwd, NULL)) + { + grub_printf("file:<%s> [%s]\n", iso, (pos ? "*" : "OK")); + grub_printf("pwd:<%s>\n\n", pwd); + } + else + { + grub_printf("Invalid password for <%s>\n", iso); + } + } + else + { + grub_printf("<%s%s> not found\n", isodisk, iso); + } + } + else if ((iso = hiso_json_get_string_ex(pCNode->pstChild, "parent")) != NULL) + { + if (hiperiso_is_dir_exist("%s%s", isodisk, iso)) + { + pwd = hiso_json_get_string_ex(pCNode->pstChild, "pwd"); + if (0 == hiperiso_plugin_parse_pwdstr((char *)pwd, NULL)) + { + grub_printf("dir:<%s> [%s]\n", iso, (pos ? "*" : "OK")); + grub_printf("pwd:<%s>\n\n", pwd); + } + else + { + grub_printf("Invalid password for <%s>\n", iso); + } + } + else + { + grub_printf("<%s%s> not found\n", isodisk, iso); + } + } + else + { + grub_printf("No file item found in json.\n"); + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_persistence_check(HISO_JSON *json, const char *isodisk) +{ + int autosel = 0; + int timeout = 0; + int pathnum = 0; + char *pos = NULL; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array type %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("NOT object type\n"); + } + + iso = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (iso) + { + pos = grub_strchr(iso, '*'); + if (pos || 0 == hiperiso_plugin_check_path(isodisk, iso)) + { + grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK")); + hiperiso_plugin_check_fullpath(pNode->pstChild, isodisk, "backend", &pathnum); + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + grub_printf("autosel: %d [OK]\n", autosel); + } + else + { + grub_printf("autosel: %d [FAIL]\n", autosel); + } + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "timeout", &timeout)) + { + if (timeout >= 0) + { + grub_printf("timeout: %d [OK]\n", timeout); + } + else + { + grub_printf("timeout: %d [FAIL]\n", timeout); + } + } + } + else + { + grub_printf("image: %s [FAIL]\n", iso); + } + } + else + { + grub_printf("image not found\n"); + } + } + + return 0; +} + +static int hiperiso_plugin_persistence_entry(HISO_JSON *json, const char *isodisk) +{ + int autosel = 0; + int timeout = 0; + int pathnum = 0; + const char *iso = NULL; + HISO_JSON *pNode = NULL; + persistence_config *node = NULL; + persistence_config *next = NULL; + file_fullpath *backendpath = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_persistence_head) + { + for (node = g_persistence_head; node; node = next) + { + next = node->next; + grub_check_free(node->backendpath); + grub_free(node); + } + + g_persistence_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + iso = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (iso && iso[0] == '/') + { + if (0 == hiperiso_plugin_parse_fullpath(pNode->pstChild, isodisk, "backend", &backendpath, &pathnum)) + { + node = grub_zalloc(sizeof(persistence_config)); + if (node) + { + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso); + node->backendpath = backendpath; + node->backendnum = pathnum; + + node->autosel = -1; + node->timeout = -1; + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + node->autosel = autosel; + } + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "timeout", &timeout)) + { + if (timeout >= 0) + { + node->timeout = timeout; + } + } + + if (g_persistence_head) + { + node->next = g_persistence_head; + } + + g_persistence_head = node; + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_menualias_check(HISO_JSON *json, const char *isodisk) +{ + int type; + const char *path = NULL; + const char *alias = NULL; + HISO_JSON *pNode = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_alias_image_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_alias_directory; + } + + alias = hiso_json_get_string_ex(pNode->pstChild, "alias"); + if (path && path[0] == '/' && alias) + { + if (hiso_alias_image_file == type) + { + if (grub_strchr(path, '*')) + { + grub_printf("image: <%s> [ * ]\n", path); + } + else if (hiperiso_check_file_exist("%s%s", isodisk, path)) + { + grub_printf("image: <%s> [ OK ]\n", path); + } + else + { + grub_printf("image: <%s> [ NOT EXIST ]\n", path); + } + } + else + { + if (hiperiso_is_dir_exist("%s%s", isodisk, path)) + { + grub_printf("dir: <%s> [ OK ]\n", path); + } + else + { + grub_printf("dir: <%s> [ NOT EXIST ]\n", path); + } + } + + grub_printf("alias: <%s>\n\n", alias); + } + } + + return 0; +} + +static int hiperiso_plugin_menualias_entry(HISO_JSON *json, const char *isodisk) +{ + int type; + const char *path = NULL; + const char *alias = NULL; + HISO_JSON *pNode = NULL; + menu_alias *node = NULL; + menu_alias *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_menu_alias_head) + { + for (node = g_menu_alias_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_menu_alias_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_alias_image_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_alias_directory; + } + + alias = hiso_json_get_string_ex(pNode->pstChild, "alias"); + if (path && path[0] == '/' && alias) + { + node = grub_zalloc(sizeof(menu_alias)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path); + grub_snprintf(node->alias, sizeof(node->alias), "%s", alias); + + if (g_menu_alias_head) + { + node->next = g_menu_alias_head; + } + + g_menu_alias_head = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_menutip_check(HISO_JSON *json, const char *isodisk) +{ + int type; + const char *path = NULL; + const char *tip = NULL; + HISO_JSON *pNode = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_OBJECT) + { + grub_printf("Not object %d\n", json->enDataType); + return 1; + } + + tip = hiso_json_get_string_ex(json->pstChild, "left"); + if (tip) + { + grub_printf("left: <%s>\n", tip); + } + + tip = hiso_json_get_string_ex(json->pstChild, "top"); + if (tip) + { + grub_printf("top: <%s>\n", tip); + } + + tip = hiso_json_get_string_ex(json->pstChild, "color"); + if (tip) + { + grub_printf("color: <%s>\n", tip); + } + + pNode = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips"); + for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_tip_image_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_tip_directory; + } + + if (path && path[0] == '/') + { + if (hiso_tip_image_file == type) + { + if (grub_strchr(path, '*')) + { + grub_printf("image: <%s> [ * ]\n", path); + } + else if (hiperiso_check_file_exist("%s%s", isodisk, path)) + { + grub_printf("image: <%s> [ OK ]\n", path); + } + else + { + grub_printf("image: <%s> [ NOT EXIST ]\n", path); + } + } + else + { + if (hiperiso_is_dir_exist("%s%s", isodisk, path)) + { + grub_printf("dir: <%s> [ OK ]\n", path); + } + else + { + grub_printf("dir: <%s> [ NOT EXIST ]\n", path); + } + } + + tip = hiso_json_get_string_ex(pNode->pstChild, "tip"); + if (tip) + { + grub_printf("tip: <%s>\n", tip); + } + else + { + tip = hiso_json_get_string_ex(pNode->pstChild, "tip1"); + if (tip) + grub_printf("tip1: <%s>\n", tip); + else + grub_printf("tip1: \n"); + + tip = hiso_json_get_string_ex(pNode->pstChild, "tip2"); + if (tip) + grub_printf("tip2: <%s>\n", tip); + else + grub_printf("tip2: \n"); + } + } + else + { + grub_printf("image: <%s> [ INVALID ]\n", path); + } + } + + return 0; +} + +static int hiperiso_plugin_menutip_entry(HISO_JSON *json, const char *isodisk) +{ + int type; + const char *path = NULL; + const char *tip = NULL; + HISO_JSON *pNode = NULL; + menu_tip *node = NULL; + menu_tip *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_OBJECT) + { + debug("Not object %d\n", json->enDataType); + return 0; + } + + pNode = hiso_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips"); + if (pNode == NULL) + { + debug("Not tips found\n"); + return 0; + } + + if (g_menu_tip_head) + { + for (node = g_menu_tip_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_menu_tip_head = NULL; + } + + tip = hiso_json_get_string_ex(json->pstChild, "left"); + if (tip) + { + grub_env_set("HISO_TIP_LEFT", tip); + } + + tip = hiso_json_get_string_ex(json->pstChild, "top"); + if (tip) + { + grub_env_set("HISO_TIP_TOP", tip); + } + + tip = hiso_json_get_string_ex(json->pstChild, "color"); + if (tip) + { + grub_env_set("HISO_TIP_COLOR", tip); + } + + for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_tip_image_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_tip_directory; + } + + if (path && path[0] == '/') + { + node = grub_zalloc(sizeof(menu_tip)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path); + + tip = hiso_json_get_string_ex(pNode->pstChild, "tip"); + if (tip) + { + grub_snprintf(node->tip1, 1000, "%s", tip); + } + else + { + tip = hiso_json_get_string_ex(pNode->pstChild, "tip1"); + if (tip) + grub_snprintf(node->tip1, 1000, "%s", tip); + + tip = hiso_json_get_string_ex(pNode->pstChild, "tip2"); + if (tip) + grub_snprintf(node->tip2, 1000, "%s", tip); + } + + if (g_menu_tip_head) + { + node->next = g_menu_tip_head; + } + + g_menu_tip_head = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_injection_check(HISO_JSON *json, const char *isodisk) +{ + int type = 0; + const char *path = NULL; + const char *archive = NULL; + HISO_JSON *pNode = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 0; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = injection_type_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + type = injection_type_parent; + path = hiso_json_get_string_ex(pNode->pstChild, "parent"); + if (!path) + { + grub_printf("image/parent not found\n"); + continue; + } + } + + archive = hiso_json_get_string_ex(pNode->pstChild, "archive"); + if (!archive) + { + grub_printf("archive not found\n"); + continue; + } + + if (type == injection_type_file) + { + if (grub_strchr(path, '*')) + { + grub_printf("image: <%s> [*]\n", path); + } + else + { + grub_printf("image: <%s> [%s]\n", path, hiperiso_check_file_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST"); + } + } + else + { + grub_printf("parent: <%s> [%s]\n", path, + hiperiso_is_dir_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST"); + } + + grub_printf("archive: <%s> [%s]\n\n", archive, hiperiso_check_file_exist("%s%s", isodisk, archive) ? "OK" : "NOT EXIST"); + } + + return 0; +} + +static int hiperiso_plugin_injection_entry(HISO_JSON *json, const char *isodisk) +{ + int type = 0; + const char *path = NULL; + const char *archive = NULL; + HISO_JSON *pNode = NULL; + injection_config *node = NULL; + injection_config *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_injection_head) + { + for (node = g_injection_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_injection_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = injection_type_file; + path = hiso_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + type = injection_type_parent; + path = hiso_json_get_string_ex(pNode->pstChild, "parent"); + } + + archive = hiso_json_get_string_ex(pNode->pstChild, "archive"); + if (path && path[0] == '/' && archive && archive[0] == '/') + { + node = grub_zalloc(sizeof(injection_config)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path); + grub_snprintf(node->archive, sizeof(node->archive), "%s", archive); + + if (g_injection_head) + { + node->next = g_injection_head; + } + + g_injection_head = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_menuclass_entry(HISO_JSON *json, const char *isodisk) +{ + int type; + int parent = 0; + const char *key = NULL; + const char *class = NULL; + HISO_JSON *pNode = NULL; + menu_class *tail = NULL; + menu_class *node = NULL; + menu_class *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_menu_class_head) + { + for (node = g_menu_class_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_menu_class_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + parent = 0; + type = hiso_class_image_file; + key = hiso_json_get_string_ex(pNode->pstChild, "key"); + if (!key) + { + key = hiso_json_get_string_ex(pNode->pstChild, "parent"); + if (key) + { + parent = 1; + } + else + { + key = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_class_directory; + } + } + + class = hiso_json_get_string_ex(pNode->pstChild, "class"); + if (key && class) + { + node = grub_zalloc(sizeof(menu_class)); + if (node) + { + node->type = type; + node->parent = parent; + node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key); + grub_snprintf(node->class, sizeof(node->class), "%s", class); + + if (g_menu_class_head) + { + tail->next = node; + } + else + { + g_menu_class_head = node; + } + tail = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_menuclass_check(HISO_JSON *json, const char *isodisk) +{ + const char *name = NULL; + const char *key = NULL; + const char *class = NULL; + HISO_JSON *pNode = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + name = "key"; + key = hiso_json_get_string_ex(pNode->pstChild, "key"); + if (!key) + { + name = "parent"; + key = hiso_json_get_string_ex(pNode->pstChild, "parent"); + if (!key) + { + name = "dir"; + key = hiso_json_get_string_ex(pNode->pstChild, "dir"); + } + } + + class = hiso_json_get_string_ex(pNode->pstChild, "class"); + if (key && class) + { + grub_printf("%s: <%s>\n", name, key); + grub_printf("class: <%s>\n\n", class); + } + } + + return 0; +} + +static int hiperiso_plugin_custom_boot_entry(HISO_JSON *json, const char *isodisk) +{ + int type; + int len; + const char *key = NULL; + const char *cfg = NULL; + HISO_JSON *pNode = NULL; + custom_boot *tail = NULL; + custom_boot *node = NULL; + custom_boot *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_custom_boot_head) + { + for (node = g_custom_boot_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_custom_boot_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_custom_boot_image_file; + key = hiso_json_get_string_ex(pNode->pstChild, "file"); + if (!key) + { + key = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_custom_boot_directory; + } + + cfg = hiso_json_get_string_ex(pNode->pstChild, "vcfg"); + if (key && cfg) + { + node = grub_zalloc(sizeof(custom_boot)); + if (node) + { + node->type = type; + node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", key); + len = (int)grub_snprintf(node->cfg, sizeof(node->cfg), "%s", cfg); + + if (len >= 5 && grub_strncmp(node->cfg + len - 5, ".vcfg", 5) == 0) + { + if (g_custom_boot_head) + { + tail->next = node; + } + else + { + g_custom_boot_head = node; + } + tail = node; + } + else + { + grub_free(node); + } + } + } + } + + return 0; +} + +static int hiperiso_plugin_custom_boot_check(HISO_JSON *json, const char *isodisk) +{ + int type; + int len; + const char *key = NULL; + const char *cfg = NULL; + HISO_JSON *pNode = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + type = hiso_custom_boot_image_file; + key = hiso_json_get_string_ex(pNode->pstChild, "file"); + if (!key) + { + key = hiso_json_get_string_ex(pNode->pstChild, "dir"); + type = hiso_custom_boot_directory; + } + + cfg = hiso_json_get_string_ex(pNode->pstChild, "vcfg"); + len = (int)grub_strlen(cfg); + if (key && cfg) + { + if (len < 5 || grub_strncmp(cfg + len - 5, ".vcfg", 5)) + { + grub_printf("<%s> does not have \".vcfg\" suffix\n\n", cfg); + } + else + { + grub_printf("%s: <%s>\n", (type == hiso_custom_boot_directory) ? "dir" : "file", key); + grub_printf("vcfg: <%s>\n\n", cfg); + } + } + } + + return 0; +} + +static int hiperiso_plugin_conf_replace_entry(HISO_JSON *json, const char *isodisk) +{ + int img = 0; + const char *isof = NULL; + const char *orgf = NULL; + const char *newf = NULL; + HISO_JSON *pNode = NULL; + conf_replace *tail = NULL; + conf_replace *node = NULL; + conf_replace *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_conf_replace_head) + { + for (node = g_conf_replace_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_conf_replace_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + isof = hiso_json_get_string_ex(pNode->pstChild, "iso"); + orgf = hiso_json_get_string_ex(pNode->pstChild, "org"); + newf = hiso_json_get_string_ex(pNode->pstChild, "new"); + if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/') + { + node = grub_zalloc(sizeof(conf_replace)); + if (node) + { + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "img", &img)) + { + node->img = img; + } + + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", isof); + grub_snprintf(node->orgconf, sizeof(node->orgconf), "%s", orgf); + grub_snprintf(node->newconf, sizeof(node->newconf), "%s", newf); + + if (g_conf_replace_head) + { + tail->next = node; + } + else + { + g_conf_replace_head = node; + } + tail = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_conf_replace_check(HISO_JSON *json, const char *isodisk) +{ + int img = 0; + const char *isof = NULL; + const char *orgf = NULL; + const char *newf = NULL; + HISO_JSON *pNode = NULL; + grub_file_t file = NULL; + char cmd[256]; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + isof = hiso_json_get_string_ex(pNode->pstChild, "iso"); + orgf = hiso_json_get_string_ex(pNode->pstChild, "org"); + newf = hiso_json_get_string_ex(pNode->pstChild, "new"); + if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/') + { + if (hiperiso_check_file_exist("%s%s", isodisk, isof)) + { + grub_printf("iso:<%s> [OK]\n", isof); + + grub_snprintf(cmd, sizeof(cmd), "loopback vtisocheck \"%s%s\"", isodisk, isof); + grub_script_execute_sourcecode(cmd); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(vtisocheck)/%s", orgf); + if (file) + { + if (grub_strcmp(file->fs->name, "iso9660") == 0) + { + grub_printf("org:<%s> [OK]\n", orgf); + } + else + { + grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf); + } + grub_file_close(file); + } + else + { + grub_printf("org:<%s> [NOT Exist]\n", orgf); + } + + grub_script_execute_sourcecode("loopback -d vtisocheck"); + } + else if (grub_strchr(isof, '*')) + { + grub_printf("iso:<%s> [*]\n", isof); + grub_printf("org:<%s>\n", orgf); + } + else + { + grub_printf("iso:<%s> [NOT Exist]\n", isof); + grub_printf("org:<%s>\n", orgf); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", isodisk, newf); + if (file) + { + if (file->size > hiso_max_replace_file_size) + { + grub_printf("new:<%s> [Too Big %lu] \n", newf, (ulong)file->size); + } + else + { + grub_printf("new1:<%s> [OK]\n", newf); + } + grub_file_close(file); + } + else + { + grub_printf("new:<%s> [NOT Exist]\n", newf); + } + + if (JSON_SUCCESS == hiso_json_get_int(pNode->pstChild, "img", &img)) + { + grub_printf("img:<%d>\n", img); + } + + grub_printf("\n"); + } + } + + return 0; +} + +static int hiperiso_plugin_auto_memdisk_entry(HISO_JSON *json, const char *isodisk) +{ + HISO_JSON *pNode = NULL; + auto_memdisk *node = NULL; + auto_memdisk *next = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_auto_memdisk_head) + { + for (node = g_auto_memdisk_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_auto_memdisk_head = NULL; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_STRING) + { + node = grub_zalloc(sizeof(auto_memdisk)); + if (node) + { + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal); + + if (g_auto_memdisk_head) + { + node->next = g_auto_memdisk_head; + } + + g_auto_memdisk_head = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_auto_memdisk_check(HISO_JSON *json, const char *isodisk) +{ + HISO_JSON *pNode = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_STRING) + { + grub_printf("<%s> ", pNode->unData.pcStrVal); + + if (grub_strchr(pNode->unData.pcStrVal, '*')) + { + grub_printf(" [*]\n"); + } + else if (hiperiso_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal)) + { + grub_printf(" [OK]\n"); + } + else + { + grub_printf(" [NOT EXIST]\n"); + } + } + } + + return 0; +} + +static int hiperiso_plugin_image_list_entry(HISO_JSON *json, const char *isodisk) +{ + HISO_JSON *pNode = NULL; + image_list *node = NULL; + image_list *next = NULL; + image_list *tail = NULL; + + (void)isodisk; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + debug("Not array %d\n", json->enDataType); + return 0; + } + + if (g_image_list_head) + { + for (node = g_image_list_head; node; node = next) + { + next = node->next; + grub_free(node); + } + + g_image_list_head = NULL; + } + + if (grub_strncmp(json->pcName, "image_blacklist", 15) == 0) + { + g_plugin_image_list = HIPERISO_IMG_BLACK_LIST; + } + else + { + g_plugin_image_list = HIPERISO_IMG_WHITE_LIST; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_STRING) + { + node = grub_zalloc(sizeof(image_list)); + if (node) + { + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal); + + if (g_image_list_head) + { + tail->next = node; + } + else + { + g_image_list_head = node; + } + tail = node; + } + } + } + + return 0; +} + +static int hiperiso_plugin_image_list_check(HISO_JSON *json, const char *isodisk) +{ + HISO_JSON *pNode = NULL; + + if (json->enDataType != JSON_TYPE_ARRAY) + { + grub_printf("Not array %d\n", json->enDataType); + return 1; + } + + for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) + { + if (pNode->enDataType == JSON_TYPE_STRING) + { + grub_printf("<%s> ", pNode->unData.pcStrVal); + + if (grub_strchr(pNode->unData.pcStrVal, '*')) + { + grub_printf(" [*]\n"); + } + else if (hiperiso_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal)) + { + grub_printf(" [OK]\n"); + } + else + { + grub_printf(" [NOT EXIST]\n"); + } + } + } + + return 0; +} + +static plugin_entry g_plugin_entries[] = +{ + { "control", hiperiso_plugin_control_entry, hiperiso_plugin_control_check, 0 }, + { "theme", hiperiso_plugin_theme_entry, hiperiso_plugin_theme_check, 0 }, + { "auto_install", hiperiso_plugin_auto_install_entry, hiperiso_plugin_auto_install_check, 0 }, + { "persistence", hiperiso_plugin_persistence_entry, hiperiso_plugin_persistence_check, 0 }, + { "menu_alias", hiperiso_plugin_menualias_entry, hiperiso_plugin_menualias_check, 0 }, + { "menu_tip", hiperiso_plugin_menutip_entry, hiperiso_plugin_menutip_check, 0 }, + { "menu_class", hiperiso_plugin_menuclass_entry, hiperiso_plugin_menuclass_check, 0 }, + { "injection", hiperiso_plugin_injection_entry, hiperiso_plugin_injection_check, 0 }, + { "auto_memdisk", hiperiso_plugin_auto_memdisk_entry, hiperiso_plugin_auto_memdisk_check, 0 }, + { "image_list", hiperiso_plugin_image_list_entry, hiperiso_plugin_image_list_check, 0 }, + { "image_blacklist", hiperiso_plugin_image_list_entry, hiperiso_plugin_image_list_check, 0 }, + { "conf_replace", hiperiso_plugin_conf_replace_entry, hiperiso_plugin_conf_replace_check, 0 }, + { "dud", hiperiso_plugin_dud_entry, hiperiso_plugin_dud_check, 0 }, + { "password", hiperiso_plugin_pwd_entry, hiperiso_plugin_pwd_check, 0 }, + { "custom_boot", hiperiso_plugin_custom_boot_entry, hiperiso_plugin_custom_boot_check, 0 }, +}; + +static int hiperiso_parse_plugin_config(HISO_JSON *json, const char *isodisk) +{ + int i; + char key[128]; + HISO_JSON *cur = NULL; + + grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk); + + for (cur = json; cur; cur = cur->pstNext) + { + for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++) + { + grub_snprintf(key, sizeof(key), "%s_%s", g_plugin_entries[i].key, g_arch_mode_suffix); + if (g_plugin_entries[i].flag == 0 && grub_strcmp(key, cur->pcName) == 0) + { + debug("Plugin entry for %s\n", g_plugin_entries[i].key); + g_plugin_entries[i].entryfunc(cur, isodisk); + g_plugin_entries[i].flag = 1; + break; + } + } + } + + + for (cur = json; cur; cur = cur->pstNext) + { + for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++) + { + if (g_plugin_entries[i].flag == 0 && grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0) + { + debug("Plugin entry for %s\n", g_plugin_entries[i].key); + g_plugin_entries[i].entryfunc(cur, isodisk); + g_plugin_entries[i].flag = 1; + break; + } + } + } + + return 0; +} + +grub_err_t hiperiso_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 0; + int offset = 0; + char *buf = NULL; + grub_uint8_t *code = NULL; + grub_file_t file; + HISO_JSON *json = NULL; + + (void)ctxt; + (void)argc; + + grub_env_set("HISO_TIP_LEFT", "10%"); + grub_env_set("HISO_TIP_TOP", "80%+5"); + grub_env_set("HISO_TIP_COLOR", "blue"); + grub_env_set("HISO_TIP_ALIGN", "left"); + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/hiperiso/hiperiso.json", args[0]); + if (!file) + { + return GRUB_ERR_NONE; + } + + debug("json configuration file size %d\n", (int)file->size); + + buf = grub_malloc(file->size + 1); + if (!buf) + { + grub_file_close(file); + return 1; + } + + buf[file->size] = 0; + grub_file_read(file, buf, file->size); + grub_file_close(file); + + json = hiso_json_create(); + if (!json) + { + return 1; + } + + code = (grub_uint8_t *)buf; + if (code[0] == 0xef && code[1] == 0xbb && code[2] == 0xbf) + { + offset = 3; /* Skip UTF-8 BOM */ + } + else if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff)) + { + grub_env_set("HISO_PLUGIN_SYNTAX_ERROR", "1"); + grub_env_export("HISO_PLUGIN_SYNTAX_ERROR"); + + grub_env_set("HISO_PLUGIN_ENCODE_ERROR", "1"); + grub_env_export("HISO_PLUGIN_ENCODE_ERROR"); + + debug("Failed to parse json string %d\n", ret); + grub_free(buf); + return 1; + } + + ret = hiso_json_parse(json, buf + offset); + if (ret) + { + grub_env_set("HISO_PLUGIN_SYNTAX_ERROR", "1"); + grub_env_export("HISO_PLUGIN_SYNTAX_ERROR"); + + debug("Failed to parse json string %d\n", ret); + grub_free(buf); + return 1; + } + + hiperiso_parse_plugin_config(json->pstChild, args[0]); + + hiso_json_destroy(json); + + grub_free(buf); + + if (g_boot_pwd.type) + { + grub_printf("\n\n======= %s ======\n\n", grub_env_get("HISO_TEXT_MENU_VER")); + if (hiperiso_check_password(&g_boot_pwd, 3)) + { + grub_printf("\n!!! Password check failed, will exit after 5 seconds. !!!\n"); + grub_refresh(); + grub_sleep(5); + grub_exit(); + } + } + + if (g_menu_tip_head) + { + grub_env_set("HISO_MENU_TIP_ENABLE", "1"); + } + else + { + grub_env_unset("HISO_MENU_TIP_ENABLE"); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +void hiperiso_plugin_dump_injection(void) +{ + injection_config *node = NULL; + + for (node = g_injection_head; node; node = node->next) + { + grub_printf("\n%s:<%s>\n", (node->type == injection_type_file) ? "IMAGE" : "PARENT", node->isopath); + grub_printf("ARCHIVE:<%s>\n", node->archive); + } + + return; +} + + +void hiperiso_plugin_dump_auto_install(void) +{ + int i; + install_template *node = NULL; + + for (node = g_install_template_head; node; node = node->next) + { + grub_printf("\n%s:<%s> <%d>\n", + (node->type == auto_install_type_file) ? "IMAGE" : "PARENT", + node->isopath, node->templatenum); + for (i = 0; i < node->templatenum; i++) + { + grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path); + } + } + + return; +} + +void hiperiso_plugin_dump_persistence(void) +{ + int rc; + int i = 0; + persistence_config *node = NULL; + hiperiso_img_chunk_list chunk_list; + + for (node = g_persistence_head; node; node = node->next) + { + grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum); + + for (i = 0; i < node->backendnum; i++) + { + grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path); + rc = hiperiso_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list); + if (rc == 0) + { + grub_printf(" [ SUCCESS ]\n"); + grub_free(chunk_list.chunk); + } + else + { + grub_printf(" [ FAILED ]\n"); + } + } + } + + return; +} + +install_template * hiperiso_plugin_find_install_template(const char *isopath) +{ + int len; + install_template *node = NULL; + + if (!g_install_template_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + for (node = g_install_template_head; node; node = node->next) + { + if (node->type == auto_install_type_file) + { + if (node->pathlen == len && hiperiso_strcmp(node->isopath, isopath) == 0) + { + return node; + } + } + } + + for (node = g_install_template_head; node; node = node->next) + { + if (node->type == auto_install_type_parent) + { + if (node->pathlen < len && hiperiso_plugin_is_parent(node->isopath, node->pathlen, isopath)) + { + return node; + } + } + } + + return NULL; +} + +char * hiperiso_plugin_get_cur_install_template(const char *isopath, install_template **cur) +{ + install_template *node = NULL; + + if (cur) + { + *cur = NULL; + } + + node = hiperiso_plugin_find_install_template(isopath); + if ((!node) || (!node->templatepath)) + { + return NULL; + } + + if (node->cursel < 0 || node->cursel >= node->templatenum) + { + return NULL; + } + + if (cur) + { + *cur = node; + } + + return node->templatepath[node->cursel].path; +} + +persistence_config * hiperiso_plugin_find_persistent(const char *isopath) +{ + int len; + persistence_config *node = NULL; + + if (!g_persistence_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + for (node = g_persistence_head; node; node = node->next) + { + if ((len == node->pathlen) && (hiperiso_strcmp(node->isopath, isopath) == 0)) + { + return node; + } + } + + return NULL; +} + +int hiperiso_plugin_get_persistent_chunklist(const char *isopath, int index, hiperiso_img_chunk_list *chunk_list) +{ + int rc = 1; + int len = 0; + char *path = NULL; + grub_uint64_t start = 0; + grub_file_t file = NULL; + persistence_config *node = NULL; + + node = hiperiso_plugin_find_persistent(isopath); + if ((!node) || (!node->backendpath)) + { + return 1; + } + + if (index < 0) + { + index = node->cursel; + } + + if (index < 0 || index >= node->backendnum) + { + return 1; + } + + path = node->backendpath[index].path; + + if (node->backendpath[index].vlnk_add == 0) + { + len = grub_strlen(path); + if (len > 9 && grub_strncmp(path + len - 9, ".vlnk.dat", 9) == 0) + { + hiperiso_add_vlnk_file(NULL, path); + node->backendpath[index].vlnk_add = 1; + } + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", g_iso_disk_name, path); + if (!file) + { + debug("Failed to open file %s%s\n", g_iso_disk_name, path); + goto end; + } + + grub_memset(chunk_list, 0, sizeof(hiperiso_img_chunk_list)); + chunk_list->chunk = grub_malloc(sizeof(hiperiso_img_chunk) * DEFAULT_CHUNK_NUM); + if (NULL == chunk_list->chunk) + { + goto end; + } + + chunk_list->max_chunk = DEFAULT_CHUNK_NUM; + chunk_list->cur_chunk = 0; + + start = file->device->disk->partition->start; + hiperiso_get_block_list(file, chunk_list, start); + + if (0 != hiperiso_check_block_list(file, chunk_list, start, NULL, 0)) + { + grub_free(chunk_list->chunk); + chunk_list->chunk = NULL; + goto end; + } + + rc = 0; + +end: + if (file) + grub_file_close(file); + + return rc; +} + +const char * hiperiso_plugin_get_injection(const char *isopath) +{ + int len; + injection_config *node = NULL; + + if (!g_injection_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + for (node = g_injection_head; node; node = node->next) + { + if (node->type == injection_type_file) + { + if (node->pathlen == len && hiperiso_strcmp(node->isopath, isopath) == 0) + { + return node->archive; + } + } + } + + for (node = g_injection_head; node; node = node->next) + { + if (node->type == injection_type_parent) + { + if (node->pathlen < len && hiperiso_plugin_is_parent(node->isopath, node->pathlen, isopath)) + { + return node->archive; + } + } + } + + return NULL; +} + +const char * hiperiso_plugin_get_menu_alias(int type, const char *isopath) +{ + int len; + menu_alias *node = NULL; + + if (!g_menu_alias_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + for (node = g_menu_alias_head; node; node = node->next) + { + if (node->type == type && node->pathlen && + node->pathlen == len && hiperiso_strcmp(node->isopath, isopath) == 0) + { + return node->alias; + } + } + + return NULL; +} + +const menu_tip * hiperiso_plugin_get_menu_tip(int type, const char *isopath) +{ + int len; + menu_tip *node = NULL; + + if (!g_menu_tip_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + for (node = g_menu_tip_head; node; node = node->next) + { + if (node->type == type && node->pathlen && + node->pathlen == len && hiperiso_strcmp(node->isopath, isopath) == 0) + { + return node; + } + } + + return NULL; +} + +const char * hiperiso_plugin_get_menu_class(int type, const char *name, const char *path) +{ + int namelen; + int pathlen; + menu_class *node = NULL; + + if (!g_menu_class_head) + { + return NULL; + } + + namelen = (int)grub_strlen(name); + pathlen = (int)grub_strlen(path); + + if (hiso_class_image_file == type) + { + for (node = g_menu_class_head; node; node = node->next) + { + if (node->type != type) + { + continue; + } + + if (node->parent == 0) + { + if ((node->patlen < namelen) && grub_strstr(name, node->pattern)) + { + return node->class; + } + } + } + + for (node = g_menu_class_head; node; node = node->next) + { + if (node->type != type) + { + continue; + } + + if (node->parent) + { + if ((node->patlen < pathlen) && hiperiso_plugin_is_parent(node->pattern, node->patlen, path)) + { + return node->class; + } + } + } + } + else + { + for (node = g_menu_class_head; node; node = node->next) + { + if (node->type == type && node->patlen == namelen && grub_strncmp(name, node->pattern, namelen) == 0) + { + return node->class; + } + } + } + + return NULL; +} + +int hiperiso_plugin_add_custom_boot(const char *vcfgpath) +{ + int len; + custom_boot *node = NULL; + + node = grub_zalloc(sizeof(custom_boot)); + if (node) + { + node->type = hiso_custom_boot_image_file; + node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath); + grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath); + + /* .vcfg */ + len = node->pathlen - 5; + node->path[len] = 0; + node->pathlen = len; + + if (g_custom_boot_head) + { + node->next = g_custom_boot_head; + } + g_custom_boot_head = node; + } + + return 0; +} + +const char * hiperiso_plugin_get_custom_boot(const char *isopath) +{ + int i; + int len; + custom_boot *node = NULL; + + if (!g_custom_boot_head) + { + return NULL; + } + + len = (int)grub_strlen(isopath); + + for (node = g_custom_boot_head; node; node = node->next) + { + if (node->type == hiso_custom_boot_image_file) + { + if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0) + { + return node->cfg; + } + } + else + { + if (node->pathlen < len && isopath[node->pathlen] == '/' && + grub_strncmp(isopath, node->path, node->pathlen) == 0) + { + for (i = node->pathlen + 1; i < len; i++) + { + if (isopath[i] == '/') + { + break; + } + } + + if (i >= len) + { + return node->cfg; + } + } + } + } + + return NULL; +} + +grub_err_t hiperiso_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + custom_boot *node = NULL; + + (void)argc; + (void)ctxt; + (void)args; + + for (node = g_custom_boot_head; node; node = node->next) + { + grub_printf("[%s] <%s>:<%s>\n", (node->type == hiso_custom_boot_directory) ? "dir" : "file", + node->path, node->cfg); + } + + return 0; +} + +int hiperiso_plugin_check_memdisk(const char *isopath) +{ + int len; + auto_memdisk *node = NULL; + + if (!g_auto_memdisk_head) + { + return 0; + } + + len = (int)grub_strlen(isopath); + for (node = g_auto_memdisk_head; node; node = node->next) + { + if (node->pathlen == len && hiperiso_strncmp(node->isopath, isopath, len) == 0) + { + return 1; + } + } + + return 0; +} + +int hiperiso_plugin_get_image_list_index(int type, const char *name) +{ + int len; + int index = 1; + image_list *node = NULL; + + if (!g_image_list_head) + { + return 0; + } + + len = (int)grub_strlen(name); + + for (node = g_image_list_head; node; node = node->next, index++) + { + if (hiso_class_directory == type) + { + if (len < node->pathlen && hiperiso_strncmp(node->isopath, name, len) == 0) + { + return index; + } + } + else + { + if (len == node->pathlen && hiperiso_strncmp(node->isopath, name, len) == 0) + { + return index; + } + } + } + + return 0; +} + +int hiperiso_plugin_find_conf_replace(const char *iso, conf_replace *nodes[HISO_MAX_CONF_REPLACE]) +{ + int n = 0; + int len; + conf_replace *node; + + if (!g_conf_replace_head) + { + return 0; + } + + len = (int)grub_strlen(iso); + + for (node = g_conf_replace_head; node; node = node->next) + { + if (node->pathlen == len && hiperiso_strncmp(node->isopath, iso, len) == 0) + { + nodes[n++] = node; + if (n >= HISO_MAX_CONF_REPLACE) + { + return n; + } + } + } + + return n; +} + +dud * hiperiso_plugin_find_dud(const char *iso) +{ + int len; + dud *node; + + if (!g_dud_head) + { + return NULL; + } + + len = (int)grub_strlen(iso); + for (node = g_dud_head; node; node = node->next) + { + if (node->pathlen == len && hiperiso_strncmp(node->isopath, iso, len) == 0) + { + return node; + } + } + + return NULL; +} + +int hiperiso_plugin_load_dud(dud *node, const char *isopart) +{ + int i; + char *buf; + grub_file_t file; + + for (i = 0; i < node->dudnum; i++) + { + if (node->files[i].size > 0) + { + debug("file %d has been loaded\n", i); + continue; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path); + if (file) + { + buf = grub_malloc(file->size); + if (buf) + { + grub_file_read(file, buf, file->size); + node->files[i].size = (int)file->size; + node->files[i].buf = buf; + } + grub_file_close(file); + } + } + + return 0; +} + +static const hiso_password * hiperiso_plugin_get_password(const char *isopath) +{ + int i; + int len; + const char *pos = NULL; + menu_password *node = NULL; + + if (!isopath) + { + return NULL; + } + + if (g_pwd_head) + { + len = (int)grub_strlen(isopath); + for (node = g_pwd_head; node; node = node->next) + { + if (node->type == hiso_menu_pwd_file) + { + if (node->pathlen == len && hiperiso_strncmp(node->isopath, isopath, len) == 0) + { + return &(node->password); + } + } + } + + for (node = g_pwd_head; node; node = node->next) + { + if (node->type == hiso_menu_pwd_parent) + { + if (node->pathlen < len && hiperiso_plugin_is_parent(node->isopath, node->pathlen, isopath)) + { + return &(node->password); + } + } + } + } + + while (*isopath) + { + if (*isopath == '.') + { + pos = isopath; + } + isopath++; + } + + if (pos) + { + for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++) + { + if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i])) + { + return g_file_type_pwd + i; + } + } + } + + return NULL; +} + +grub_err_t hiperiso_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret; + const hiso_password *pwd = NULL; + + (void)ctxt; + (void)argc; + + pwd = hiperiso_plugin_get_password(args[0]); + if (pwd) + { + if (0 == hiperiso_check_password(pwd, 1)) + { + ret = 1; + } + else + { + ret = 0; + } + } + else + { + ret = 1; + } + + grub_errno = 0; + return ret; +} + +grub_err_t hiperiso_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + int ret = 0; + char *buf = NULL; + char key[128]; + grub_file_t file; + HISO_JSON *node = NULL; + HISO_JSON *json = NULL; + + (void)ctxt; + + if (argc != 3) + { + return 0; + } + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/hiperiso/hiperiso.json", args[0]); + if (!file) + { + grub_printf("Plugin json file /hiperiso/hiperiso.json does NOT exist.\n"); + grub_printf("Attention: directory name and filename are both case-sensitive.\n"); + goto end; + } + + buf = grub_malloc(file->size + 1); + if (!buf) + { + grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1)); + goto end; + } + + buf[file->size] = 0; + grub_file_read(file, buf, file->size); + + json = hiso_json_create(); + if (!json) + { + grub_printf("Failed to create json\n"); + goto end; + } + + ret = hiso_json_parse(json, buf); + if (ret) + { + grub_printf("Syntax error detected in hiperiso.json, please check it.\n"); + goto end; + } + + grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix); + for (node = json->pstChild; node; node = node->pstNext) + { + if (grub_strcmp(node->pcName, key) == 0) + { + break; + } + } + + if (!node) + { + for (node = json->pstChild; node; node = node->pstNext) + { + if (grub_strcmp(node->pcName, args[1]) == 0) + { + break; + } + } + + if (!node) + { + grub_printf("%s is NOT found in hiperiso.json\n", args[1]); + goto end; + } + } + + for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++) + { + if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0) + { + if (g_plugin_entries[i].checkfunc) + { + ret = g_plugin_entries[i].checkfunc(node, args[2]); + } + break; + } + } + +end: + check_free(file, grub_file_close); + check_free(json, hiso_json_destroy); + grub_check_free(buf); + + return 0; +} + +grub_err_t hiperiso_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int pos = 0; + int bufsize = 0; + char *name = NULL; + char *buf = NULL; + theme_list *node = NULL; + + (void)argc; + (void)args; + (void)ctxt; + + if (g_theme_single_file[0]) + { + return 0; + } + + if (g_theme_num < 2) + { + return 0; + } + + bufsize = (g_theme_num + 1) * 1024; + buf = grub_malloc(bufsize); + if (!buf) + { + return 0; + } + + for (node = g_theme_head; node; node = node->next) + { + name = grub_strstr(node->theme.path, ")/"); + if (name) + { + name++; + } + else + { + name = node->theme.path; + } + + pos += grub_snprintf(buf + pos, bufsize - pos, + "menuentry \"%s\" --class=debug_theme_item --class=debug_theme_select --class=F5tool {\n" + "vt_set_theme_path \"%s\"\n" + "}\n", + name, node->theme.path); + } + + pos += grub_snprintf(buf + pos, bufsize - pos, + "menuentry \"$VTLANG_RETURN_PREVIOUS\" --class=hisoret HISO_RET {\n" + "echo 'Return ...'\n" + "}\n"); + + grub_script_execute_sourcecode(buf); + grub_free(buf); + + return 0; +} + +extern char g_hiperiso_theme_path[256]; + +grub_err_t hiperiso_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t i = 0; + grub_uint32_t mod = 0; + grub_uint32_t theme_num = 0; + theme_list *node = g_theme_head; + struct grub_datetime datetime; + struct grub_video_mode_info info; + char buf[64]; + char **pThemePath = NULL; + + (void)argc; + (void)args; + (void)ctxt; + + if (g_theme_single_file[0]) + { + debug("single theme %s\n", g_theme_single_file); + grub_env_set("theme", g_theme_single_file); + goto end; + } + + debug("g_theme_num = %d\n", g_theme_num); + + if (g_theme_num == 0) + { + goto end; + } + + if (g_theme_id > 0 && g_theme_id <= g_theme_num) + { + for (i = 0; i < (grub_uint32_t)(g_theme_id - 1) && node; i++) + { + node = node->next; + } + + grub_env_set("theme", node->theme.path); + goto end; + } + + pThemePath = (char **)grub_zalloc(sizeof(char *) * g_theme_num); + if (!pThemePath) + { + goto end; + } + + if (g_theme_res_fit) + { + if (grub_video_get_info(&info) == GRUB_ERR_NONE) + { + debug("get video info success %ux%u\n", info.width, info.height); + grub_snprintf(buf, sizeof(buf), "%ux%u", info.width, info.height); + for (node = g_theme_head; node; node = node->next) + { + if (grub_strstr(node->theme.path, buf)) + { + pThemePath[theme_num++] = node->theme.path; + } + } + } + } + + if (theme_num == 0) + { + for (node = g_theme_head; node; node = node->next) + { + pThemePath[theme_num++] = node->theme.path; + } + } + + if (theme_num == 1) + { + mod = 0; + debug("Only 1 theme match, no need to random.\n"); + } + else + { + grub_memset(&datetime, 0, sizeof(datetime)); + grub_get_datetime(&datetime); + + if (g_theme_random == hiso_theme_random_boot_second) + { + grub_divmod32((grub_uint32_t)datetime.second, theme_num, &mod); + } + else if (g_theme_random == hiso_theme_random_boot_day) + { + grub_divmod32((grub_uint32_t)datetime.day, theme_num, &mod); + } + else if (g_theme_random == hiso_theme_random_boot_month) + { + grub_divmod32((grub_uint32_t)datetime.month, theme_num, &mod); + } + + debug("%04d/%02d/%02d %02d:%02d:%02d theme_num:%d mod:%d\n", + datetime.year, datetime.month, datetime.day, + datetime.hour, datetime.minute, datetime.second, + theme_num, mod); + } + + if (argc > 0 && grub_strcmp(args[0], "switch") == 0) + { + grub_snprintf(g_hiperiso_theme_path, sizeof(g_hiperiso_theme_path), "%s", pThemePath[mod]); + } + else + { + debug("random theme %s\n", pThemePath[mod]); + grub_env_set("theme", pThemePath[mod]); + } + g_hiperiso_menu_refresh = 1; + +end: + + grub_check_free(pThemePath); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)argc; + (void)ctxt; + + if (argc == 0) + { + g_hiperiso_theme_path[0] = 0; + } + else + { + grub_snprintf(g_hiperiso_theme_path, sizeof(g_hiperiso_theme_path), "%s", args[0]); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +const char *hiperiso_get_vmenu_title(const char *vMenu) +{ + return hiso_json_get_string_ex(g_menu_lang_json->pstChild, vMenu); +} + +int hiperiso_plugin_load_menu_lang(int init, const char *lang) +{ + int ret = 1; + grub_file_t file = NULL; + char *buf = NULL; + + if (grub_strcmp(lang, g_cur_menu_language) == 0) + { + debug("Same menu lang %s\n", lang); + return 0; + } + grub_snprintf(g_cur_menu_language, sizeof(g_cur_menu_language), "%s", lang); + + debug("Load menu lang %s\n", g_cur_menu_language); + + if (g_menu_lang_json) + { + hiso_json_destroy(g_menu_lang_json); + g_menu_lang_json = NULL; + } + + g_menu_lang_json = hiso_json_create(); + if (!g_menu_lang_json) + { + goto end; + } + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(vt_menu_tarfs)/menu/%s.json", lang); + if (!file) + { + goto end; + } + + buf = grub_malloc(file->size + 1); + if (!buf) + { + grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1)); + goto end; + } + + buf[file->size] = 0; + grub_file_read(file, buf, file->size); + + hiso_json_parse(g_menu_lang_json, buf); + + if (g_default_menu_mode == 0) + { + grub_snprintf(g_hiperiso_hotkey_tip, sizeof(g_hiperiso_hotkey_tip), "%s", hiperiso_get_vmenu_title("VTLANG_STR_HOTKEY_TREE")); + } + else + { + grub_snprintf(g_hiperiso_hotkey_tip, sizeof(g_hiperiso_hotkey_tip), "%s", hiperiso_get_vmenu_title("VTLANG_STR_HOTKEY_LIST")); + } + + if (init == 0) + { + hiperiso_menu_push_key(GRUB_TERM_ESC); + hiperiso_menu_push_key(GRUB_TERM_ESC); + g_hiperiso_menu_refresh = 1; + } + ret = 0; + +end: + + check_free(file, grub_file_close); + grub_check_free(buf); + + return ret; +} + +grub_err_t hiperiso_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + if (argc > 0) + { + grub_env_set(args[0], g_cur_menu_language); + } + else + { + grub_printf("%s\n", g_cur_menu_language); + grub_printf("%s\n", g_hiperiso_hotkey_tip); + grub_refresh(); + } + + HIPERISO_CMD_RETURN(0); +} + +grub_err_t hiperiso_cmd_push_menulang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)argc; + (void)ctxt; + + if (g_push_menu_language[0] == 0) + { + grub_memcpy(g_push_menu_language, g_cur_menu_language, sizeof(g_push_menu_language)); + hiperiso_plugin_load_menu_lang(0, args[0]); + } + + HIPERISO_CMD_RETURN(0); +} + +grub_err_t hiperiso_cmd_pop_menulang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)argc; + (void)ctxt; + (void)args; + + if (g_push_menu_language[0]) + { + hiperiso_plugin_load_menu_lang(0, g_push_menu_language); + g_push_menu_language[0] = 0; + } + + HIPERISO_CMD_RETURN(0); +} + + diff --git a/src/grub2/hiperiso_unix.c b/src/grub2/hiperiso_unix.c new file mode 100644 index 0000000..e8209be --- /dev/null +++ b/src/grub2/hiperiso_unix.c @@ -0,0 +1,1245 @@ +/****************************************************************************** + * hiperiso_unix.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +char g_ko_mod_path[256]; +int g_conf_new_len = 0; +char *g_conf_new_data = NULL; + +int g_mod_new_len = 0; +char *g_mod_new_data = NULL; + +int g_mod_search_magic = 0; +int g_unix_vlnk_boot = 0; + +int g_ko_fillmap_len = 0; +char *g_ko_fillmap_data = NULL; + +grub_uint64_t g_mod_override_offset = 0; +grub_uint64_t g_conf_override_offset = 0; + +static int hiperiso_get_file_override(const char *filename, grub_uint64_t *offset) +{ + grub_file_t file; + + *offset = 0; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(loop)%s", filename); + if (!file) + { + return 1; + } + + *offset = grub_iso9660_get_last_file_dirent_pos(file) + 2; + + grub_file_close(file); + + return 0; +} + +static grub_uint32_t hiperiso_unix_get_override_chunk_count(void) +{ + grub_uint32_t count = 0; + + if (g_conf_new_len > 0) + { + count++; + } + + if (g_mod_new_len > 0) + { + count++; + } + + if (g_ko_fillmap_len > 0) + { + count += (g_ko_fillmap_len / 512); + if ((g_ko_fillmap_len % 512) > 0) + { + count++; + } + } + + return count; +} + +static grub_uint32_t hiperiso_unix_get_virt_chunk_count(void) +{ + grub_uint32_t count = 0; + + if (g_conf_new_len > 0) + { + count++; + } + + if (g_mod_new_len > 0) + { + count++; + } + + return count; +} +static grub_uint32_t hiperiso_unix_get_virt_chunk_size(void) +{ + grub_uint32_t size; + + size = sizeof(hiperiso_virt_chunk) * hiperiso_unix_get_virt_chunk_count(); + + if (g_conf_new_len > 0) + { + size += hiperiso_align_2k(g_conf_new_len); + } + + if (g_mod_new_len > 0) + { + size += hiperiso_align_2k(g_mod_new_len); + } + + return size; +} + +static void hiperiso_unix_fill_map_data(hiperiso_chain_head *chain, struct g_hiperiso_map *map) +{ + grub_uint32_t i; + hiperiso_img_chunk *chunk = NULL; + + debug("Fill unix map data: <%llu> <%u> %p\n", + (unsigned long long)chain->os_param.hiso_disk_size, g_img_chunk_list.cur_chunk, map); + + map->magic1[0] = map->magic2[0] = HIPERISO_UNIX_SEG_MAGIC0; + map->magic1[1] = map->magic2[1] = HIPERISO_UNIX_SEG_MAGIC1; + map->magic1[2] = map->magic2[2] = HIPERISO_UNIX_SEG_MAGIC2; + map->magic1[3] = map->magic2[3] = HIPERISO_UNIX_SEG_MAGIC3; + + map->disksize = chain->os_param.hiso_disk_size; + grub_memcpy(map->diskuuid, chain->os_param.hiso_disk_guid, 16); + + map->segnum = g_img_chunk_list.cur_chunk; + if (g_img_chunk_list.cur_chunk > HIPERISO_UNIX_MAX_SEGNUM) + { + debug("####[FAIL] Too many segments for the ISO file %u\n", g_img_chunk_list.cur_chunk); + map->segnum = HIPERISO_UNIX_MAX_SEGNUM; + } + + for (i = 0; i < (grub_uint32_t)(map->segnum); i++) + { + chunk = g_img_chunk_list.chunk + i; + map->seglist[i].seg_start_bytes = chunk->disk_start_sector * 512ULL; + map->seglist[i].seg_end_bytes = (chunk->disk_end_sector + 1) * 512ULL; + } +} + +static void hiperiso_unix_fill_override_data( grub_uint64_t isosize, hiperiso_chain_head *chain) +{ + int i; + int left; + char *data = NULL; + grub_uint64_t offset; + grub_uint64_t sector; + hiperiso_override_chunk *cur; + hiperiso_iso9660_override *dirent; + + sector = (isosize + 2047) / 2048; + + cur = (hiperiso_override_chunk *)((char *)chain + chain->override_chunk_offset); + + if (g_conf_new_len > 0) + { + /* loader.conf */ + cur->img_offset = g_conf_override_offset; + cur->override_size = sizeof(hiperiso_iso9660_override); + dirent = (hiperiso_iso9660_override *)cur->override_data; + dirent->first_sector = (grub_uint32_t)sector; + dirent->size = (grub_uint32_t)g_conf_new_len; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + sector += (dirent->size + 2047) / 2048; + cur++; + } + + if (g_mod_new_len > 0) + { + /* mod.ko */ + cur->img_offset = g_mod_override_offset; + cur->override_size = sizeof(hiperiso_iso9660_override); + dirent = (hiperiso_iso9660_override *)cur->override_data; + dirent->first_sector = (grub_uint32_t)sector; + dirent->size = (grub_uint32_t)g_mod_new_len; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + sector += (dirent->size + 2047) / 2048; + cur++; + } + + if (g_ko_fillmap_len > 0) + { + data = g_ko_fillmap_data; + offset = g_mod_override_offset; + + hiperiso_unix_fill_map_data(chain, (struct g_hiperiso_map *)data); + + for (i = 0; i < g_ko_fillmap_len / 512; i++) + { + cur->img_offset = offset; + cur->override_size = 512; + grub_memcpy(cur->override_data, data, 512); + + offset += 512; + data += 512; + cur++; + } + + left = (g_ko_fillmap_len % 512); + if (left > 0) + { + cur->img_offset = offset; + cur->override_size = left; + grub_memcpy(cur->override_data, data, left); + + offset += left; + cur++; + } + } + + return; +} + +static void hiperiso_unix_fill_virt_data( grub_uint64_t isosize, hiperiso_chain_head *chain) +{ + grub_uint64_t sector; + grub_uint32_t offset; + grub_uint32_t data_secs; + char *override; + hiperiso_virt_chunk *cur; + + override = (char *)chain + chain->virt_chunk_offset; + cur = (hiperiso_virt_chunk *)override; + + sector = (isosize + 2047) / 2048; + offset = 2 * sizeof(hiperiso_virt_chunk); + + if (g_conf_new_len > 0) + { + hiperiso_unix_fill_virt(g_conf_new_data, g_conf_new_len); + } + + if (g_mod_new_len > 0) + { + if (g_mod_search_magic > 0) + { + hiperiso_unix_fill_map_data(chain, (struct g_hiperiso_map *)(g_mod_new_data + g_mod_search_magic)); + } + + hiperiso_unix_fill_virt(g_mod_new_data, g_mod_new_len); + } + + return; +} + +static int hiperiso_freebsd_append_conf(char *buf, const char *isopath, const char *alias) +{ + int pos = 0; + grub_uint32_t i; + grub_disk_t disk; + grub_file_t isofile; + char uuid[64] = {0}; + const char *val = NULL; + hiperiso_img_chunk *chunk; + grub_uint8_t disk_sig[4]; + grub_uint8_t disk_guid[16]; + + debug("hiperiso_freebsd_append_conf %s\n", isopath); + + isofile = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", isopath); + if (!isofile) + { + return 1; + } + + hiso_ssprintf(buf, pos, "hiperiso_load=\"%s\"\n", "YES"); + hiso_ssprintf(buf, pos, "hiperiso_name=\"%s\"\n", g_ko_mod_path); + + if (alias) + { + hiso_ssprintf(buf, pos, "hint.hiperiso.0.alias=\"%s\"\n", alias); + } + + if (g_unix_vlnk_boot) + { + hiso_ssprintf(buf, pos, "hint.hiperiso.0.vlnk=%d\n", 1); + } + + val = hiperiso_get_env("HISO_UNIX_REMOUNT"); + if (val && val[0] == '1' && val[1] == 0) + { + hiso_ssprintf(buf, pos, "hint.hiperiso.0.remount=%d\n", 1); + } + + if (g_mod_search_magic) + { + debug("hint.hiperiso NO need\n"); + goto out; + } + + debug("Fill hint.hiperiso info\n"); + + disk = isofile->device->disk; + + hiperiso_get_disk_guid(isofile->name, disk_guid, disk_sig); + + for (i = 0; i < 16; i++) + { + grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]); + } + + hiso_ssprintf(buf, pos, "hint.hiperiso.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size))); + hiso_ssprintf(buf, pos, "hint.hiperiso.0.diskuuid=\"%s\"\n", uuid); + hiso_ssprintf(buf, pos, "hint.hiperiso.0.disksignature=%02x%02x%02x%02x\n", disk_sig[0], disk_sig[1], disk_sig[2], disk_sig[3]); + hiso_ssprintf(buf, pos, "hint.hiperiso.0.segnum=%u\n", g_img_chunk_list.cur_chunk); + + for (i = 0; i < g_img_chunk_list.cur_chunk; i++) + { + chunk = g_img_chunk_list.chunk + i; + hiso_ssprintf(buf, pos, "hint.hiperiso.%u.seg=\"0x%llx@0x%llx\"\n", + i, (ulonglong)(chunk->disk_start_sector * 512), + (ulonglong)((chunk->disk_end_sector + 1) * 512)); + } + +out: + grub_file_close(isofile); + return pos; +} + +static int hiperiso_dragonfly_append_conf(char *buf, const char *isopath) +{ + int pos = 0; + + debug("hiperiso_dragonfly_append_conf %s\n", isopath); + + hiso_ssprintf(buf, pos, "tmpfs_load=\"%s\"\n", "YES"); + hiso_ssprintf(buf, pos, "dm_target_linear_load=\"%s\"\n", "YES"); + hiso_ssprintf(buf, pos, "initrd.img_load=\"%s\"\n", "YES"); + hiso_ssprintf(buf, pos, "initrd.img_type=\"%s\"\n", "md_image"); + hiso_ssprintf(buf, pos, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0"); + + return pos; +} + +grub_err_t hiperiso_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + g_unix_vlnk_boot = 0; + g_mod_search_magic = 0; + g_conf_new_len = 0; + g_mod_new_len = 0; + g_mod_override_offset = 0; + g_conf_override_offset = 0; + g_ko_fillmap_len = 0; + + check_free(g_mod_new_data, grub_free); + check_free(g_conf_new_data, grub_free); + check_free(g_ko_fillmap_data, grub_free); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_check_vlnk(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file; + + (void)ctxt; + + if (argc != 1) + { + return 1; + } + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (file) + { + g_unix_vlnk_boot = file->vlnk; + grub_file_close(file); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file; + const char *ver = NULL; + char *buf = NULL; + HISO_JSON *json = NULL; + + (void)ctxt; + (void)argc; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + debug("Failed to open file %s\n", args[0]); + return 1; + } + + buf = grub_malloc(file->size + 2); + if (!buf) + { + grub_file_close(file); + return 0; + } + grub_file_read(file, buf, file->size); + buf[file->size] = 0; + + json = hiso_json_create(); + if (!json) + { + goto end; + } + + if (hiso_json_parse(json, buf)) + { + goto end; + } + + ver = hiso_json_get_string_ex(json->pstChild, "Version"); + if (ver) + { + debug("NAS version:<%s>\n", ver); + if (grub_strncmp(ver, "TrueNAS-", 8) == 0) + { + ver += 8; + } + hiperiso_set_env(args[1], ver); + } + else + { + debug("NAS version:<%s>\n", "NOT FOUND"); + grub_env_unset(args[1]); + } + +end: + grub_check_free(buf); + check_free(json, hiso_json_destroy); + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file; + char *buf; + char *start = NULL; + char *nextline = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]); + if (!file) + { + debug("Failed to open file %s\n", args[0]); + return 1; + } + + buf = grub_zalloc(file->size + 2); + if (!buf) + { + grub_file_close(file); + return 0; + } + grub_file_read(file, buf, file->size); + + for (start = buf; start; start = nextline) + { + if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0) + { + nextline = start; + while (*nextline && *nextline != '\r' && *nextline != '\n') + { + nextline++; + } + + *nextline = 0; + break; + } + nextline = hiperiso_get_line(start); + } + + if (start) + { + debug("freebsd version:<%s>\n", start); + hiperiso_set_env(args[1], start); + } + else + { + debug("freebsd version:<%s>\n", "NOT FOUND"); + grub_env_unset(args[1]); + } + + grub_free(buf); + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int j; + int k; + grub_elf_t elf = NULL; + grub_off_t offset = 0; + grub_uint32_t len = 0; + char *str = NULL; + char *data = NULL; + void *hdr = NULL; + char ver[64] = {0}; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 3) + { + debug("Invalid argc %d\n", argc); + return 1; + } + + data = grub_zalloc(8192); + if (!data) + { + goto out; + } + + elf = grub_elf_open(args[0], GRUB_FILE_TYPE_LINUX_INITRD); + if (!elf) + { + debug("Failed to open file %s\n", args[0]); + goto out; + } + + if (args[1][0] == '6') + { + Elf64_Ehdr *e = &(elf->ehdr.ehdr64); + Elf64_Shdr *h; + Elf64_Shdr *s; + Elf64_Shdr *t; + Elf64_Half i; + + h = hdr = grub_zalloc(e->e_shnum * e->e_shentsize); + if (!h) + { + goto out; + } + + debug("read section header %u %u %u\n", e->e_shnum, e->e_shentsize, e->e_shstrndx); + grub_file_seek(elf->file, e->e_shoff); + grub_file_read(elf->file, h, e->e_shnum * e->e_shentsize); + + s = (Elf64_Shdr *)((char *)h + e->e_shstrndx * e->e_shentsize); + str = grub_malloc(s->sh_size + 1); + if (!str) + { + goto out; + } + str[s->sh_size] = 0; + + debug("read string table %u %u\n", (grub_uint32_t)s->sh_offset, (grub_uint32_t)s->sh_size); + grub_file_seek(elf->file, s->sh_offset); + grub_file_read(elf->file, str, s->sh_size); + + for (t = h, i = 0; i < e->e_shnum; i++) + { + if (grub_strcmp(str + t->sh_name, ".data") == 0) + { + offset = t->sh_offset; + len = t->sh_size; + debug("find .data section at %u %u\n", (grub_uint32_t)offset, len); + break; + } + t = (Elf64_Shdr *)((char *)t + e->e_shentsize); + } + } + else + { + Elf32_Ehdr *e = &(elf->ehdr.ehdr32); + Elf32_Shdr *h; + Elf32_Shdr *s; + Elf32_Shdr *t; + Elf32_Half i; + + h = hdr = grub_zalloc(e->e_shnum * e->e_shentsize); + if (!h) + { + goto out; + } + + debug("read section header %u %u %u\n", e->e_shnum, e->e_shentsize, e->e_shstrndx); + grub_file_seek(elf->file, e->e_shoff); + grub_file_read(elf->file, h, e->e_shnum * e->e_shentsize); + + s = (Elf32_Shdr *)((char *)h + e->e_shstrndx * e->e_shentsize); + str = grub_malloc(s->sh_size + 1); + if (!str) + { + goto out; + } + str[s->sh_size] = 0; + + debug("read string table %u %u\n", (grub_uint32_t)s->sh_offset, (grub_uint32_t)s->sh_size); + grub_file_seek(elf->file, s->sh_offset); + grub_file_read(elf->file, str, s->sh_size); + + for (t = h, i = 0; i < e->e_shnum; i++) + { + if (grub_strcmp(str + t->sh_name, ".data") == 0) + { + offset = t->sh_offset; + len = t->sh_size; + debug("find .data section at %u %u\n", (grub_uint32_t)offset, len); + break; + } + t = (Elf32_Shdr *)((char *)t + e->e_shentsize); + } + } + + if (offset == 0 || len == 0) + { + debug(".data section not found %s\n", args[0]); + goto out; + } + + grub_file_seek(elf->file, offset + len - 8192); + grub_file_read(elf->file, data, 8192); + + for (j = 0; j < 8192 - 12; j++) + { + if (grub_strncmp(data + j, "@(#)FreeBSD ", 12) == 0) + { + for (k = j + 12; k < 8192; k++) + { + if (0 == grub_isdigit(data[k]) && data[k] != '.') + { + data[k] = 0; + break; + } + } + + grub_snprintf(ver, sizeof(ver), "%s", data + j + 12); + break; + } + } + + if (ver[0]) + { + k = (int)grub_strtoul(ver, NULL, 10); + debug("freebsd version:<%s> <%d.x>\n", ver, k); + grub_snprintf(ver, sizeof(ver), "%d.x", k); + hiperiso_set_env(args[2], ver); + } + else + { + debug("freebsd version:<%s>\n", "NOT FOUND"); + } + +out: + grub_check_free(str); + grub_check_free(hdr); + grub_check_free(data); + check_free(elf, grub_elf_close); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_replace_grub_conf(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int len = 0; + grub_uint32_t i; + char *data; + char *pos; + const char *val = NULL; + grub_uint64_t offset; + grub_file_t file; + char extcfg[512]; + const char *confile = NULL; + const char * loader_conf[] = + { + "/boot/grub/grub.cfg", + }; + + (void)ctxt; + + if (argc != 1 && argc != 2) + { + debug("Replace conf invalid argc %d\n", argc); + return 1; + } + + for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++) + { + if (hiperiso_get_file_override(loader_conf[i], &offset) == 0) + { + confile = loader_conf[i]; + g_conf_override_offset = offset; + break; + } + } + + if (confile == NULL) + { + debug("Can't find grub.cfg file from %u locations\n", i); + return 1; + } + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile); + if (!file) + { + debug("Failed to open %s \n", confile); + return 1; + } + + debug("old grub2 conf file size:%d\n", (int)file->size); + + data = grub_malloc(HISO_MAX_SCRIPT_BUF); + if (!data) + { + grub_file_close(file); + return 1; + } + + grub_file_read(file, data, file->size); + grub_file_close(file); + + g_conf_new_data = data; + g_conf_new_len = (int)file->size; + + pos = grub_strstr(data, "kfreebsd /boot/kernel/kernel"); + if (pos) + { + pos += grub_strlen("kfreebsd /boot/kernel/kernel"); + if (grub_strncmp(pos, ".gz", 3) == 0) + { + pos += 3; + } + + if (argc == 2) + { + hiso_ssprintf(extcfg, len, ";kfreebsd_module_elf %s; set kFreeBSD.hint.hiperiso.0.alias=\"%s\"", args[0], args[1]); + } + else + { + hiso_ssprintf(extcfg, len, ";kfreebsd_module_elf %s", args[0]); + } + + if (g_unix_vlnk_boot) + { + hiso_ssprintf(extcfg, len, ";set kFreeBSD.hint.hiperiso.0.vlnk=%d", 1); + } + + val = hiperiso_get_env("HISO_UNIX_REMOUNT"); + if (val && val[0] == '1' && val[1] == 0) + { + hiso_ssprintf(extcfg, len, ";set kFreeBSD.hint.hiperiso.0.remount=%d", 1); + } + + grub_memmove(pos + len, pos, (int)(file->size - (pos - data))); + grub_memcpy(pos, extcfg, len); + g_conf_new_len += len; + } + else + { + debug("no kfreebsd found\n"); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t i; + char *data; + grub_uint64_t offset; + grub_file_t file; + const char *confile = NULL; + const char * loader_conf[] = + { + "/boot/loader.conf", + "/boot/defaults/loader.conf", + }; + + (void)ctxt; + + if (argc != 2 && argc != 3) + { + debug("Replace conf invalid argc %d\n", argc); + return 1; + } + + for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++) + { + if (hiperiso_get_file_override(loader_conf[i], &offset) == 0) + { + confile = loader_conf[i]; + g_conf_override_offset = offset; + break; + } + } + + if (confile == NULL) + { + debug("Can't find loader.conf file from %u locations\n", i); + return 1; + } + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile); + if (!file) + { + debug("Failed to open %s \n", confile); + return 1; + } + + debug("old conf file <%s> size:%d\n", confile, (int)file->size); + + data = grub_malloc(HISO_MAX_SCRIPT_BUF); + if (!data) + { + grub_file_close(file); + return 1; + } + + grub_file_read(file, data, file->size); + grub_file_close(file); + + g_conf_new_data = data; + g_conf_new_len = (int)file->size; + + if (grub_strcmp(args[0], "FreeBSD") == 0) + { + g_conf_new_len += hiperiso_freebsd_append_conf(data + file->size, args[1], (argc > 2) ? args[2] : NULL); + } + else if (grub_strcmp(args[0], "DragonFly") == 0) + { + g_conf_new_len += hiperiso_dragonfly_append_conf(data + file->size, args[1]); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static int hiperiso_unix_search_magic(char *data, int len) +{ + int i; + grub_uint32_t *magic = NULL; + + for (i = 0; i < len; i += 4096) + { + magic = (grub_uint32_t *)(data + i); + if (magic[0] == HIPERISO_UNIX_SEG_MAGIC0 && magic[1] == HIPERISO_UNIX_SEG_MAGIC1 && + magic[2] == HIPERISO_UNIX_SEG_MAGIC2 && magic[3] == HIPERISO_UNIX_SEG_MAGIC3) + { + debug("unix find search magic at 0x%x loop:%d\n", i, (i >> 12)); + g_mod_search_magic = i; + return 0; + } + } + + debug("unix can not find search magic\n"); + return 1; +} + +grub_err_t hiperiso_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *data; + grub_uint64_t offset; + grub_file_t file; + + (void)ctxt; + + if (argc != 2) + { + debug("Replace ko invalid argc %d\n", argc); + return 1; + } + + debug("replace ko %s\n", args[0]); + + if (hiperiso_get_file_override(args[0], &offset) == 0) + { + grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]); + g_mod_override_offset = offset; + } + else + { + debug("Can't find replace ko file from %s\n", args[0]); + return 1; + } + + file = hiperiso_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]); + if (!file) + { + debug("Failed to open %s \n", args[1]); + return 1; + } + + debug("new ko file size:%d\n", (int)file->size); + + data = grub_malloc(file->size); + if (!data) + { + debug("Failed to alloc memory for new ko %d\n", (int)file->size); + grub_file_close(file); + return 1; + } + + grub_file_read(file, data, file->size); + grub_file_close(file); + + g_mod_new_data = data; + g_mod_new_len = (int)file->size; + + hiperiso_unix_search_magic(g_mod_new_data, g_mod_new_len); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + grub_file_t file; + grub_uint32_t magic[4]; + grub_uint32_t len; + + (void)ctxt; + + if (argc != 1) + { + debug("Fillmap ko invalid argc %d\n", argc); + return 1; + } + + debug("Fillmap ko %s\n", args[0]); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(loop)%s", args[0]); + if (file) + { + grub_file_read(file, magic, 4); /* read for trigger */ + g_mod_override_offset = grub_iso9660_get_last_read_pos(file); + } + else + { + debug("Can't find replace ko file from %s\n", args[0]); + return 1; + } + + for (i = 0; i < (int)(file->size); i += 65536) + { + magic[0] = 0; + grub_file_seek(file, i); + grub_file_read(file, magic, sizeof(magic)); + + if (magic[0] == HIPERISO_UNIX_SEG_MAGIC0 && magic[1] == HIPERISO_UNIX_SEG_MAGIC1 && + magic[2] == HIPERISO_UNIX_SEG_MAGIC2 && magic[3] == HIPERISO_UNIX_SEG_MAGIC3) + { + debug("unix find search magic at 0x%x loop:%d\n", i, (i >> 16)); + g_mod_override_offset += i; + break; + } + } + + len = (grub_uint32_t)OFFSET_OF(struct g_hiperiso_map, seglist) + + (sizeof(struct g_hiperiso_seg) * g_img_chunk_list.cur_chunk); + + g_ko_fillmap_len = (int)len; + g_ko_fillmap_data = grub_malloc(len); + if (!g_ko_fillmap_data) + { + g_ko_fillmap_len = 0; + debug("Failed to malloc fillmap data\n"); + } + + debug("Fillmap ko segnum:%u, override len:%u data:%p\n", g_img_chunk_list.cur_chunk, len, g_ko_fillmap_data); + + grub_file_close(file); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + grub_uint8_t *byte; + grub_uint32_t memsize; + hiperiso_image_desc *desc; + grub_uint8_t flag[32] = { + 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + + (void)ctxt; + (void)argc; + (void)args; + + debug("hiperiso_cmd_unix_fill_image_desc %p\n", g_mod_new_data); + + if (!g_mod_new_data) + { + goto end; + } + + byte = (grub_uint8_t *)g_mod_new_data; + for (i = 0; i < g_mod_new_len - 32; i += 16) + { + if (byte[i] == 0xFF && byte[i + 1] == 0xEE) + { + if (grub_memcmp(flag, byte + i, 32) == 0) + { + debug("Find position flag at %d(0x%x)\n", i, i); + break; + } + } + } + + if (i >= g_mod_new_len - 32) + { + debug("Failed to find position flag %d\n", i); + goto end; + } + + desc = (hiperiso_image_desc *)(byte + i); + desc->disk_size = g_hiperiso_disk_size; + desc->part1_size = g_hiperiso_disk_part_size[0]; + grub_memcpy(desc->disk_uuid, g_hiperiso_part_info->MBR.BootCode + 0x180, 16); + grub_memcpy(desc->disk_signature, g_hiperiso_part_info->MBR.BootCode + 0x1B8, 4); + + desc->img_chunk_count = g_img_chunk_list.cur_chunk; + memsize = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + debug("image chunk count:%u memsize:%u\n", desc->img_chunk_count, memsize); + + if (memsize >= HISO_SIZE_1MB * 8) + { + grub_printf("image chunk count:%u memsize:%u too big\n", desc->img_chunk_count, memsize); + goto end; + } + + grub_memcpy(desc + 1, g_img_chunk_list.chunk, memsize); + +end: + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int newlen; + grub_uint8_t *buf; + + (void)ctxt; + (void)argc; + (void)args; + + debug("hiperiso_cmd_unix_gzip_newko %p\n", g_mod_new_data); + + if (!g_mod_new_data) + { + goto end; + } + + buf = grub_malloc(g_mod_new_len); + if (!buf) + { + goto end; + } + + newlen = hiperiso_gzip_compress(g_mod_new_data, g_mod_new_len, buf, g_mod_new_len); + + grub_free(g_mod_new_data); + + debug("gzip org len:%d newlen:%d\n", g_mod_new_len, newlen); + + g_mod_new_data = (char *)buf; + g_mod_new_len = newlen; + +end: + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int hiperiso_compatible = 0; + grub_uint32_t size = 0; + grub_uint64_t isosize = 0; + grub_uint32_t boot_catlog = 0; + grub_uint32_t img_chunk_size = 0; + grub_uint32_t override_count = 0; + grub_uint32_t override_size = 0; + grub_uint32_t virt_chunk_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + const char *compatible; + hiperiso_chain_head *chain; + + (void)ctxt; + (void)argc; + + compatible = grub_env_get("hiperiso_compatible"); + if (compatible && compatible[0] == 'Y') + { + hiperiso_compatible = 1; + } + + if (NULL == g_img_chunk_list.chunk) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return 1; + } + + isosize = file->size; + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + if (boot_catlog) + { + if (hiperiso_is_efi_os() && (!hiperiso_has_efi_eltorito(file, boot_catlog))) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + } + else + { + if (hiperiso_is_efi_os()) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + else + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]); + } + } + + img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + if (hiperiso_compatible) + { + size = sizeof(hiperiso_chain_head) + img_chunk_size; + } + else + { + override_count = hiperiso_unix_get_override_chunk_count(); + override_size = override_count * sizeof(hiperiso_override_chunk); + + virt_chunk_size = hiperiso_unix_get_virt_chunk_size(); + size = sizeof(hiperiso_chain_head) + img_chunk_size + override_size + virt_chunk_size; + } + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain unix memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_linux; + hiperiso_fill_os_param(file, &(chain->os_param)); + + /* part 2: chain head */ + disk = file->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + chain->real_img_size_in_bytes = file->size; + chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048; + chain->boot_catalog = boot_catlog; + + if (!hiperiso_is_efi_os()) + { + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector)); + } + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_img_chunk_list.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size); + + if (hiperiso_compatible) + { + return 0; + } + + /* part 4: override chunk */ + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size; + chain->override_chunk_num = override_count; + hiperiso_unix_fill_override_data(isosize, chain); + + /* part 5: virt chunk */ + chain->virt_chunk_offset = chain->override_chunk_offset + override_size; + chain->virt_chunk_num = hiperiso_unix_get_virt_chunk_count(); + hiperiso_unix_fill_virt_data(isosize, chain); + + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + diff --git a/src/grub2/hiperiso_vhd.c b/src/grub2/hiperiso_vhd.c new file mode 100644 index 0000000..15f0d97 --- /dev/null +++ b/src/grub2/hiperiso_vhd.c @@ -0,0 +1,754 @@ +/****************************************************************************** + * hiperiso_vhd.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_MACHINE_EFI +#include +#endif +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +static int g_vhdboot_isolen = 0; +static char *g_vhdboot_totbuf = NULL; +static char *g_vhdboot_isobuf = NULL; +static grub_uint64_t g_img_trim_head_secnum = 0; + +static int hiperiso_vhd_find_bcd(int *bcdoffset, int *bcdlen, const char *path) +{ + grub_uint32_t offset; + grub_file_t file; + char cmdbuf[128]; + + grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback vhdiso mem:0x%lx:size:%d", (ulong)g_vhdboot_isobuf, g_vhdboot_isolen); + + grub_script_execute_sourcecode(cmdbuf); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "(vhdiso)%s", path); + if (!file) + { + return 1; + } + + grub_file_read(file, &offset, 4); + offset = (grub_uint32_t)grub_iso9660_get_last_read_pos(file); + + *bcdoffset = (int)offset; + *bcdlen = (int)file->size; + + debug("vhdiso bcd file offset:%d len:%d\n", *bcdoffset, *bcdlen); + + grub_file_close(file); + + grub_script_execute_sourcecode("loopback -d vhdiso"); + + return 0; +} + +static int hiperiso_vhd_patch_path(char *vhdpath, hiperiso_patch_vhd *patch1, hiperiso_patch_vhd *patch2, + int bcdoffset, int bcdlen) +{ + int i; + int cnt = 0; + char *pos; + grub_size_t pathlen; + const char *plat; + char *newpath = NULL; + grub_uint16_t *unicode_path; + const grub_uint8_t winloadexe[] = + { + 0x77, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x61, 0x00, 0x64, 0x00, 0x2E, 0x00, + 0x65, 0x00, 0x78, 0x00, 0x65, 0x00 + }; + + while ((*vhdpath) != '/') + { + vhdpath++; + } + + pathlen = sizeof(grub_uint16_t) * (grub_strlen(vhdpath) + 1); + debug("unicode path for <%s> len:%d\n", vhdpath, (int)pathlen); + + unicode_path = grub_zalloc(pathlen); + if (!unicode_path) + { + return 0; + } + + plat = grub_env_get("grub_platform"); + + if (plat && (plat[0] == 'e')) /* UEFI */ + { + pos = g_vhdboot_isobuf + bcdoffset; + + /* winload.exe ==> winload.efi */ + for (i = 0; i + (int)sizeof(winloadexe) < bcdlen; i++) + { + if (*((grub_uint32_t *)(pos + i)) == 0x00690077 && + grub_memcmp(pos + i, winloadexe, sizeof(winloadexe)) == 0) + { + pos[i + sizeof(winloadexe) - 4] = 0x66; + pos[i + sizeof(winloadexe) - 2] = 0x69; + cnt++; + } + } + + debug("winload patch %d times\n", cnt); + } + + newpath = grub_strdup(vhdpath); + for (pos = newpath; *pos; pos++) + { + if (*pos == '/') + { + *pos = '\\'; + } + } + + grub_utf8_to_utf16(unicode_path, pathlen, (grub_uint8_t *)newpath, -1, NULL); + grub_memcpy(patch1->vhd_file_path, unicode_path, pathlen); + grub_memcpy(patch2->vhd_file_path, unicode_path, pathlen); + + grub_free(newpath); + return 0; +} + +static int hiperiso_vhd_read_parttbl(const char *filename, hiperiso_gpt_info *gpt, int *index, grub_uint64_t *poffset) +{ + int i; + int find = 0; + int ret = 1; + grub_uint64_t start; + grub_file_t file = NULL; + grub_disk_t disk = NULL; + grub_uint8_t zeroguid[16] = {0}; + + file = grub_file_open(filename, HIPERISO_FILE_TYPE); + if (!file) + { + goto end; + } + + disk = grub_disk_open(file->device->disk->name); + if (!disk) + { + goto end; + } + + grub_disk_read(disk, 0, 0, sizeof(hiperiso_gpt_info), gpt); + + start = file->device->disk->partition->start; + + if (grub_memcmp(gpt->Head.Signature, "EFI PART", 8) == 0) + { + debug("GPT part start: %llu\n", (ulonglong)start); + for (i = 0; i < 128; i++) + { + if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16)) + { + if (start == gpt->PartTbl[i].StartLBA) + { + *index = i; + find = 1; + break; + } + } + } + } + else + { + debug("MBR part start: %llu\n", (ulonglong)start); + for (i = 0; i < 4; i++) + { + if ((grub_uint32_t)start == gpt->MBR.PartTbl[i].StartSectorId) + { + *index = i; + find = 1; + break; + } + } + } + + if (find == 0) // MBR Logical partition + { + if (file->device->disk->partition->number > 0) + { + *index = file->device->disk->partition->number; + debug("Fall back part number: %d\n", *index); + } + } + + *poffset = start; + ret = 0; + +end: + check_free(file, grub_file_close); + check_free(disk, grub_disk_close); + + return ret; +} + +static int hiperiso_vhd_patch_disk(const char *vhdpath, hiperiso_patch_vhd *patch1, hiperiso_patch_vhd *patch2) +{ + int partIndex = 0; + grub_uint64_t offset = 0; + char efipart[16] = {0}; + hiperiso_gpt_info *gpt = NULL; + + if (vhdpath[0] == '/') + { + gpt = g_hiperiso_part_info; + partIndex = 0; + debug("This is Hiperiso ISO partIndex %d %s\n", partIndex, vhdpath); + } + else + { + gpt = grub_zalloc(sizeof(hiperiso_gpt_info)); + hiperiso_vhd_read_parttbl(vhdpath, gpt, &partIndex, &offset); + debug("This is HDD partIndex %d %s\n", partIndex, vhdpath); + } + + grub_memcpy(efipart, gpt->Head.Signature, sizeof(gpt->Head.Signature)); + + grub_memset(patch1, 0, OFFSET_OF(hiperiso_patch_vhd, vhd_file_path)); + grub_memset(patch2, 0, OFFSET_OF(hiperiso_patch_vhd, vhd_file_path)); + + if (grub_strncmp(efipart, "EFI PART", 8) == 0) + { + hiperiso_debug_dump_guid("GPT disk GUID: ", gpt->Head.DiskGuid); + hiperiso_debug_dump_guid("GPT partIndex GUID: ", gpt->PartTbl[partIndex].PartGuid); + + grub_memcpy(patch1->disk_signature_or_guid, gpt->Head.DiskGuid, 16); + grub_memcpy(patch1->part_offset_or_guid, gpt->PartTbl[partIndex].PartGuid, 16); + grub_memcpy(patch2->disk_signature_or_guid, gpt->Head.DiskGuid, 16); + grub_memcpy(patch2->part_offset_or_guid, gpt->PartTbl[partIndex].PartGuid, 16); + + patch1->part_type = patch2->part_type = 0; + } + else + { + if (offset == 0) + { + offset = gpt->MBR.PartTbl[partIndex].StartSectorId; + } + offset *= 512; + debug("MBR disk signature: %02x%02x%02x%02x Part(%d) offset:%llu\n", + gpt->MBR.BootCode[0x1b8 + 0], gpt->MBR.BootCode[0x1b8 + 1], + gpt->MBR.BootCode[0x1b8 + 2], gpt->MBR.BootCode[0x1b8 + 3], + partIndex + 1, offset); + + grub_memcpy(patch1->part_offset_or_guid, &offset, 8); + grub_memcpy(patch2->part_offset_or_guid, &offset, 8); + + grub_memcpy(patch1->disk_signature_or_guid, gpt->MBR.BootCode + 0x1b8, 4); + grub_memcpy(patch2->disk_signature_or_guid, gpt->MBR.BootCode + 0x1b8, 4); + + patch1->part_type = patch2->part_type = 1; + } + + if (gpt != g_hiperiso_part_info) + { + grub_free(gpt); + } + + return 0; +} + +static int hiperiso_find_vhdpatch_offset(int bcdoffset, int bcdlen, int *offset) +{ + int i; + int cnt = 0; + grub_uint8_t *buf = (grub_uint8_t *)(g_vhdboot_isobuf + bcdoffset); + grub_uint8_t magic[16] = { + 0x5C, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00 + }; + + for (i = 0; i < bcdlen - 16 && cnt < 2; i++) + { + if (*(grub_uint32_t *)(buf + i) == 0x0058005C) + { + if (grub_memcmp(magic, buf + i, 16) == 0) + { + *offset++ = i - (int)OFFSET_OF(hiperiso_patch_vhd, vhd_file_path); + cnt++; + } + } + } + + return 0; +} + +grub_err_t hiperiso_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc; + int bcdoffset, bcdlen; + int patchoffset[2]; + hiperiso_patch_vhd *patch1; + hiperiso_patch_vhd *patch2; + + (void)ctxt; + (void)argc; + + grub_env_unset("hiso_vhd_buf_addr"); + + debug("patch vhd <%s>\n", args[0]); + + if ((!g_vhdboot_enable) || (!g_vhdboot_totbuf)) + { + debug("vhd boot not ready %d %p\n", g_vhdboot_enable, g_vhdboot_totbuf); + return 0; + } + + rc = hiperiso_vhd_find_bcd(&bcdoffset, &bcdlen, "/boot/bcd"); + if (rc) + { + debug("failed to get bcd location %d\n", rc); + } + else + { + hiperiso_find_vhdpatch_offset(bcdoffset, bcdlen, patchoffset); + patch1 = (hiperiso_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[0]); + patch2 = (hiperiso_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[1]); + + debug("Find /boot/bcd (%d %d) now patch it (offset: 0x%x 0x%x) ...\n", + bcdoffset, bcdlen, patchoffset[0], patchoffset[1]); + hiperiso_vhd_patch_disk(args[0], patch1, patch2); + hiperiso_vhd_patch_path(args[0], patch1, patch2, bcdoffset, bcdlen); + } + + rc = hiperiso_vhd_find_bcd(&bcdoffset, &bcdlen, "/boot/BCD"); + if (rc) + { + debug("No file /boot/BCD \n"); + } + else + { + hiperiso_find_vhdpatch_offset(bcdoffset, bcdlen, patchoffset); + patch1 = (hiperiso_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[0]); + patch2 = (hiperiso_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[1]); + + debug("Find /boot/BCD (%d %d) now patch it (offset: 0x%x 0x%x) ...\n", + bcdoffset, bcdlen, patchoffset[0], patchoffset[1]); + hiperiso_vhd_patch_disk(args[0], patch1, patch2); + hiperiso_vhd_patch_path(args[0], patch1, patch2, bcdoffset, bcdlen); + } + + /* set buffer and size */ +#ifdef GRUB_MACHINE_EFI + hiperiso_memfile_env_set("hiso_vhd_buf", g_vhdboot_totbuf, (ulonglong)(g_vhdboot_isolen + sizeof(hiperiso_chain_head))); +#else + hiperiso_memfile_env_set("hiso_vhd_buf", g_vhdboot_isobuf, (ulonglong)g_vhdboot_isolen); +#endif + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int buflen; + grub_file_t file; + + (void)ctxt; + (void)argc; + + g_vhdboot_enable = 0; + grub_check_free(g_vhdboot_totbuf); + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + return 0; + } + + debug("load vhd boot: <%s> <%lu>\n", args[0], (ulong)file->size); + + if (file->size < HISO_SIZE_1KB * 32) + { + grub_file_close(file); + return 0; + } + + g_vhdboot_isolen = (int)file->size; + + buflen = (int)(file->size + sizeof(hiperiso_chain_head)); + +#ifdef GRUB_MACHINE_EFI + g_vhdboot_totbuf = (char *)grub_efi_allocate_iso_buf(buflen); +#else + g_vhdboot_totbuf = (char *)grub_malloc(buflen); +#endif + + if (!g_vhdboot_totbuf) + { + grub_file_close(file); + return 0; + } + + g_vhdboot_isobuf = g_vhdboot_totbuf + sizeof(hiperiso_chain_head); + + grub_file_read(file, g_vhdboot_isobuf, file->size); + grub_file_close(file); + + g_vhdboot_enable = 1; + + return 0; +} + +static int hiperiso_raw_trim_head(grub_uint64_t offset) +{ + grub_uint32_t i; + grub_uint32_t memsize; + grub_uint32_t imgstart = 0; + grub_uint32_t imgsecs = 0; + grub_uint64_t sectors = 0; + grub_uint64_t cursecs = 0; + grub_uint64_t delta = 0; + + if ((!g_img_chunk_list.chunk) || (!offset)) + { + debug("image chunk not ready %p %lu\n", g_img_chunk_list.chunk, (ulong)offset); + return 0; + } + + debug("image trim head %lu\n", (ulong)offset); + + for (i = 0; i < g_img_chunk_list.cur_chunk; i++) + { + cursecs = g_img_chunk_list.chunk[i].disk_end_sector + 1 - g_img_chunk_list.chunk[i].disk_start_sector; + sectors += cursecs; + if (sectors >= offset) + { + delta = cursecs - (sectors - offset); + break; + } + } + + if (sectors < offset || i >= g_img_chunk_list.cur_chunk) + { + debug("Invalid size %lu %lu\n", (ulong)sectors, (ulong)offset); + return 0; + } + + if (sectors == offset) + { + memsize = (g_img_chunk_list.cur_chunk - (i + 1)) * sizeof(hiperiso_img_chunk); + grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i + 1, memsize); + g_img_chunk_list.cur_chunk -= (i + 1); + } + else + { + g_img_chunk_list.chunk[i].disk_start_sector += delta; + g_img_chunk_list.chunk[i].img_start_sector += (grub_uint32_t)(delta / 4); + + if (i > 0) + { + memsize = (g_img_chunk_list.cur_chunk - i) * sizeof(hiperiso_img_chunk); + grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i, memsize); + g_img_chunk_list.cur_chunk -= i; + } + } + + for (i = 0; i < g_img_chunk_list.cur_chunk; i++) + { + imgsecs = g_img_chunk_list.chunk[i].img_end_sector + 1 - g_img_chunk_list.chunk[i].img_start_sector; + g_img_chunk_list.chunk[i].img_start_sector = imgstart; + g_img_chunk_list.chunk[i].img_end_sector = imgstart + (imgsecs - 1); + imgstart += imgsecs; + } + + return 0; +} + +grub_err_t hiperiso_cmd_get_hiso_type(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int altboot = 0; + int offset = -1; + grub_file_t file; + grub_uint8_t data = 0; + vhd_footer_t vhdfoot; + VDIPREHEADER vdihdr; + char type[16] = {0}; + hiperiso_gpt_info *gpt = NULL; + + (void)ctxt; + + g_img_trim_head_secnum = 0; + + if (argc != 4) + { + return 0; + } + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + debug("Failed to open file %s\n", args[0]); + return 0; + } + + grub_snprintf(type, sizeof(type), "unknown"); + + grub_file_seek(file, file->size - 512); + grub_file_read(file, &vhdfoot, sizeof(vhdfoot)); + + if (grub_strncmp(vhdfoot.cookie, "conectix", 8) == 0) + { + offset = 0; + grub_snprintf(type, sizeof(type), "vhd%u", grub_swap_bytes32(vhdfoot.disktype)); + } + else + { + grub_file_seek(file, 0); + grub_file_read(file, &vdihdr, sizeof(vdihdr)); + if (vdihdr.u32Signature == VDI_IMAGE_SIGNATURE) + { + grub_snprintf(type, sizeof(type), "vdi"); + if (grub_strncmp(vdihdr.szFileInfo, VDI_IMAGE_FILE_INFO, grub_strlen(VDI_IMAGE_FILE_INFO)) == 0) + { + offset = 2 * 1048576; + g_img_trim_head_secnum = offset / 512; + debug("VDI V1\n"); + } + else if (grub_strncmp(vdihdr.szFileInfo, VDI_IMAGE_FILE_INFO2, grub_strlen(VDI_IMAGE_FILE_INFO2)) == 0) + { + offset = 2 * 1048576; + g_img_trim_head_secnum = offset / 512; + debug("VDI V2\n"); + } + else + { + debug("invalid file info <%s>\n", vdihdr.szFileInfo); + } + } + else + { + offset = 0; + grub_snprintf(type, sizeof(type), "raw"); + } + } + + grub_env_set(args[1], type); + debug("<%s> hiso type: <%s> offset:%d\n", args[0], type, offset); + + if (offset >= 0) + { + gpt = grub_zalloc(sizeof(hiperiso_gpt_info)); + if (!gpt) + { + grub_env_set(args[1], "unknown"); + goto end; + } + + grub_file_seek(file, offset); + grub_file_read(file, gpt, sizeof(hiperiso_gpt_info)); + + if (gpt->MBR.Byte55 != 0x55 || gpt->MBR.ByteAA != 0xAA) + { + grub_env_set(args[1], "unknown"); + debug("invalid mbr signature: 0x%x 0x%x offset=%d\n", gpt->MBR.Byte55, gpt->MBR.ByteAA, offset); + goto end; + } + + if (grub_memcmp(gpt->Head.Signature, "EFI PART", 8) == 0) + { + grub_env_set(args[2], "gpt"); + debug("part type: %s\n", "GPT"); + + if (gpt->MBR.PartTbl[0].FsFlag == 0xEE) + { + for (i = 0; i < 128; i++) + { + if (grub_memcmp(gpt->PartTbl[i].PartType, "Hah!IdontNeedEFI", 16) == 0) + { + debug("part %d is grub_bios part\n", i); + altboot = 1; + grub_env_set(args[3], "1"); + break; + } + else if (gpt->PartTbl[i].LastLBA == 0) + { + break; + } + } + } + + if (!altboot) + { + if (gpt->MBR.BootCode[92] == 0x22) + { + grub_file_seek(file, offset + 17908); + grub_file_read(file, &data, 1); + if (data == 0x23) + { + altboot = 1; + grub_env_set(args[3], "1"); + } + else + { + debug("offset data=0x%x\n", data); + } + } + else + { + debug("BootCode: 0x%x\n", gpt->MBR.BootCode[92]); + } + } + } + else + { + grub_env_set(args[2], "mbr"); + debug("part type: %s\n", "MBR"); + + for (i = 0; i < 4; i++) + { + if (gpt->MBR.PartTbl[i].FsFlag == 0xEF) + { + debug("part %d is esp part in MBR mode\n", i); + altboot = 1; + grub_env_set(args[3], "1"); + break; + } + } + } + } + else + { + debug("part type: %s\n", "xxx"); + } + +end: + grub_check_free(gpt); + grub_file_close(file); + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t size = 0; + grub_uint32_t img_chunk_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + hiperiso_chain_head *chain; + + (void)ctxt; + (void)argc; + + if (NULL == g_img_chunk_list.chunk) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + if (g_img_trim_head_secnum > 0) + { + hiperiso_raw_trim_head(g_img_trim_head_secnum); + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return 1; + } + + if (grub_strncmp(args[0], g_iso_path, grub_strlen(g_iso_path))) + { + file->vlnk = 1; + } + + img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + size = sizeof(hiperiso_chain_head) + img_chunk_size; + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain raw memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_env_export("hiso_chain_mem_addr"); + grub_env_export("hiso_chain_mem_size"); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_linux; + hiperiso_fill_os_param(file, &(chain->os_param)); + + /* part 2: chain head */ + disk = file->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + + chain->real_img_size_in_bytes = file->size; + if (g_img_trim_head_secnum > 0) + { + chain->real_img_size_in_bytes -= g_img_trim_head_secnum * 512; + } + + chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes; + chain->boot_catalog = 0; + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_img_chunk_list.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size); + + grub_file_seek(file, g_img_trim_head_secnum * 512); + grub_file_read(file, chain->boot_catalog_sector, 512); + + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} diff --git a/src/grub2/hiperiso_windows.c b/src/grub2/hiperiso_windows.c new file mode 100644 index 0000000..f2a858d --- /dev/null +++ b/src/grub2/hiperiso_windows.c @@ -0,0 +1,2781 @@ +/****************************************************************************** + * hiperiso_windows.c + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +static int g_iso_fs_type = 0; +static int g_wim_total_patch_count = 0; +static int g_wim_valid_patch_count = 0; +static wim_patch *g_wim_patch_head = NULL; + +static grub_uint64_t g_suppress_wincd_override_offset = 0; +static grub_uint32_t g_suppress_wincd_override_data = 0; + +grub_uint8_t g_temp_buf[512]; + +grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf ); +grub_ssize_t xca_decompress ( const void *data, grub_size_t len, void *buf ); + +static wim_patch *hiperiso_find_wim_patch(const char *path) +{ + int len = (int)grub_strlen(path); + wim_patch *node = g_wim_patch_head; + + while (node) + { + if (len == node->pathlen && 0 == grub_strcmp(path, node->path)) + { + return node; + } + node = node->next; + } + + return NULL; +} + +static int hiperiso_collect_wim_patch(const char *bcdfile) +{ + int i, j, k; + int rc = 1; + grub_uint64_t magic; + grub_file_t file = NULL; + char *buf = NULL; + wim_patch *node = NULL; + char c; + grub_uint8_t byte; + char valid; + char path[256]; + + g_hiperiso_case_insensitive = 1; + file = grub_file_open(bcdfile, HIPERISO_FILE_TYPE); + g_hiperiso_case_insensitive = 0; + if (!file) + { + debug("Failed to open file %s\n", bcdfile); + grub_errno = 0; + goto end; + } + + buf = grub_malloc(file->size + 8); + if (!buf) + { + goto end; + } + + grub_file_read(file, buf, file->size); + + for (i = 0; i < (int)file->size - 8; i++) + { + if (buf[i + 8] != 0) + { + continue; + } + + magic = *(grub_uint64_t *)(buf + i); + + /* .wim .WIM .Wim */ + if ((magic == 0x006D00690077002EULL) || + (magic == 0x004D00490057002EULL) || + (magic == 0x006D00690057002EULL)) + { + for (j = i; j > 0; j-= 2) + { + if (*(grub_uint16_t *)(buf + j) == 0) + { + break; + } + } + + if (j > 0) + { + byte = (grub_uint8_t)(*(grub_uint16_t *)(buf + j + 2)); + if (byte != '/' && byte != '\\') + { + continue; + } + + valid = 1; + for (k = 0, j += 2; k < (int)sizeof(path) - 1 && j < i + 8; j += 2) + { + byte = (grub_uint8_t)(*(grub_uint16_t *)(buf + j)); + c = (char)byte; + if (byte > '~' || byte < ' ') /* not printable */ + { + valid = 0; + break; + } + else if (c == '\\') + { + c = '/'; + } + + path[k++] = c; + } + path[k++] = 0; + + debug("@@@@ Find wim flag:<%s>\n", path); + + if (0 == valid) + { + debug("Invalid wim file %d\n", k); + } + else if (NULL == hiperiso_find_wim_patch(path)) + { + node = grub_zalloc(sizeof(wim_patch)); + if (node) + { + node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", path); + + debug("add patch <%s>\n", path); + + if (g_wim_patch_head) + { + node->next = g_wim_patch_head; + } + g_wim_patch_head = node; + + g_wim_total_patch_count++; + } + } + else + { + debug("wim <%s> already exist\n", path); + } + } + } + } + +end: + check_free(file, grub_file_close); + grub_check_free(buf); + return rc; +} + +grub_err_t hiperiso_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args) +{ + char buf[32]; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc == 1) + { + grub_snprintf(buf, sizeof(buf), "%d", g_wim_total_patch_count); + hiperiso_set_env(args[0], buf); + } + + return 0; +} + +grub_err_t hiperiso_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args) +{ + wim_patch *node = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + if (argc != 2) + { + return 1; + } + + debug("hiperiso_cmd_collect_wim_patch %s %s\n", args[0], args[1]); + + if (grub_strcmp(args[0], "bcd") == 0) + { + hiperiso_collect_wim_patch(args[1]); + return 0; + } + + if (NULL == hiperiso_find_wim_patch(args[1])) + { + node = grub_zalloc(sizeof(wim_patch)); + if (node) + { + node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", args[1]); + + debug("add patch <%s>\n", args[1]); + + if (g_wim_patch_head) + { + node->next = g_wim_patch_head; + } + g_wim_patch_head = node; + + g_wim_total_patch_count++; + } + } + + return 0; +} + + +grub_err_t hiperiso_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + wim_patch *node = NULL; + + (void)ctxt; + (void)argc; + (void)args; + + for (node = g_wim_patch_head; node; node = node->next) + { + grub_printf("%d %s [%s]\n", i++, node->path, node->valid ? "SUCCESS" : "FAIL"); + } + + return 0; +} + + +static int wim_name_cmp(const char *search, grub_uint16_t *name, grub_uint16_t namelen) +{ + char c1 = hiso_to_upper(*search); + char c2 = hiso_to_upper(*name); + + while (namelen > 0 && (c1 == c2)) + { + search++; + name++; + namelen--; + + c1 = hiso_to_upper(*search); + c2 = hiso_to_upper(*name); + } + + if (namelen == 0 && *search == 0) + { + return 0; + } + + return 1; +} + +static int hiperiso_is_pe64(grub_uint8_t *buffer) +{ + grub_uint32_t pe_off; + + if (buffer[0] != 'M' || buffer[1] != 'Z') + { + return 0; + } + + pe_off = *(grub_uint32_t *)(buffer + 60); + + if (buffer[pe_off] != 'P' || buffer[pe_off + 1] != 'E') + { + return 0; + } + + if (*(grub_uint16_t *)(buffer + pe_off + 24) == 0x020b) + { + return 1; + } + + return 0; +} + +grub_err_t hiperiso_cmd_is_pe64(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int ret = 1; + grub_file_t file; + grub_uint8_t buf[512]; + + (void)ctxt; + (void)argc; + + file = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!file) + { + return 1; + } + + grub_memset(buf, 0, 512); + grub_file_read(file, buf, 512); + if (hiperiso_is_pe64(buf)) + { + debug("%s is PE64\n", args[0]); + ret = 0; + } + else + { + debug("%s is PE32\n", args[0]); + } + grub_file_close(file); + + return ret; +} + +grub_err_t hiperiso_cmd_sel_wimboot(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int size; + char *buf = NULL; + char configfile[128]; + + (void)ctxt; + (void)argc; + (void)args; + + debug("select wimboot argc:%d\n", argc); + + buf = (char *)grub_malloc(8192); + if (!buf) + { + return 0; + } + + size = (int)grub_snprintf(buf, 8192, + "menuentry \"Windows Setup (32-bit)\" {\n" + " set hiso_wimboot_sel=32\n" + "}\n" + "menuentry \"Windows Setup (64-bit)\" {\n" + " set hiso_wimboot_sel=64\n" + "}\n" + ); + buf[size] = 0; + + g_hiperiso_menu_esc = 1; + g_hiperiso_suppress_esc = 1; + g_hiperiso_suppress_esc_default = 1; + + grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, size); + grub_script_execute_sourcecode(configfile); + + g_hiperiso_menu_esc = 0; + g_hiperiso_suppress_esc = 0; + + grub_free(buf); + + if (g_hiperiso_last_entry == 0) + { + debug("last entry=%d %s=32\n", g_hiperiso_last_entry, args[0]); + grub_env_set(args[0], "32"); + } + else + { + debug("last entry=%d %s=64\n", g_hiperiso_last_entry, args[0]); + grub_env_set(args[0], "64"); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args) +{ + wim_patch *next = NULL; + wim_patch *node = g_wim_patch_head; + + (void)ctxt; + (void)argc; + (void)args; + + while (node) + { + next = node->next; + grub_free(node); + node = next; + } + + g_wim_patch_head = NULL; + g_wim_total_patch_count = 0; + g_wim_valid_patch_count = 0; + + return 0; +} + +static int hiperiso_load_jump_exe(const char *path, grub_uint8_t **data, grub_uint32_t *size, wim_hash *hash) +{ + grub_uint32_t i; + grub_uint32_t align; + grub_file_t file; + + debug("windows load jump %s\n", path); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", path); + if (!file) + { + debug("Can't open file %s\n", path); + return 1; + } + + align = hiperiso_align((int)file->size, 2048); + + debug("file %s size:%d align:%u\n", path, (int)file->size, align); + + *size = (grub_uint32_t)file->size; + *data = (grub_uint8_t *)grub_malloc(align); + if ((*data) == NULL) + { + debug("Failed to alloc memory size %u\n", align); + goto end; + } + + grub_file_read(file, (*data), file->size); + + if (hash) + { + grub_crypto_hash(GRUB_MD_SHA1, hash->sha1, (*data), file->size); + + if (g_hiperiso_debug) + { + debug("%s", "jump bin 64 hash: "); + for (i = 0; i < sizeof(hash->sha1); i++) + { + hiperiso_debug("%02x ", hash->sha1[i]); + } + hiperiso_debug("\n"); + } + } + +end: + + grub_file_close(file); + return 0; +} + +static int hiperiso_get_override_info(grub_file_t file, wim_tail *wim_data) +{ + grub_uint32_t start_block; + grub_uint64_t file_offset; + grub_uint64_t override_offset; + grub_uint32_t override_len; + grub_uint64_t fe_entry_size_offset; + + if (grub_strcmp(file->fs->name, "iso9660") == 0) + { + g_iso_fs_type = wim_data->iso_type = 0; + override_len = sizeof(hiperiso_iso9660_override); + override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2; + + grub_file_read(file, &start_block, 1); // just read for hook trigger + file_offset = grub_iso9660_get_last_read_pos(file); + + debug("iso9660 wim size:%llu override_offset:%llu file_offset:%llu\n", + (ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset); + } + else + { + g_iso_fs_type = wim_data->iso_type = 1; + override_len = sizeof(hiperiso_udf_override); + override_offset = grub_udf_get_last_file_attr_offset(file, &start_block, &fe_entry_size_offset); + + file_offset = grub_udf_get_file_offset(file); + + debug("UDF wim size:%llu override_offset:%llu file_offset:%llu start_block=%u\n", + (ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset, start_block); + } + + wim_data->file_offset = file_offset; + wim_data->udf_start_block = start_block; + wim_data->fe_entry_size_offset = fe_entry_size_offset; + wim_data->override_offset = override_offset; + wim_data->override_len = override_len; + + return 0; +} + +static int hiperiso_read_resource(grub_file_t fp, wim_header *wimhdr, wim_resource_header *head, void **buffer) +{ + int decompress_len = 0; + int total_decompress = 0; + grub_uint32_t i = 0; + grub_uint32_t chunk_num = 0; + grub_uint32_t chunk_size = 0; + grub_uint32_t last_chunk_size = 0; + grub_uint32_t last_decompress_size = 0; + grub_uint32_t cur_offset = 0; + grub_uint8_t *cur_dst = NULL; + grub_uint8_t *buffer_compress = NULL; + grub_uint8_t *buffer_decompress = NULL; + grub_uint32_t *chunk_offset = NULL; + + buffer_decompress = (grub_uint8_t *)grub_malloc(head->raw_size + head->size_in_wim); + if (NULL == buffer_decompress) + { + return 0; + } + + grub_file_seek(fp, head->offset); + + if (head->size_in_wim == head->raw_size) + { + grub_file_read(fp, buffer_decompress, head->size_in_wim); + *buffer = buffer_decompress; + return 0; + } + + buffer_compress = buffer_decompress + head->raw_size; + grub_file_read(fp, buffer_compress, head->size_in_wim); + + chunk_num = (head->raw_size + WIM_CHUNK_LEN - 1) / WIM_CHUNK_LEN; + cur_offset = (chunk_num - 1) * 4; + chunk_offset = (grub_uint32_t *)buffer_compress; + + //debug("%llu %llu chunk_num=%lu", (ulonglong)head->size_in_wim, (ulonglong)head->raw_size, chunk_num); + + cur_dst = buffer_decompress; + + for (i = 0; i < chunk_num - 1; i++) + { + chunk_size = (i == 0) ? chunk_offset[i] : chunk_offset[i] - chunk_offset[i - 1]; + + if (WIM_CHUNK_LEN == chunk_size) + { + grub_memcpy(cur_dst, buffer_compress + cur_offset, chunk_size); + decompress_len = (int)chunk_size; + } + else + { + if (wimhdr->flags & FLAG_HEADER_COMPRESS_XPRESS) + { + decompress_len = (int)xca_decompress(buffer_compress + cur_offset, chunk_size, cur_dst); + } + else + { + decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, chunk_size, cur_dst); + } + } + + //debug("chunk_size:%u decompresslen:%d\n", chunk_size, decompress_len); + + total_decompress += decompress_len; + cur_dst += decompress_len; + cur_offset += chunk_size; + } + + /* last chunk */ + last_chunk_size = (grub_uint32_t)(head->size_in_wim - cur_offset); + last_decompress_size = head->raw_size - total_decompress; + + if (last_chunk_size < WIM_CHUNK_LEN && last_chunk_size == last_decompress_size) + { + debug("Last chunk %u uncompressed\n", last_chunk_size); + grub_memcpy(cur_dst, buffer_compress + cur_offset, last_chunk_size); + decompress_len = (int)last_chunk_size; + } + else + { + if (wimhdr->flags & FLAG_HEADER_COMPRESS_XPRESS) + { + decompress_len = (int)xca_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst); + } + else + { + decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst); + } + } + + cur_dst += decompress_len; + total_decompress += decompress_len; + + //debug("last chunk_size:%u decompresslen:%d tot:%d\n", last_chunk_size, decompress_len, total_decompress); + + if (cur_dst != buffer_decompress + head->raw_size) + { + debug("head->size_in_wim:%llu head->raw_size:%llu cur_dst:%p buffer_decompress:%p total_decompress:%d\n", + (ulonglong)head->size_in_wim, (ulonglong)head->raw_size, cur_dst, buffer_decompress, total_decompress); + grub_free(buffer_decompress); + return 1; + } + + *buffer = buffer_decompress; + return 0; +} + + +static wim_directory_entry * search_wim_dirent(wim_directory_entry *dir, const char *search_name) +{ + do + { + if (dir->len && dir->name_len) + { + if (wim_name_cmp(search_name, (grub_uint16_t *)(dir + 1), dir->name_len / 2) == 0) + { + return dir; + } + } + dir = (wim_directory_entry *)((grub_uint8_t *)dir + dir->len); + } while(dir->len); + + return NULL; +} + +static wim_directory_entry * search_full_wim_dirent +( + void *meta_data, + wim_directory_entry *dir, + const char **path +) +{ + wim_directory_entry *subdir = NULL; + wim_directory_entry *search = dir; + + while (*path) + { + subdir = (wim_directory_entry *)((char *)meta_data + search->subdir); + search = search_wim_dirent(subdir, *path); + path++; + } + + return search; +} + + + +static wim_lookup_entry * hiperiso_find_look_entry(wim_header *header, wim_lookup_entry *lookup, wim_hash *hash) +{ + grub_uint32_t i = 0; + + for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++) + { + if (grub_memcmp(&lookup[i].hash, hash, sizeof(wim_hash)) == 0) + { + return lookup + i; + } + } + + return NULL; +} + +static int parse_registry_setup_cmdline +( + grub_file_t file, + wim_header *head, + wim_lookup_entry *lookup, + void *meta_data, + wim_directory_entry *dir, + char *buf, + grub_uint32_t buflen +) +{ + char c; + int ret = 0; + grub_uint32_t i = 0; + grub_uint32_t reglen = 0; + wim_hash zerohash; + reg_vk *regvk = NULL; + wim_lookup_entry *look = NULL; + wim_directory_entry *wim_dirent = NULL; + char *decompress_data = NULL; + const char *reg_path[] = { "Windows", "System32", "config", "SYSTEM", NULL }; + + wim_dirent = search_full_wim_dirent(meta_data, dir, reg_path); + debug("search reg SYSTEM %p\n", wim_dirent); + if (!wim_dirent) + { + return 1; + } + + grub_memset(&zerohash, 0, sizeof(zerohash)); + if (grub_memcmp(&zerohash, wim_dirent->hash.sha1, sizeof(wim_hash)) == 0) + { + return 2; + } + + look = hiperiso_find_look_entry(head, lookup, &wim_dirent->hash); + if (!look) + { + return 3; + } + + reglen = (grub_uint32_t)look->resource.raw_size; + debug("find system lookup entry_id:%ld raw_size:%u\n", + ((long)look - (long)lookup) / sizeof(wim_lookup_entry), reglen); + + if (0 != hiperiso_read_resource(file, head, &(look->resource), (void **)&(decompress_data))) + { + return 4; + } + + if (grub_strncmp(decompress_data + 0x1000, "hbin", 4)) + { + ret_goto_end(5); + } + + for (i = 0x1000; i + sizeof(reg_vk) < reglen; i += 8) + { + regvk = (reg_vk *)(decompress_data + i); + if (regvk->sig == 0x6B76 && regvk->namesize == 7 && + regvk->datatype == 1 && regvk->flag == 1) + { + if (grub_strncasecmp((char *)(regvk + 1), "cmdline", 7) == 0) + { + debug("find registry cmdline i:%u offset:(0x%x)%u size:(0x%x)%u\n", + i, regvk->dataoffset, regvk->dataoffset, regvk->datasize, regvk->datasize); + break; + } + } + } + + if (i + sizeof(reg_vk) >= reglen || regvk == NULL) + { + ret_goto_end(6); + } + + if (regvk->datasize == 0 || (regvk->datasize & 0x80000000) > 0 || + regvk->dataoffset == 0 || regvk->dataoffset == 0xFFFFFFFF) + { + ret_goto_end(7); + } + + if (regvk->datasize / 2 >= buflen) + { + ret_goto_end(8); + } + + debug("start offset is 0x%x(%u)\n", 0x1000 + regvk->dataoffset + 4, 0x1000 + regvk->dataoffset + 4); + + for (i = 0; i < regvk->datasize; i+=2) + { + c = (char)(*(grub_uint16_t *)(decompress_data + 0x1000 + regvk->dataoffset + 4 + i)); + *buf++ = c; + } + + ret = 0; + +end: + grub_check_free(decompress_data); + return ret; +} + +static int parse_custom_setup_path(char *cmdline, const char **path, char *exefile) +{ + int i = 0; + int len = 0; + char *pos1 = NULL; + char *pos2 = NULL; + + if ((cmdline[0] == 'x' || cmdline[0] == 'X') && cmdline[1] == ':') + { + pos1 = pos2 = cmdline + 3; + + while (i < HISO_MAX_DIR_DEPTH && *pos2) + { + while (*pos2 && *pos2 != '\\' && *pos2 != '/') + { + pos2++; + } + + path[i++] = pos1; + + if (*pos2 == 0) + { + break; + } + + *pos2 = 0; + pos1 = pos2 + 1; + pos2 = pos1; + } + + if (i == 0 || i >= HISO_MAX_DIR_DEPTH) + { + return 1; + } + } + else + { + path[i++] = "Windows"; + path[i++] = "System32"; + path[i++] = cmdline; + } + + pos1 = (char *)path[i - 1]; + while (*pos1 != ' ' && *pos1 != '\t' && *pos1) + { + pos1++; + } + *pos1 = 0; + + len = (int)grub_strlen(path[i - 1]); + if (len < 4 || grub_strcasecmp(path[i - 1] + len - 4, ".exe") != 0) + { + grub_snprintf(exefile, 256, "%s.exe", path[i - 1]); + path[i - 1] = exefile; + } + + + debug("custom setup: %d <%s>\n", i, path[i - 1]); + return 0; +} + +static wim_directory_entry * search_replace_wim_dirent +( + grub_file_t file, + wim_header *head, + wim_lookup_entry *lookup, + void *meta_data, + wim_directory_entry *dir +) +{ + int ret; + char exefile[256] = {0}; + char cmdline[256] = {0}; + wim_directory_entry *wim_dirent = NULL; + wim_directory_entry *pecmd_dirent = NULL; + const char *peset_path[] = { "Windows", "System32", "peset.exe", NULL }; + const char *pecmd_path[] = { "Windows", "System32", "pecmd.exe", NULL }; + const char *winpeshl_path[] = { "Windows", "System32", "winpeshl.exe", NULL }; + const char *custom_path[HISO_MAX_DIR_DEPTH + 1] = { NULL }; + + pecmd_dirent = search_full_wim_dirent(meta_data, dir, pecmd_path); + debug("search pecmd.exe %p\n", pecmd_dirent); + + if (pecmd_dirent) + { + ret = parse_registry_setup_cmdline(file, head, lookup, meta_data, dir, cmdline, sizeof(cmdline) - 1); + if (0 == ret) + { + debug("registry setup cmdline:<%s>\n", cmdline); + + if (grub_strncasecmp(cmdline, "PECMD", 5) == 0) + { + wim_dirent = pecmd_dirent; + } + else if (grub_strncasecmp(cmdline, "PESET", 5) == 0) + { + wim_dirent = search_full_wim_dirent(meta_data, dir, peset_path); + debug("search peset.exe %p\n", wim_dirent); + } + else if (grub_strncasecmp(cmdline, "WINPESHL", 8) == 0) + { + wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path); + debug("search winpeshl.exe %p\n", wim_dirent); + } + else if (0 == parse_custom_setup_path(cmdline, custom_path, exefile)) + { + wim_dirent = search_full_wim_dirent(meta_data, dir, custom_path); + debug("search custom path %p\n", wim_dirent); + } + + if (wim_dirent) + { + return wim_dirent; + } + } + else + { + debug("registry setup cmdline failed : %d\n", ret); + } + } + + wim_dirent = pecmd_dirent; + if (wim_dirent) + { + return wim_dirent; + } + + wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path); + debug("search winpeshl.exe %p\n", wim_dirent); + if (wim_dirent) + { + return wim_dirent; + } + + return NULL; +} + + +static wim_lookup_entry * hiperiso_find_meta_entry(wim_header *header, wim_lookup_entry *lookup) +{ + grub_uint32_t i = 0; + grub_uint32_t index = 0;; + + if ((header == NULL) || (lookup == NULL)) + { + return NULL; + } + + for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++) + { + if (lookup[i].resource.flags & RESHDR_FLAG_METADATA) + { + index++; + if (index == header->boot_index) + { + return lookup + i; + } + } + } + + return NULL; +} + +static grub_uint64_t hiperiso_get_stream_len(wim_directory_entry *dir) +{ + grub_uint16_t i; + grub_uint64_t offset = 0; + wim_stream_entry *stream = (wim_stream_entry *)((char *)dir + dir->len); + + for (i = 0; i < dir->streams; i++) + { + offset += stream->len; + stream = (wim_stream_entry *)((char *)stream + stream->len); + } + + return offset; +} + +static int hiperiso_update_stream_hash(wim_patch *patch, wim_directory_entry *dir) +{ + grub_uint16_t i; + grub_uint64_t offset = 0; + wim_stream_entry *stream = (wim_stream_entry *)((char *)dir + dir->len); + + for (i = 0; i < dir->streams; i++) + { + if (grub_memcmp(stream->hash.sha1, patch->old_hash.sha1, sizeof(wim_hash)) == 0) + { + debug("find target stream %u, name_len:%u upadte hash\n", i, stream->name_len); + grub_memcpy(stream->hash.sha1, &(patch->wim_data.bin_hash), sizeof(wim_hash)); + } + + offset += stream->len; + stream = (wim_stream_entry *)((char *)stream + stream->len); + } + + return offset; +} + +static int hiperiso_update_all_hash(wim_patch *patch, void *meta_data, wim_directory_entry *dir) +{ + if ((meta_data == NULL) || (dir == NULL)) + { + return 0; + } + + if (dir->len < sizeof(wim_directory_entry)) + { + return 0; + } + + do + { + if (dir->subdir == 0 && grub_memcmp(dir->hash.sha1, patch->old_hash.sha1, sizeof(wim_hash)) == 0) + { + debug("find target file, name_len:%u upadte hash\n", dir->name_len); + grub_memcpy(dir->hash.sha1, &(patch->wim_data.bin_hash), sizeof(wim_hash)); + } + + if (dir->subdir) + { + hiperiso_update_all_hash(patch, meta_data, (wim_directory_entry *)((char *)meta_data + dir->subdir)); + } + + if (dir->streams) + { + hiperiso_update_stream_hash(patch, dir); + dir = (wim_directory_entry *)((char *)dir + dir->len + hiperiso_get_stream_len(dir)); + } + else + { + dir = (wim_directory_entry *)((char *)dir + dir->len); + } + } while (dir->len >= sizeof(wim_directory_entry)); + + return 0; +} + +static int hiperiso_cat_exe_file_data(wim_tail *wim_data, grub_uint32_t exe_len, grub_uint8_t *exe_data, int windatalen) +{ + int pe64 = 0; + char file[256]; + grub_uint32_t jump_len = 0; + grub_uint32_t jump_align = 0; + grub_uint8_t *jump_data = NULL; + + pe64 = hiperiso_is_pe64(exe_data); + + grub_snprintf(file, sizeof(file), "%s/hisojump%d.exe", grub_env_get("hiso_path"), pe64 ? 64 : 32); + hiperiso_load_jump_exe(file, &jump_data, &jump_len, NULL); + jump_align = hiperiso_align(jump_len, 16); + + wim_data->jump_exe_len = jump_len; + wim_data->bin_raw_len = jump_align + sizeof(hiperiso_os_param) + windatalen + exe_len; + wim_data->bin_align_len = hiperiso_align(wim_data->bin_raw_len, 2048); + + wim_data->jump_bin_data = grub_malloc(wim_data->bin_align_len); + if (wim_data->jump_bin_data) + { + grub_memcpy(wim_data->jump_bin_data, jump_data, jump_len); + grub_memcpy(wim_data->jump_bin_data + jump_align + sizeof(hiperiso_os_param) + windatalen, exe_data, exe_len); + } + + debug("jump_exe_len:%u bin_raw_len:%u bin_align_len:%u\n", + wim_data->jump_exe_len, wim_data->bin_raw_len, wim_data->bin_align_len); + + return 0; +} + +static int hiperiso_get_windows_rtdata_len(const char *iso, int *flag) +{ + int size = 0; + int template_file_len = 0; + char *pos = NULL; + char *script = NULL; + install_template *template_node = NULL; + + *flag = 0; + size = (int)sizeof(hiperiso_windows_data); + + pos = grub_strstr(iso, "/"); + if (!pos) + { + return size; + } + + script = hiperiso_plugin_get_cur_install_template(pos, &template_node); + if (script) + { + (*flag) |= WINDATA_FLAG_TEMPLATE; + template_file_len = template_node->filelen; + } + + return size + template_file_len; +} + +static int hiperiso_fill_windows_rtdata(void *buf, char *isopath, int dataflag) +{ + int template_len = 0; + char *pos = NULL; + char *end = NULL; + char *script = NULL; + const char *env = NULL; + install_template *template_node = NULL; + hiperiso_windows_data *data = (hiperiso_windows_data *)buf; + + grub_memset(data, 0, sizeof(hiperiso_windows_data)); + + env = grub_env_get("HISO_WIN11_BYPASS_CHECK"); + if (env && env[0] == '1' && env[1] == 0) + { + data->windows11_bypass_check = 1; + } + + env = grub_env_get("HISO_WIN11_BYPASS_NRO"); + if (env && env[0] == '1' && env[1] == 0) + { + data->windows11_bypass_nro = 1; + } + + pos = grub_strstr(isopath, "/"); + if (!pos) + { + return 1; + } + + if (dataflag & WINDATA_FLAG_TEMPLATE) + { + script = hiperiso_plugin_get_cur_install_template(pos, &template_node); + if (script) + { + data->auto_install_len = template_len = template_node->filelen; + debug("auto install script OK <%s> \n", script, template_len); + end = hiperiso_str_last(script, '/'); + grub_snprintf(data->auto_install_script, sizeof(data->auto_install_script) - 1, "%s", end ? end + 1 : script); + grub_memcpy(data + 1, template_node->filebuf, template_len); + } + } + else + { + debug("auto install script skipped or not configed %s\n", pos); + } + + script = (char *)hiperiso_plugin_get_injection(pos); + if (script) + { + if (hiperiso_check_file_exist("%s%s", hiperiso_get_env("hiso_iso_part"), script)) + { + debug("injection archive <%s> OK\n", script); + grub_snprintf(data->injection_archive, sizeof(data->injection_archive) - 1, "%s", script); + } + else + { + debug("injection archive <%s> NOT exist\n", script); + } + } + else + { + debug("injection archive not configed %s\n", pos); + } + + return 0; +} + +static int hiperiso_update_before_chain(hiperiso_os_param *param, char *isopath) +{ + grub_uint32_t jump_align = 0; + wim_lookup_entry *meta_look = NULL; + wim_security_header *security = NULL; + wim_directory_entry *rootdir = NULL; + wim_header *head = NULL; + wim_lookup_entry *lookup = NULL; + wim_patch *node = NULL; + wim_tail *wim_data = NULL; + + for (node = g_wim_patch_head; node; node = node->next) + { + if (0 == node->valid) + { + continue; + } + + wim_data = &node->wim_data; + head = &wim_data->wim_header; + lookup = (wim_lookup_entry *)wim_data->new_lookup_data; + + jump_align = hiperiso_align(wim_data->jump_exe_len, 16); + if (wim_data->jump_bin_data) + { + grub_memcpy(wim_data->jump_bin_data + jump_align, param, sizeof(hiperiso_os_param)); + hiperiso_fill_windows_rtdata(wim_data->jump_bin_data + jump_align + sizeof(hiperiso_os_param), isopath, wim_data->windata_flag); + } + + grub_crypto_hash(GRUB_MD_SHA1, wim_data->bin_hash.sha1, wim_data->jump_bin_data, wim_data->bin_raw_len); + + security = (wim_security_header *)wim_data->new_meta_data; + if (security->len > 0) + { + rootdir = (wim_directory_entry *)(wim_data->new_meta_data + ((security->len + 7) & 0xFFFFFFF8U)); + } + else + { + rootdir = (wim_directory_entry *)(wim_data->new_meta_data + 8); + } + + /* update all winpeshl.exe dirent entry's hash */ + hiperiso_update_all_hash(node, wim_data->new_meta_data, rootdir); + + /* update winpeshl.exe lookup entry data (hash/offset/length) */ + if (node->replace_look) + { + debug("update replace lookup entry_id:%ld\n", ((long)node->replace_look - (long)lookup) / sizeof(wim_lookup_entry)); + node->replace_look->resource.raw_size = wim_data->bin_raw_len; + node->replace_look->resource.size_in_wim = wim_data->bin_raw_len; + node->replace_look->resource.flags = 0; + node->replace_look->resource.offset = wim_data->wim_align_size; + + grub_memcpy(node->replace_look->hash.sha1, wim_data->bin_hash.sha1, sizeof(wim_hash)); + } + + /* update metadata's hash */ + meta_look = hiperiso_find_meta_entry(head, lookup); + if (meta_look) + { + debug("find meta lookup entry_id:%ld\n", ((long)meta_look - (long)lookup) / sizeof(wim_lookup_entry)); + grub_memcpy(&meta_look->resource, &head->metadata, sizeof(wim_resource_header)); + grub_crypto_hash(GRUB_MD_SHA1, meta_look->hash.sha1, wim_data->new_meta_data, wim_data->new_meta_len); + } + } + + return 0; +} + +static int hiperiso_wimdows_locate_wim(const char *disk, wim_patch *patch, int windatalen) +{ + int rc; + grub_uint16_t i; + grub_file_t file; + grub_uint32_t exe_len; + grub_uint8_t *exe_data = NULL; + grub_uint8_t *decompress_data = NULL; + wim_lookup_entry *lookup = NULL; + wim_security_header *security = NULL; + wim_directory_entry *rootdir = NULL; + wim_directory_entry *search = NULL; + wim_stream_entry *stream = NULL; + wim_header *head = &(patch->wim_data.wim_header); + wim_tail *wim_data = &patch->wim_data; + + debug("windows locate wim start %s\n", patch->path); + + g_hiperiso_case_insensitive = 1; + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", disk, patch->path); + g_hiperiso_case_insensitive = 0; + + if (!file) + { + debug("File %s%s NOT exist\n", disk, patch->path); + return 1; + } + + hiperiso_get_override_info(file, &patch->wim_data); + + grub_file_seek(file, 0); + grub_file_read(file, head, sizeof(wim_header)); + + if (grub_memcmp(head->signature, WIM_HEAD_SIGNATURE, sizeof(head->signature))) + { + debug("Not a valid wim file %s\n", (char *)head->signature); + grub_file_close(file); + return 1; + } + + if (head->flags & FLAG_HEADER_COMPRESS_LZMS) + { + debug("LZMS compress is not supported 0x%x\n", head->flags); + grub_file_close(file); + return 1; + } + + rc = hiperiso_read_resource(file, head, &head->metadata, (void **)&decompress_data); + if (rc) + { + grub_printf("failed to read meta data %d\n", rc); + grub_file_close(file); + return 1; + } + + security = (wim_security_header *)decompress_data; + if (security->len > 0) + { + rootdir = (wim_directory_entry *)(decompress_data + ((security->len + 7) & 0xFFFFFFF8U)); + } + else + { + rootdir = (wim_directory_entry *)(decompress_data + 8); + } + + + debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size); + lookup = grub_malloc(head->lookup.raw_size); + grub_file_seek(file, head->lookup.offset); + grub_file_read(file, lookup, head->lookup.raw_size); + + + + /* search winpeshl.exe dirent entry */ + search = search_replace_wim_dirent(file, head, lookup, decompress_data, rootdir); + if (!search) + { + debug("Failed to find replace file %p\n", search); + grub_file_close(file); + return 1; + } + + debug("find replace file at %p\n", search); + + grub_memset(&patch->old_hash, 0, sizeof(wim_hash)); + if (grub_memcmp(&patch->old_hash, search->hash.sha1, sizeof(wim_hash)) == 0) + { + debug("search hash all 0, now do deep search\n"); + stream = (wim_stream_entry *)((char *)search + search->len); + for (i = 0; i < search->streams; i++) + { + if (stream->name_len == 0) + { + grub_memcpy(&patch->old_hash, stream->hash.sha1, sizeof(wim_hash)); + debug("new search hash: %02x %02x %02x %02x %02x %02x %02x %02x\n", + hiperiso_varg_8(patch->old_hash.sha1)); + break; + } + stream = (wim_stream_entry *)((char *)stream + stream->len); + } + } + else + { + grub_memcpy(&patch->old_hash, search->hash.sha1, sizeof(wim_hash)); + } + + + /* find and extact winpeshl.exe */ + patch->replace_look = hiperiso_find_look_entry(head, lookup, &patch->old_hash); + if (patch->replace_look) + { + exe_len = (grub_uint32_t)patch->replace_look->resource.raw_size; + debug("find replace lookup entry_id:%ld raw_size:%u\n", + ((long)patch->replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len); + + if (0 == hiperiso_read_resource(file, head, &(patch->replace_look->resource), (void **)&(exe_data))) + { + hiperiso_cat_exe_file_data(wim_data, exe_len, exe_data, windatalen); + grub_free(exe_data); + } + else + { + debug("failed to read replace file meta data %u\n", exe_len); + } + } + else + { + debug("failed to find lookup entry for replace file %02x %02x %02x %02x\n", + hiperiso_varg_4(patch->old_hash.sha1)); + } + + wim_data->wim_raw_size = (grub_uint32_t)file->size; + wim_data->wim_align_size = hiperiso_align(wim_data->wim_raw_size, 2048); + + grub_check_free(wim_data->new_meta_data); + wim_data->new_meta_data = decompress_data; + wim_data->new_meta_len = head->metadata.raw_size; + wim_data->new_meta_align_len = hiperiso_align(wim_data->new_meta_len, 2048); + + grub_check_free(wim_data->new_lookup_data); + wim_data->new_lookup_data = (grub_uint8_t *)lookup; + wim_data->new_lookup_len = (grub_uint32_t)head->lookup.raw_size; + wim_data->new_lookup_align_len = hiperiso_align(wim_data->new_lookup_len, 2048); + + head->metadata.flags = RESHDR_FLAG_METADATA; + head->metadata.offset = wim_data->wim_align_size + wim_data->bin_align_len; + head->metadata.size_in_wim = wim_data->new_meta_len; + head->metadata.raw_size = wim_data->new_meta_len; + + head->lookup.flags = 0; + head->lookup.offset = head->metadata.offset + wim_data->new_meta_align_len; + head->lookup.size_in_wim = wim_data->new_lookup_len; + head->lookup.raw_size = wim_data->new_lookup_len; + + grub_file_close(file); + + debug("%s", "windows locate wim finish\n"); + return 0; +} + +grub_err_t hiperiso_cmd_sel_winpe_wim(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i = 0; + int pos = 0; + int len = 0; + int find = 0; + char *cmd = NULL; + wim_patch *node = NULL; + wim_patch *tmp = NULL; + grub_file_t file = NULL; + wim_header *head = NULL; + char cfgfile[128]; + + (void)ctxt; + (void)argc; + + len = 8 * HISO_SIZE_1KB; + cmd = (char *)grub_malloc(len + sizeof(wim_header)); + if (!cmd) + { + return 1; + } + + head = (wim_header *)(cmd + len); + grub_env_unset("hiso_pe_wim_path"); + + for (node = g_wim_patch_head; node; node = node->next) + { + find = 0; + for (tmp = g_wim_patch_head; tmp != node; tmp = tmp->next) + { + if (tmp->valid && grub_strcasecmp(tmp->path, node->path) == 0) + { + find = 1; + break; + } + } + + if (find) + { + continue; + } + + g_hiperiso_case_insensitive = 1; + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s%s", args[0], node->path); + g_hiperiso_case_insensitive = 0; + if (!file) + { + debug("File %s%s NOT exist\n", args[0], node->path); + continue; + } + + grub_file_read(file, head, sizeof(wim_header)); + if (grub_memcmp(head->signature, WIM_HEAD_SIGNATURE, sizeof(head->signature))) + { + debug("Not a valid wim file %s\n", (char *)head->signature); + grub_file_close(file); + continue; + } + + if (head->flags & FLAG_HEADER_COMPRESS_LZMS) + { + debug("LZMS compress is not supported 0x%x\n", head->flags); + grub_file_close(file); + continue; + } + + grub_file_close(file); + node->valid = 1; + + hiso_len_ssprintf(cmd, pos, len, "menuentry \"%s\" --class=\"sel_wim\" {\n echo \"\"\n}\n", node->path); + } + + if (pos > 0) + { + g_hiperiso_menu_esc = 1; + g_hiperiso_suppress_esc = 1; + g_hiperiso_suppress_esc_default = 0; + g_hiperiso_secondary_menu_on = 1; + + grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)cmd, pos); + grub_script_execute_sourcecode(cfgfile); + + g_hiperiso_menu_esc = 0; + g_hiperiso_suppress_esc = 0; + g_hiperiso_suppress_esc_default = 1; + g_hiperiso_secondary_menu_on = 0; + + for (node = g_wim_patch_head; node; node = node->next) + { + if (node->valid) + { + if (i == g_hiperiso_last_entry) + { + grub_env_set("hiso_pe_wim_path", node->path); + break; + } + i++; + } + } + } + + grub_free(cmd); + return 0; +} + +grub_err_t hiperiso_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int datalen = 0; + int dataflag = 0; + wim_patch *node = g_wim_patch_head; + + (void)ctxt; + (void)argc; + (void)args; + + datalen = hiperiso_get_windows_rtdata_len(args[1], &dataflag); + + while (node) + { + node->wim_data.windata_flag = dataflag; + if (0 == hiperiso_wimdows_locate_wim(args[0], node, datalen)) + { + node->valid = 1; + g_wim_valid_patch_count++; + } + + node = node->next; + } + + return 0; +} + +static grub_uint32_t hiperiso_get_override_chunk_num(void) +{ + grub_uint32_t chunk_num = 0; + + if (g_iso_fs_type == 0) + { + /* ISO9660: */ + /* per wim */ + /* 1: file_size and file_offset */ + /* 2: new wim file header */ + chunk_num = g_wim_valid_patch_count * 2; + } + else + { + /* UDF: */ + /* global: */ + /* 1: block count in Partition Descriptor */ + + /* per wim */ + /* 1: file_size in file_entry or extend_file_entry */ + /* 2: data_size and position in extend data short ad */ + /* 3: new wim file header */ + chunk_num = g_wim_valid_patch_count * 3 + 1; + } + + if (g_suppress_wincd_override_offset > 0) + { + chunk_num++; + } + + return chunk_num; +} + +static void hiperiso_fill_suppress_wincd_override_data(void *override) +{ + hiperiso_override_chunk *cur = (hiperiso_override_chunk *)override; + + cur->override_size = 4; + cur->img_offset = g_suppress_wincd_override_offset; + grub_memcpy(cur->override_data, &g_suppress_wincd_override_data, cur->override_size); +} + +static void hiperiso_windows_fill_override_data_iso9660( grub_uint64_t isosize, void *override) +{ + grub_uint64_t sector; + grub_uint32_t new_wim_size; + hiperiso_override_chunk *cur; + wim_patch *node = NULL; + wim_tail *wim_data = NULL; + hiperiso_iso9660_override *dirent = NULL; + + sector = (isosize + 2047) / 2048; + + cur = (hiperiso_override_chunk *)override; + + if (g_suppress_wincd_override_offset > 0) + { + hiperiso_fill_suppress_wincd_override_data(cur); + cur++; + } + + debug("hiperiso_windows_fill_override_data_iso9660 %lu\n", (ulong)isosize); + + for (node = g_wim_patch_head; node; node = node->next) + { + wim_data = &node->wim_data; + if (0 == node->valid) + { + continue; + } + + new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + + wim_data->new_meta_align_len + wim_data->new_lookup_align_len; + + dirent = (hiperiso_iso9660_override *)wim_data->override_data; + + dirent->first_sector = (grub_uint32_t)sector; + dirent->size = new_wim_size; + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + + sector += (new_wim_size / 2048); + + /* override 1: position and length in dirent */ + cur->img_offset = wim_data->override_offset; + cur->override_size = wim_data->override_len; + grub_memcpy(cur->override_data, wim_data->override_data, cur->override_size); + cur++; + + /* override 2: new wim file header */ + cur->img_offset = wim_data->file_offset; + cur->override_size = sizeof(wim_header); + grub_memcpy(cur->override_data, &(wim_data->wim_header), cur->override_size); + cur++; + } + + return; +} + +static int hiperiso_windows_fill_udf_short_ad(grub_file_t isofile, grub_uint32_t curpos, + wim_tail *wim_data, grub_uint32_t new_wim_size) +{ + int i; + grub_uint32_t total = 0; + grub_uint32_t left_size = 0; + hiperiso_udf_override *udf = NULL; + hiperiso_udf_override tmp[4]; + + grub_memset(tmp, 0, sizeof(tmp)); + grub_file_seek(isofile, wim_data->override_offset); + grub_file_read(isofile, tmp, sizeof(tmp)); + + left_size = new_wim_size; + udf = (hiperiso_udf_override *)wim_data->override_data; + + for (i = 0; i < 4; i++) + { + total += tmp[i].length; + if (total >= wim_data->wim_raw_size) + { + udf->length = left_size; + udf->position = curpos; + return 0; + } + else + { + udf->length = tmp[i].length; + udf->position = curpos; + } + + left_size -= tmp[i].length; + curpos += udf->length / 2048; + udf++; + wim_data->override_len += sizeof(hiperiso_udf_override); + } + + debug("######## Too many udf ad ######\n"); + return 1; +} + +static void hiperiso_windows_fill_override_data_udf(grub_file_t isofile, void *override) +{ + grub_uint32_t data32; + grub_uint64_t data64; + grub_uint64_t sector; + grub_uint32_t new_wim_size; + grub_uint64_t total_wim_size = 0; + grub_uint32_t udf_start_block = 0; + hiperiso_override_chunk *cur; + wim_patch *node = NULL; + wim_tail *wim_data = NULL; + + sector = (isofile->size + 2047) / 2048; + + cur = (hiperiso_override_chunk *)override; + + if (g_suppress_wincd_override_offset > 0) + { + hiperiso_fill_suppress_wincd_override_data(cur); + cur++; + } + + debug("hiperiso_windows_fill_override_data_udf %lu\n", (ulong)isofile->size); + + for (node = g_wim_patch_head; node; node = node->next) + { + wim_data = &node->wim_data; + if (node->valid) + { + if (udf_start_block == 0) + { + udf_start_block = wim_data->udf_start_block; + } + new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + + wim_data->new_meta_align_len + wim_data->new_lookup_align_len; + total_wim_size += new_wim_size; + } + } + + //override 1: sector number in pd data + cur->img_offset = grub_udf_get_last_pd_size_offset(); + cur->override_size = 4; + data32 = sector - udf_start_block + (total_wim_size / 2048); + grub_memcpy(cur->override_data, &(data32), 4); + + for (node = g_wim_patch_head; node; node = node->next) + { + wim_data = &node->wim_data; + if (0 == node->valid) + { + continue; + } + + new_wim_size = wim_data->wim_align_size + wim_data->bin_align_len + + wim_data->new_meta_align_len + wim_data->new_lookup_align_len; + + //override 2: filesize in file_entry + cur++; + cur->img_offset = wim_data->fe_entry_size_offset; + cur->override_size = 8; + data64 = new_wim_size; + grub_memcpy(cur->override_data, &(data64), 8); + + /* override 3: position and length in extend data */ + hiperiso_windows_fill_udf_short_ad(isofile, (grub_uint32_t)sector - udf_start_block, wim_data, new_wim_size); + + sector += (new_wim_size / 2048); + + cur++; + cur->img_offset = wim_data->override_offset; + cur->override_size = wim_data->override_len; + grub_memcpy(cur->override_data, wim_data->override_data, cur->override_size); + + /* override 4: new wim file header */ + cur++; + cur->img_offset = wim_data->file_offset; + cur->override_size = sizeof(wim_header); + grub_memcpy(cur->override_data, &(wim_data->wim_header), cur->override_size); + } + + return; +} + +static grub_uint32_t hiperiso_windows_get_virt_data_size(void) +{ + grub_uint32_t size = 0; + wim_tail *wim_data = NULL; + wim_patch *node = g_wim_patch_head; + + while (node) + { + if (node->valid) + { + wim_data = &node->wim_data; + size += sizeof(hiperiso_virt_chunk) + wim_data->bin_align_len + + wim_data->new_meta_align_len + wim_data->new_lookup_align_len; + } + node = node->next; + } + + return size; +} + +static void hiperiso_windows_fill_virt_data( grub_uint64_t isosize, hiperiso_chain_head *chain) +{ + grub_uint64_t sector; + grub_uint32_t offset; + grub_uint32_t wim_secs; + grub_uint32_t mem_secs; + char *override = NULL; + hiperiso_virt_chunk *cur = NULL; + wim_tail *wim_data = NULL; + wim_patch *node = NULL; + + sector = (isosize + 2047) / 2048; + offset = sizeof(hiperiso_virt_chunk) * g_wim_valid_patch_count; + + override = (char *)chain + chain->virt_chunk_offset; + cur = (hiperiso_virt_chunk *)override; + + for (node = g_wim_patch_head; node; node = node->next) + { + if (0 == node->valid) + { + continue; + } + + wim_data = &node->wim_data; + + wim_secs = wim_data->wim_align_size / 2048; + mem_secs = (wim_data->bin_align_len + wim_data->new_meta_align_len + wim_data->new_lookup_align_len) / 2048; + + cur->remap_sector_start = sector; + cur->remap_sector_end = cur->remap_sector_start + wim_secs; + cur->org_sector_start = (grub_uint32_t)(wim_data->file_offset / 2048); + + cur->mem_sector_start = cur->remap_sector_end; + cur->mem_sector_end = cur->mem_sector_start + mem_secs; + cur->mem_sector_offset = offset; + + sector += wim_secs + mem_secs; + cur++; + + grub_memcpy(override + offset, wim_data->jump_bin_data, wim_data->bin_raw_len); + offset += wim_data->bin_align_len; + + grub_memcpy(override + offset, wim_data->new_meta_data, wim_data->new_meta_len); + offset += wim_data->new_meta_align_len; + + grub_memcpy(override + offset, wim_data->new_lookup_data, wim_data->new_lookup_len); + offset += wim_data->new_lookup_align_len; + + chain->virt_img_size_in_bytes += wim_data->wim_align_size + + wim_data->bin_align_len + + wim_data->new_meta_align_len + + wim_data->new_lookup_align_len; + } + + return; +} + +static int hiperiso_windows_drive_map(hiperiso_chain_head *chain, int vlnk) +{ + int hd1 = 0; + grub_disk_t disk; + + debug("drive map begin <%p> <%d> ...\n", chain, vlnk); + + disk = grub_disk_open("hd1"); + if (disk) + { + grub_disk_close(disk); + hd1 = 1; + debug("BIOS hd1 exist\n"); + } + else + { + debug("failed to open disk %s\n", "hd1"); + } + + if (vlnk) + { + if (g_hiperiso_disk_bios_id == 0x80 && hd1) + { + debug("drive map needed vlnk %p\n", disk); + chain->drive_map = 0x81; + } + } + else if (chain->disk_drive == 0x80) + { + if (hd1) + { + debug("drive map needed normal %p\n", disk); + chain->drive_map = 0x81; + } + } + else + { + debug("no need to map 0x%x\n", chain->disk_drive); + } + + return 0; +} + +static int hiperiso_suppress_windows_cd_prompt(void) +{ + int rc = 1; + const char *cdprompt = NULL; + grub_uint64_t readpos = 0; + grub_file_t file = NULL; + grub_uint8_t data[32]; + + cdprompt = hiperiso_get_env("HISO_WINDOWS_CD_PROMPT"); + if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0) + { + debug("HISO_WINDOWS_CD_PROMPT:<%s>\n", cdprompt); + return 0; + } + + g_hiperiso_case_insensitive = 1; + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s/boot/bootfix.bin", "(loop)"); + g_hiperiso_case_insensitive = 0; + + if (!file) + { + debug("Failed to open %s\n", "bootfix.bin"); + goto end; + } + + grub_file_read(file, data, 32); + + if (file->fs && file->fs->name && grub_strcmp(file->fs->name, "udf") == 0) + { + readpos = grub_udf_get_file_offset(file); + } + else + { + readpos = grub_iso9660_get_last_read_pos(file); + } + + debug("bootfix.bin readpos:%lu (sector:%lu) data: %02x %02x %02x %02x\n", + (ulong)readpos, (ulong)readpos / 2048, data[24], data[25], data[26], data[27]); + + if (*(grub_uint32_t *)(data + 24) == 0x13cd0080) + { + g_suppress_wincd_override_offset = readpos + 24; + g_suppress_wincd_override_data = 0x13cd00fd; + + rc = 0; + } + + debug("g_suppress_wincd_override_offset:%lu\n", (ulong)g_suppress_wincd_override_offset); + +end: + check_free(file, grub_file_close); + + return rc; +} + +static int hiperiso_extract_init_exe(char *wimfile, grub_uint8_t **pexe_data, grub_uint32_t *pexe_len, char *exe_name) +{ + int rc; + int ret = 1; + grub_uint16_t i; + grub_file_t file = NULL; + grub_uint32_t exe_len = 0; + wim_header *head = NULL; + grub_uint16_t *uname = NULL; + grub_uint8_t *exe_data = NULL; + grub_uint8_t *decompress_data = NULL; + wim_lookup_entry *lookup = NULL; + wim_security_header *security = NULL; + wim_directory_entry *rootdir = NULL; + wim_directory_entry *search = NULL; + wim_stream_entry *stream = NULL; + wim_lookup_entry *replace_look = NULL; + wim_header wimhdr; + wim_hash hashdata; + + head = &wimhdr; + + file = grub_file_open(wimfile, HIPERISO_FILE_TYPE); + if (!file) + { + goto out; + } + + grub_file_read(file, head, sizeof(wim_header)); + rc = hiperiso_read_resource(file, head, &head->metadata, (void **)&decompress_data); + if (rc) + { + grub_printf("failed to read meta data %d\n", rc); + goto out; + } + + security = (wim_security_header *)decompress_data; + if (security->len > 0) + { + rootdir = (wim_directory_entry *)(decompress_data + ((security->len + 7) & 0xFFFFFFF8U)); + } + else + { + rootdir = (wim_directory_entry *)(decompress_data + 8); + } + + debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size); + lookup = grub_malloc(head->lookup.raw_size); + grub_file_seek(file, head->lookup.offset); + grub_file_read(file, lookup, head->lookup.raw_size); + + /* search winpeshl.exe dirent entry */ + search = search_replace_wim_dirent(file, head, lookup, decompress_data, rootdir); + if (!search) + { + debug("Failed to find replace file %p\n", search); + goto out; + } + + uname = (grub_uint16_t *)(search + 1); + for (i = 0; i < search->name_len / 2 && i < 200; i++) + { + exe_name[i] = (char)uname[i]; + } + exe_name[i] = 0; + debug("find replace file at %p <%s>\n", search, exe_name); + + grub_memset(&hashdata, 0, sizeof(wim_hash)); + if (grub_memcmp(&hashdata, search->hash.sha1, sizeof(wim_hash)) == 0) + { + debug("search hash all 0, now do deep search\n"); + stream = (wim_stream_entry *)((char *)search + search->len); + for (i = 0; i < search->streams; i++) + { + if (stream->name_len == 0) + { + grub_memcpy(&hashdata, stream->hash.sha1, sizeof(wim_hash)); + debug("new search hash: %02x %02x %02x %02x %02x %02x %02x %02x\n", + hiperiso_varg_8(hashdata.sha1)); + break; + } + stream = (wim_stream_entry *)((char *)stream + stream->len); + } + } + else + { + grub_memcpy(&hashdata, search->hash.sha1, sizeof(wim_hash)); + } + + /* find and extact winpeshl.exe */ + replace_look = hiperiso_find_look_entry(head, lookup, &hashdata); + if (replace_look) + { + exe_len = (grub_uint32_t)replace_look->resource.raw_size; + debug("find replace lookup entry_id:%ld raw_size:%u\n", + ((long)replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len); + + if (0 != hiperiso_read_resource(file, head, &(replace_look->resource), (void **)&(exe_data))) + { + exe_len = 0; + exe_data = NULL; + debug("failed to read replace file meta data %u\n", exe_len); + } + } + else + { + debug("failed to find lookup entry for replace file %02x %02x %02x %02x\n", + hiperiso_varg_4(hashdata.sha1)); + } + + if (exe_data) + { + ret = 0; + *pexe_data = exe_data; + *pexe_len = exe_len; + } + +out: + + grub_check_free(lookup); + grub_check_free(decompress_data); + check_free(file, grub_file_close); + + return ret; +} + +grub_err_t hiperiso_cmd_windows_wimboot_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int rc = 0; + int wim64 = 0; + int datalen = 0; + int dataflag = 0; + grub_uint32_t exe_len = 0; + grub_uint32_t jump_align = 0; + const char *addr = NULL; + hiperiso_chain_head *chain = NULL; + grub_uint8_t *param = NULL; + grub_uint8_t *exe_data = NULL; + hiperiso_windows_data *rtdata = NULL; + char exename[128] = {0}; + wim_tail wim_data; + + (void)ctxt; + (void)argc; + + addr = grub_env_get("hiso_chain_mem_addr"); + if (!addr) + { + debug("Failed to find hiso_chain_mem_addr\n"); + return 1; + } + + chain = (hiperiso_chain_head *)(void *)grub_strtoul(addr, NULL, 16); + + if (grub_memcmp(&g_hiperiso_guid, &chain->os_param.guid, 16) != 0) + { + debug("os_param.guid not match\n"); + return 1; + } + + datalen = hiperiso_get_windows_rtdata_len(chain->os_param.hiso_img_path, &dataflag); + + rc = hiperiso_extract_init_exe(args[0], &exe_data, &exe_len, exename); + if (rc) + { + return 1; + } + wim64 = hiperiso_is_pe64(exe_data); + + grub_memset(&wim_data, 0, sizeof(wim_data)); + hiperiso_cat_exe_file_data(&wim_data, exe_len, exe_data, datalen); + grub_check_free(exe_data); + + jump_align = hiperiso_align(wim_data.jump_exe_len, 16); + param = wim_data.jump_bin_data; + + grub_memcpy(param + jump_align, &chain->os_param, sizeof(hiperiso_os_param)); + + rtdata = (hiperiso_windows_data *)(param + jump_align + sizeof(hiperiso_os_param)); + hiperiso_fill_windows_rtdata(rtdata, chain->os_param.hiso_img_path, dataflag); + + hiperiso_memfile_env_set("hiso_wimboot_mem", param, (ulonglong)(wim_data.bin_align_len)); + + grub_env_set(args[1], exename); + grub_env_set(args[2], wim64 ? "64" : "32"); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int unknown_image = 0; + int hiperiso_compatible = 0; + grub_uint32_t size = 0; + grub_uint64_t isosize = 0; + grub_uint32_t boot_catlog = 0; + grub_uint32_t img_chunk_size = 0; + grub_uint32_t override_size = 0; + grub_uint32_t virt_chunk_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + const char *compatible; + hiperiso_chain_head *chain; + + (void)ctxt; + (void)argc; + + debug("chain data begin <%s> ...\n", args[0]); + + compatible = grub_env_get("hiperiso_compatible"); + if (compatible && compatible[0] == 'Y') + { + hiperiso_compatible = 1; + } + + if (NULL == g_img_chunk_list.chunk) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + if (0 == hiperiso_compatible && g_wim_valid_patch_count == 0) + { + unknown_image = 1; + if (!g_hiperiso_wimboot_mode) + { + debug("Warning: %s was not recognized by Hiperiso\n", args[0]); + } + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + return 1; + } + + isosize = file->size; + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + if (boot_catlog) + { + if (hiperiso_is_efi_os() && (!hiperiso_has_efi_eltorito(file, boot_catlog))) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + } + else + { + if (hiperiso_is_efi_os()) + { + grub_env_set("LoadIsoEfiDriver", "on"); + } + else + { + return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]); + } + } + + g_suppress_wincd_override_offset = 0; + if (!hiperiso_is_efi_os()) /* legacy mode */ + { + hiperiso_suppress_windows_cd_prompt(); + } + + img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + + if (hiperiso_compatible || unknown_image) + { + override_size = g_suppress_wincd_override_offset > 0 ? sizeof(hiperiso_override_chunk) : 0; + size = sizeof(hiperiso_chain_head) + img_chunk_size + override_size; + } + else + { + override_size = hiperiso_get_override_chunk_num() * sizeof(hiperiso_override_chunk); + virt_chunk_size = hiperiso_windows_get_virt_data_size(); + size = sizeof(hiperiso_chain_head) + img_chunk_size + override_size + virt_chunk_size; + } + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain win1 memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_windows; + hiperiso_fill_os_param(file, &(chain->os_param)); + + if (0 == unknown_image) + { + hiperiso_update_before_chain(&(chain->os_param), args[0]); + } + + /* part 2: chain head */ + disk = file->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + chain->real_img_size_in_bytes = file->size; + chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048; + chain->boot_catalog = boot_catlog; + + if (!hiperiso_is_efi_os()) + { + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector)); + } + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_img_chunk_list.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size); + + if (hiperiso_compatible || unknown_image) + { + if (g_suppress_wincd_override_offset > 0) + { + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size; + chain->override_chunk_num = 1; + hiperiso_fill_suppress_wincd_override_data((char *)chain + chain->override_chunk_offset); + } + + return 0; + } + + if (0 == g_wim_valid_patch_count) + { + return 0; + } + + /* part 4: override chunk */ + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size; + chain->override_chunk_num = hiperiso_get_override_chunk_num(); + + if (g_iso_fs_type == 0) + { + hiperiso_windows_fill_override_data_iso9660(isosize, (char *)chain + chain->override_chunk_offset); + } + else + { + hiperiso_windows_fill_override_data_udf(file, (char *)chain + chain->override_chunk_offset); + } + + /* part 5: virt chunk */ + chain->virt_chunk_offset = chain->override_chunk_offset + override_size; + chain->virt_chunk_num = g_wim_valid_patch_count; + hiperiso_windows_fill_virt_data(isosize, chain); + + if (hiperiso_is_efi_os() == 0) + { + hiperiso_windows_drive_map(chain, file->vlnk); + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_uint32_t hiperiso_get_wim_iso_offset(const char *filepath) +{ + grub_uint32_t imgoffset; + grub_file_t file; + char cmdbuf[128]; + + grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback wimiso \"%s\"", filepath); + grub_script_execute_sourcecode(cmdbuf); + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", "(wimiso)/boot/boot.wim"); + if (!file) + { + grub_printf("Failed to open boot.wim file in the image file\n"); + return 0; + } + + imgoffset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file) + 2; + + debug("wimiso wim direct offset: %u\n", imgoffset); + + grub_file_close(file); + + grub_script_execute_sourcecode("loopback -d wimiso"); + + return imgoffset; +} + +static int hiperiso_get_wim_chunklist(grub_file_t wimfile, hiperiso_img_chunk_list *wimchunk) +{ + grub_memset(wimchunk, 0, sizeof(hiperiso_img_chunk_list)); + wimchunk->chunk = grub_malloc(sizeof(hiperiso_img_chunk) * DEFAULT_CHUNK_NUM); + if (NULL == wimchunk->chunk) + { + return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n"); + } + + wimchunk->max_chunk = DEFAULT_CHUNK_NUM; + wimchunk->cur_chunk = 0; + + hiperiso_get_block_list(wimfile, wimchunk, wimfile->device->disk->partition->start); + + return 0; +} + +grub_err_t hiperiso_cmd_is_standard_winiso(grub_extcmd_context_t ctxt, int argc, char **args) +{ + int i; + int ret = 1; + char prefix[32] = {0}; + const char *chkfile[] = + { + "boot/bcd", "boot/boot.sdi", NULL + }; + + (void)ctxt; + (void)argc; + + if (hiperiso_check_file_exist("%s/sources/boot.wim", args[0])) + { + prefix[0] = 0; + } + else if (hiperiso_check_file_exist("%s/x86/sources/boot.wim", args[0])) + { + grub_snprintf(prefix, sizeof(prefix), "/x86"); + } + else if (hiperiso_check_file_exist("%s/x64/sources/boot.wim", args[0])) + { + grub_snprintf(prefix, sizeof(prefix), "/x64"); + } + else + { + debug("No boot.wim found.\n"); + goto out; + } + + for (i = 0; chkfile[i]; i++) + { + if (!hiperiso_check_file_exist("%s%s/%s", args[0], prefix, chkfile[i])) + { + debug("%s not found.\n", chkfile[i]); + goto out; + } + } + + if ((!hiperiso_check_file_exist("%s%s/sources/install.wim", args[0], prefix)) && + (!hiperiso_check_file_exist("%s%s/sources/install.esd", args[0], prefix))) + { + debug("No install.wim(esd) found.\n"); + goto out; + } + + if (!hiperiso_check_file_exist("%s/setup.exe", args[0])) + { + debug("No setup.exe found.\n"); + goto out; + } + + ret = 0; + debug("This is standard Windows ISO.\n"); + +out: + + return ret; +} + +grub_err_t hiperiso_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint32_t boot_index; + grub_file_t file = NULL; + wim_header *wimhdr = NULL; + + (void)ctxt; + (void)argc; + + wimhdr = grub_zalloc(sizeof(wim_header)); + if (!wimhdr) + { + return 1; + } + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", args[0]); + if (!file) + { + grub_free(wimhdr); + return 1; + } + + grub_file_read(file, wimhdr, sizeof(wim_header)); + grub_file_close(file); + boot_index = wimhdr->boot_index; + grub_free(wimhdr); + + if (boot_index == 0) + { + return 1; + } + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_vlnk_wim_chain_data(grub_file_t wimfile) +{ + grub_uint32_t i = 0; + grub_uint32_t imgoffset = 0; + grub_uint32_t size = 0; + grub_uint32_t isosector = 0; + grub_uint64_t wimsize = 0; + grub_uint32_t boot_catlog = 0; + grub_uint32_t img_chunk1_size = 0; + grub_uint32_t img_chunk2_size = 0; + grub_uint32_t override_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + hiperiso_chain_head *chain; + hiperiso_iso9660_override *dirent; + hiperiso_img_chunk *chunknode; + hiperiso_override_chunk *override; + hiperiso_img_chunk_list wimchunk; + + debug("vlnk wim chain data begin <%s> ...\n", wimfile->name); + + if (NULL == g_wimiso_chunk_list.chunk || NULL == g_wimiso_path) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + imgoffset = hiperiso_get_wim_iso_offset(g_wimiso_path); + if (imgoffset == 0) + { + grub_printf("image offset not found\n"); + return 1; + } + + if (0 != hiperiso_get_wim_chunklist(wimfile, &wimchunk)) + { + grub_printf("Failed to get wim chunklist\n"); + return 1; + } + wimsize = wimfile->size; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", g_wimiso_path); + if (!file) + { + return 1; + } + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + + img_chunk1_size = g_wimiso_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + img_chunk2_size = wimchunk.cur_chunk * sizeof(hiperiso_img_chunk); + override_size = sizeof(hiperiso_override_chunk) + g_wimiso_size; + + size = sizeof(hiperiso_chain_head) + img_chunk1_size + img_chunk2_size + override_size; + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain win2 memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_wim; + hiperiso_fill_os_param(wimfile, &(chain->os_param)); + + /* part 2: chain head */ + disk = wimfile->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + chain->real_img_size_in_bytes = hiperiso_align_2k(file->size) + hiperiso_align_2k(wimsize); + chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes; + chain->boot_catalog = boot_catlog; + + if (!hiperiso_is_efi_os()) + { + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector)); + } + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_wimiso_chunk_list.cur_chunk + wimchunk.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_wimiso_chunk_list.chunk, img_chunk1_size); + + chunknode = (hiperiso_img_chunk *)((char *)chain + chain->img_chunk_offset); + for (i = 0; i < g_wimiso_chunk_list.cur_chunk; i++) + { + chunknode->disk_end_sector = chunknode->disk_end_sector - chunknode->disk_start_sector; + chunknode->disk_start_sector = 0; + chunknode++; + } + + /* fs cluster size >= 2048, so don't need to proc align */ + + /* align by 2048 */ + chunknode = wimchunk.chunk + wimchunk.cur_chunk - 1; + i = (chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) % 4; + if (i) + { + chunknode->disk_end_sector += 4 - i; + } + + isosector = (grub_uint32_t)((file->size + 2047) / 2048); + for (i = 0; i < wimchunk.cur_chunk; i++) + { + chunknode = wimchunk.chunk + i; + chunknode->img_start_sector = isosector; + chunknode->img_end_sector = chunknode->img_start_sector + + ((chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) / 4) - 1; + isosector = chunknode->img_end_sector + 1; + } + + grub_memcpy((char *)chain + chain->img_chunk_offset + img_chunk1_size, wimchunk.chunk, img_chunk2_size); + + /* part 4: override chunk */ + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk1_size + img_chunk2_size; + chain->override_chunk_num = 1; + + override = (hiperiso_override_chunk *)((char *)chain + chain->override_chunk_offset); + override->img_offset = 0; + override->override_size = g_wimiso_size; + + grub_file_seek(file, 0); + grub_file_read(file, override->override_data, file->size); + + dirent = (hiperiso_iso9660_override *)(override->override_data + imgoffset); + dirent->first_sector = (grub_uint32_t)((file->size + 2047) / 2048); + dirent->size = (grub_uint32_t)(wimsize); + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + + debug("imgoffset=%u first_sector=0x%x size=0x%x\n", imgoffset, dirent->first_sector, dirent->size); + + if (hiperiso_is_efi_os() == 0) + { + hiperiso_windows_drive_map(chain, 0); + } + + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +static grub_err_t hiperiso_normal_wim_chain_data(grub_file_t wimfile) +{ + grub_uint32_t i = 0; + grub_uint32_t imgoffset = 0; + grub_uint32_t size = 0; + grub_uint32_t isosector = 0; + grub_uint64_t wimsize = 0; + grub_uint32_t boot_catlog = 0; + grub_uint32_t img_chunk1_size = 0; + grub_uint32_t img_chunk2_size = 0; + grub_uint32_t override_size = 0; + grub_file_t file; + grub_disk_t disk; + const char *pLastChain = NULL; + hiperiso_chain_head *chain; + hiperiso_iso9660_override *dirent; + hiperiso_img_chunk *chunknode; + hiperiso_override_chunk *override; + hiperiso_img_chunk_list wimchunk; + + debug("normal wim chain data begin <%s> ...\n", wimfile->name); + + if (NULL == g_wimiso_chunk_list.chunk || NULL == g_wimiso_path) + { + grub_printf("hiperiso not ready\n"); + return 1; + } + + imgoffset = hiperiso_get_wim_iso_offset(g_wimiso_path); + if (imgoffset == 0) + { + grub_printf("image offset not found\n"); + return 1; + } + + if (0 != hiperiso_get_wim_chunklist(wimfile, &wimchunk)) + { + grub_printf("Failed to get wim chunklist\n"); + return 1; + } + wimsize = wimfile->size; + + file = hiperiso_grub_file_open(HIPERISO_FILE_TYPE, "%s", g_wimiso_path); + if (!file) + { + return 1; + } + + boot_catlog = hiperiso_get_iso_boot_catlog(file); + + img_chunk1_size = g_wimiso_chunk_list.cur_chunk * sizeof(hiperiso_img_chunk); + img_chunk2_size = wimchunk.cur_chunk * sizeof(hiperiso_img_chunk); + override_size = sizeof(hiperiso_override_chunk); + + size = sizeof(hiperiso_chain_head) + img_chunk1_size + img_chunk2_size + override_size; + + pLastChain = grub_env_get("hiso_chain_mem_addr"); + if (pLastChain) + { + chain = (hiperiso_chain_head *)grub_strtoul(pLastChain, NULL, 16); + if (chain) + { + debug("free last chain memory %p\n", chain); + grub_free(chain); + } + } + + chain = hiperiso_alloc_chain(size); + if (!chain) + { + grub_printf("Failed to alloc chain win3 memory size %u\n", size); + grub_file_close(file); + return 1; + } + + hiperiso_memfile_env_set("hiso_chain_mem", chain, (ulonglong)size); + + grub_memset(chain, 0, sizeof(hiperiso_chain_head)); + + /* part 1: os parameter */ + g_hiperiso_chain_type = hiperiso_chain_wim; + hiperiso_fill_os_param(file, &(chain->os_param)); + + /* part 2: chain head */ + disk = file->device->disk; + chain->disk_drive = disk->id; + chain->disk_sector_size = (1 << disk->log_sector_size); + chain->real_img_size_in_bytes = hiperiso_align_2k(file->size) + hiperiso_align_2k(wimsize); + chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes; + chain->boot_catalog = boot_catlog; + + if (!hiperiso_is_efi_os()) + { + grub_file_seek(file, boot_catlog * 2048); + grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector)); + } + + /* part 3: image chunk */ + chain->img_chunk_offset = sizeof(hiperiso_chain_head); + chain->img_chunk_num = g_wimiso_chunk_list.cur_chunk + wimchunk.cur_chunk; + grub_memcpy((char *)chain + chain->img_chunk_offset, g_wimiso_chunk_list.chunk, img_chunk1_size); + + /* fs cluster size >= 2048, so don't need to proc align */ + + /* align by 2048 */ + chunknode = wimchunk.chunk + wimchunk.cur_chunk - 1; + i = (chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) % 4; + if (i) + { + chunknode->disk_end_sector += 4 - i; + } + + isosector = (grub_uint32_t)((file->size + 2047) / 2048); + for (i = 0; i < wimchunk.cur_chunk; i++) + { + chunknode = wimchunk.chunk + i; + chunknode->img_start_sector = isosector; + chunknode->img_end_sector = chunknode->img_start_sector + + ((chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) / 4) - 1; + isosector = chunknode->img_end_sector + 1; + } + + grub_memcpy((char *)chain + chain->img_chunk_offset + img_chunk1_size, wimchunk.chunk, img_chunk2_size); + + /* part 4: override chunk */ + chain->override_chunk_offset = chain->img_chunk_offset + img_chunk1_size + img_chunk2_size; + chain->override_chunk_num = 1; + + override = (hiperiso_override_chunk *)((char *)chain + chain->override_chunk_offset); + override->img_offset = imgoffset; + override->override_size = sizeof(hiperiso_iso9660_override); + + dirent = (hiperiso_iso9660_override *)(override->override_data); + dirent->first_sector = (grub_uint32_t)((file->size + 2047) / 2048); + dirent->size = (grub_uint32_t)(wimsize); + dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector); + dirent->size_be = grub_swap_bytes32(dirent->size); + + debug("imgoffset=%u first_sector=0x%x size=0x%x\n", imgoffset, dirent->first_sector, dirent->size); + + if (hiperiso_is_efi_os() == 0) + { + hiperiso_windows_drive_map(chain, 0); + } + + grub_file_close(file); + + HIPERISO_CMD_RETURN(GRUB_ERR_NONE); +} + +grub_err_t hiperiso_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_err_t ret; + grub_file_t wimfile; + + (void)ctxt; + (void)argc; + + wimfile = grub_file_open(args[0], HIPERISO_FILE_TYPE); + if (!wimfile) + { + return 1; + } + + if (wimfile->vlnk) + { + ret = hiperiso_vlnk_wim_chain_data(wimfile); + } + else + { + ret = hiperiso_normal_wim_chain_data(wimfile); + } + + grub_file_close(wimfile); + return ret; +} + +int hiperiso_chain_file_size(const char *path) +{ + int size; + grub_file_t file; + + file = grub_file_open(path, HIPERISO_FILE_TYPE); + size = (int)(file->size); + + grub_file_close(file); + + return size; +} + +int hiperiso_chain_file_read(const char *path, int offset, int len, void *buf) +{ + int size; + grub_file_t file; + + file = grub_file_open(path, HIPERISO_FILE_TYPE); + grub_file_seek(file, offset); + size = grub_file_read(file, buf, len); + grub_file_close(file); + + return size; +} + diff --git a/src/grub2/huffman.c b/src/grub2/huffman.c new file mode 100644 index 0000000..1680056 --- /dev/null +++ b/src/grub2/huffman.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * Huffman alphabets + * + */ + +#include "wimboot.h" +#include "huffman.h" + +/** + * Transcribe binary value (for debugging) + * + * @v value Value + * @v bits Length of value (in bits) + * @ret string Transcribed value + */ +const char * huffman_bin ( unsigned long value, unsigned int bits ) { + static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ]; + char *out = buf; + + /* Sanity check */ + assert ( bits < sizeof ( buf ) ); + + /* Transcribe value */ + while ( bits-- ) + *(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' ); + *out = '\0'; + + return buf; +} + +/** + * Dump Huffman alphabet (for debugging) + * + * @v alphabet Huffman alphabet + */ +static void __attribute__ (( unused )) +huffman_dump_alphabet ( struct huffman_alphabet *alphabet ) { + struct huffman_symbols *sym; + unsigned int bits; + unsigned int huf; + unsigned int i; + + (void)huf; + + /* Dump symbol table for each utilised length */ + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + sym = &alphabet->huf[ bits - 1 ]; + if ( sym->freq == 0 ) + continue; + huf = ( sym->start >> sym->shift ); + DBG ( "Huffman length %d start \"%s\" freq %d:", bits, + huffman_bin ( huf, sym->bits ), sym->freq ); + for ( i = 0 ; i < sym->freq ; i++ ) { + DBG ( " %03x", sym->raw[ huf + i ] ); + } + DBG ( "\n" ); + } + + /* Dump quick lookup table */ + DBG ( "Huffman quick lookup:" ); + for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) / + sizeof ( alphabet->lookup[0] ) ) ; i++ ) { + DBG ( " %d", ( alphabet->lookup[i] + 1 ) ); + } + DBG ( "\n" ); +} + +/** + * Construct Huffman alphabet + * + * @v alphabet Huffman alphabet + * @v lengths Symbol length table + * @v count Number of symbols + * @ret rc Return status code + */ +int huffman_alphabet ( struct huffman_alphabet *alphabet, + uint8_t *lengths, unsigned int count ) { + struct huffman_symbols *sym; + unsigned int huf; + unsigned int cum_freq; + unsigned int bits; + unsigned int raw; + unsigned int adjustment; + unsigned int prefix; + int empty; + int complete; + + /* Clear symbol table */ + memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) ); + + /* Count number of symbols with each Huffman-coded length */ + empty = 1; + for ( raw = 0 ; raw < count ; raw++ ) { + bits = lengths[raw]; + if ( bits ) { + alphabet->huf[ bits - 1 ].freq++; + empty = 0; + } + } + + /* In the degenerate case of having no symbols (i.e. an unused + * alphabet), generate a trivial alphabet with exactly two + * single-bit codes. This allows callers to avoid having to + * check for this special case. + */ + if ( empty ) + alphabet->huf[0].freq = 2; + + /* Populate Huffman-coded symbol table */ + huf = 0; + cum_freq = 0; + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + sym = &alphabet->huf[ bits - 1 ]; + sym->bits = bits; + sym->shift = ( HUFFMAN_BITS - bits ); + sym->start = ( huf << sym->shift ); + sym->raw = &alphabet->raw[cum_freq]; + huf += sym->freq; + if ( huf > ( 1U << bits ) ) { + DBG ( "Huffman alphabet has too many symbols with " + "lengths <=%d\n", bits ); + return -1; + } + huf <<= 1; + cum_freq += sym->freq; + } + complete = ( huf == ( 1U << bits ) ); + + /* Populate raw symbol table */ + for ( raw = 0 ; raw < count ; raw++ ) { + bits = lengths[raw]; + if ( bits ) { + sym = &alphabet->huf[ bits - 1 ]; + *(sym->raw++) = raw; + } + } + + /* Adjust Huffman-coded symbol table raw pointers and populate + * quick lookup table. + */ + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + sym = &alphabet->huf[ bits - 1 ]; + + /* Adjust raw pointer */ + sym->raw -= sym->freq; /* Reset to first symbol */ + adjustment = ( sym->start >> sym->shift ); + sym->raw -= adjustment; /* Adjust for quick indexing */ + + /* Populate quick lookup table */ + for ( prefix = ( sym->start >> HUFFMAN_QL_SHIFT ) ; + prefix < ( 1 << HUFFMAN_QL_BITS ) ; prefix++ ) { + alphabet->lookup[prefix] = ( bits - 1 ); + } + } + + /* Check that there are no invalid codes */ + if ( ! complete ) { + DBG ( "Huffman alphabet is incomplete\n" ); + return -1; + } + + return 0; +} + +/** + * Get Huffman symbol set + * + * @v alphabet Huffman alphabet + * @v huf Raw input value (normalised to HUFFMAN_BITS bits) + * @ret sym Huffman symbol set + */ +struct huffman_symbols * huffman_sym ( struct huffman_alphabet *alphabet, + unsigned int huf ) { + struct huffman_symbols *sym; + unsigned int lookup_index; + + /* Find symbol set for this length */ + lookup_index = ( huf >> HUFFMAN_QL_SHIFT ); + sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ]; + while ( huf < sym->start ) + sym--; + return sym; +} diff --git a/src/grub2/huffman.h b/src/grub2/huffman.h new file mode 100644 index 0000000..95bbae8 --- /dev/null +++ b/src/grub2/huffman.h @@ -0,0 +1,108 @@ +#ifndef _HUFFMAN_H +#define _HUFFMAN_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * Huffman alphabets + * + */ + +/** Maximum length of a Huffman symbol (in bits) */ +#define HUFFMAN_BITS 16 + +/** Raw huffman symbol */ +typedef uint16_t huffman_raw_symbol_t; + +/** Quick lookup length for a Huffman symbol (in bits) + * + * This is a policy decision. + */ +#define HUFFMAN_QL_BITS 7 + +/** Quick lookup shift */ +#define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS ) + +/** A Huffman-coded set of symbols of a given length */ +struct huffman_symbols { + /** Length of Huffman-coded symbols (in bits) */ + uint8_t bits; + /** Shift to normalise symbols of this length to HUFFMAN_BITS bits */ + uint8_t shift; + /** Number of Huffman-coded symbols having this length */ + uint16_t freq; + /** First symbol of this length (normalised to HUFFMAN_BITS bits) + * + * Stored as a 32-bit value to allow the value + * (1<bits; +} + +/** + * Get Huffman symbol value + * + * @v sym Huffman symbol set + * @v huf Raw input value (normalised to HUFFMAN_BITS bits) + * @ret raw Raw symbol value + */ +static inline __attribute__ (( always_inline )) huffman_raw_symbol_t +huffman_raw ( struct huffman_symbols *sym, unsigned int huf ) { + + return sym->raw[ huf >> sym->shift ]; +} + +extern int huffman_alphabet ( struct huffman_alphabet *alphabet, + uint8_t *lengths, unsigned int count ); +extern struct huffman_symbols * +huffman_sym ( struct huffman_alphabet *alphabet, unsigned int huf ); + +#endif /* _HUFFMAN_H */ diff --git a/src/grub2/lzx.c b/src/grub2/lzx.c new file mode 100644 index 0000000..732a96f --- /dev/null +++ b/src/grub2/lzx.c @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2014 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * LZX decompression + * + * This algorithm is derived jointly from the document "[MS-PATCH]: + * LZX DELTA Compression and Decompression", available from + * + * http://msdn.microsoft.com/en-us/library/cc483133.aspx + * + * and from the file lzx-decompress.c in the wimlib source code. + * + */ + +#include "wimboot.h" +#include "huffman.h" +#include "lzx.h" + +/** Base positions, indexed by position slot */ +static unsigned int lzx_position_base[LZX_POSITION_SLOTS]; + +/** + * Attempt to accumulate bits from LZX bitstream + * + * @v lzx Decompressor + * @v bits Number of bits to accumulate + * @v norm_value Accumulated value (normalised to 16 bits) + * + * Note that there may not be sufficient accumulated bits in the + * bitstream; callers must check that sufficient bits are available + * before using the value. + */ +static int lzx_accumulate ( struct lzx *lzx, unsigned int bits ) { + const uint16_t *src16; + + /* Accumulate more bits if required */ + if ( ( lzx->bits < bits ) && + ( lzx->input.offset < lzx->input.len ) ) { + src16 = (const uint16_t *)( ( char * ) lzx->input.data + lzx->input.offset ); + lzx->input.offset += sizeof ( *src16 ); + lzx->accumulator |= ( *src16 << ( 16 - lzx->bits ) ); + lzx->bits += 16; + } + + return ( lzx->accumulator >> 16 ); +} + +/** + * Consume accumulated bits from LZX bitstream + * + * @v lzx Decompressor + * @v bits Number of bits to consume + * @ret rc Return status code + */ +static int lzx_consume ( struct lzx *lzx, unsigned int bits ) { + + /* Fail if insufficient bits are available */ + if ( lzx->bits < bits ) { + DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n", + lzx->input.offset, lzx->input.len, lzx->output.offset ); + return -1; + } + + /* Consume bits */ + lzx->accumulator <<= bits; + lzx->bits -= bits; + + return 0; +} + +/** + * Get bits from LZX bitstream + * + * @v lzx Decompressor + * @v bits Number of bits to fetch + * @ret value Value, or negative error + */ +static int lzx_getbits ( struct lzx *lzx, unsigned int bits ) { + int norm_value; + int rc; + + /* Accumulate more bits if required */ + norm_value = lzx_accumulate ( lzx, bits ); + + /* Consume bits */ + if ( ( rc = lzx_consume ( lzx, bits ) ) != 0 ) + return rc; + + return ( norm_value >> ( 16 - bits ) ); +} + +/** + * Align LZX bitstream for byte access + * + * @v lzx Decompressor + * @v bits Minimum number of padding bits + * @ret rc Return status code + */ +static int lzx_align ( struct lzx *lzx, unsigned int bits ) { + int pad; + + /* Get padding bits */ + pad = lzx_getbits ( lzx, bits ); + if ( pad < 0 ) + return pad; + + /* Consume all accumulated bits */ + lzx_consume ( lzx, lzx->bits ); + + return 0; +} + +/** + * Get bytes from LZX bitstream + * + * @v lzx Decompressor + * @v data Data buffer, or NULL + * @v len Length of data buffer + * @ret rc Return status code + */ +static int lzx_getbytes ( struct lzx *lzx, void *data, size_t len ) { + + /* Sanity check */ + if ( ( lzx->input.offset + len ) > lzx->input.len ) { + DBG ( "LZX input overrun in %#zx/%#zx out %#zx)\n", + lzx->input.offset, lzx->input.len, lzx->output.offset ); + return -1; + } + + /* Copy data */ + if ( data ) + memcpy ( data, ( lzx->input.data + lzx->input.offset ), len ); + lzx->input.offset += len; + + return 0; +} + +/** + * Decode LZX Huffman-coded symbol + * + * @v lzx Decompressor + * @v alphabet Huffman alphabet + * @ret raw Raw symbol, or negative error + */ +static int lzx_decode ( struct lzx *lzx, struct huffman_alphabet *alphabet ) { + struct huffman_symbols *sym; + int huf; + int rc; + + /* Accumulate sufficient bits */ + huf = lzx_accumulate ( lzx, HUFFMAN_BITS ); + if ( huf < 0 ) + return huf; + + /* Decode symbol */ + sym = huffman_sym ( alphabet, huf ); + + /* Consume bits */ + if ( ( rc = lzx_consume ( lzx, huffman_len ( sym ) ) ) != 0 ) + return rc; + + return huffman_raw ( sym, huf ); +} + +/** + * Generate Huffman alphabet from raw length table + * + * @v lzx Decompressor + * @v count Number of symbols + * @v bits Length of each length (in bits) + * @v lengths Lengths table to fill in + * @v alphabet Huffman alphabet to fill in + * @ret rc Return status code + */ +static int lzx_raw_alphabet ( struct lzx *lzx, unsigned int count, + unsigned int bits, uint8_t *lengths, + struct huffman_alphabet *alphabet ) { + unsigned int i; + int len; + int rc; + + /* Read lengths */ + for ( i = 0 ; i < count ; i++ ) { + len = lzx_getbits ( lzx, bits ); + if ( len < 0 ) + return len; + lengths[i] = len; + } + + /* Generate Huffman alphabet */ + if ( ( rc = huffman_alphabet ( alphabet, lengths, count ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Generate pretree + * + * @v lzx Decompressor + * @v count Number of symbols + * @v lengths Lengths table to fill in + * @ret rc Return status code + */ +static int lzx_pretree ( struct lzx *lzx, unsigned int count, + uint8_t *lengths ) { + unsigned int i; + unsigned int length; + int dup = 0; + int code; + int rc; + + /* Generate pretree alphabet */ + if ( ( rc = lzx_raw_alphabet ( lzx, LZX_PRETREE_CODES, + LZX_PRETREE_BITS, lzx->pretree_lengths, + &lzx->pretree ) ) != 0 ) + return rc; + + /* Read lengths */ + for ( i = 0 ; i < count ; i++ ) { + + if ( dup ) { + + /* Duplicate previous length */ + lengths[i] = lengths[ i - 1 ]; + dup--; + + } else { + + /* Get next code */ + code = lzx_decode ( lzx, &lzx->pretree ); + if ( code < 0 ) + return code; + + /* Interpret code */ + if ( code <= 16 ) { + length = ( ( lengths[i] - code + 17 ) % 17 ); + } else if ( code == 17 ) { + length = 0; + dup = lzx_getbits ( lzx, 4 ); + if ( dup < 0 ) + return dup; + dup += 3; + } else if ( code == 18 ) { + length = 0; + dup = lzx_getbits ( lzx, 5 ); + if ( dup < 0 ) + return dup; + dup += 19; + } else if ( code == 19 ) { + length = 0; + dup = lzx_getbits ( lzx, 1 ); + if ( dup < 0 ) + return dup; + dup += 3; + code = lzx_decode ( lzx, &lzx->pretree ); + if ( code < 0 ) + return code; + length = ( ( lengths[i] - code + 17 ) % 17 ); + } else { + DBG ( "Unrecognised pretree code %d\n", code ); + return -1; + } + lengths[i] = length; + } + } + + /* Sanity check */ + if ( dup ) { + DBG ( "Pretree duplicate overrun\n" ); + return -1; + } + + return 0; +} + +/** + * Generate aligned offset Huffman alphabet + * + * @v lzx Decompressor + * @ret rc Return status code + */ +static int lzx_alignoffset_alphabet ( struct lzx *lzx ) { + int rc; + + /* Generate aligned offset alphabet */ + if ( ( rc = lzx_raw_alphabet ( lzx, LZX_ALIGNOFFSET_CODES, + LZX_ALIGNOFFSET_BITS, + lzx->alignoffset_lengths, + &lzx->alignoffset ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Generate main Huffman alphabet + * + * @v lzx Decompressor + * @ret rc Return status code + */ +static int lzx_main_alphabet ( struct lzx *lzx ) { + int rc; + + /* Generate literal symbols pretree */ + if ( ( rc = lzx_pretree ( lzx, LZX_MAIN_LIT_CODES, + lzx->main_lengths.literals ) ) != 0 ) { + DBG ( "Could not construct main literal pretree\n" ); + return rc; + } + + /* Generate remaining symbols pretree */ + if ( ( rc = lzx_pretree ( lzx, ( LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ), + lzx->main_lengths.remainder ) ) != 0 ) { + DBG ( "Could not construct main remainder pretree\n" ); + return rc; + } + + /* Generate Huffman alphabet */ + if ( ( rc = huffman_alphabet ( &lzx->main, lzx->main_lengths.literals, + LZX_MAIN_CODES ) ) != 0 ) { + DBG ( "Could not generate main alphabet\n" ); + return rc; + } + + return 0; +} + +/** + * Generate length Huffman alphabet + * + * @v lzx Decompressor + * @ret rc Return status code + */ +static int lzx_length_alphabet ( struct lzx *lzx ) { + int rc; + + /* Generate pretree */ + if ( ( rc = lzx_pretree ( lzx, LZX_LENGTH_CODES, + lzx->length_lengths ) ) != 0 ) { + DBG ( "Could not generate length pretree\n" ); + return rc; + } + + /* Generate Huffman alphabet */ + if ( ( rc = huffman_alphabet ( &lzx->length, lzx->length_lengths, + LZX_LENGTH_CODES ) ) != 0 ) { + DBG ( "Could not generate length alphabet\n" ); + return rc; + } + + return 0; +} + +/** + * Process LZX block header + * + * @v lzx Decompressor + * @ret rc Return status code + */ +static int lzx_block_header ( struct lzx *lzx ) { + size_t block_len; + int block_type; + int default_len; + int len_high; + int len_low; + int rc; + + /* Get block type */ + block_type = lzx_getbits ( lzx, LZX_BLOCK_TYPE_BITS ); + if ( block_type < 0 ) + return block_type; + lzx->block_type = block_type; + + /* Check block length */ + default_len = lzx_getbits ( lzx, 1 ); + if ( default_len < 0 ) + return default_len; + if ( default_len ) { + block_len = LZX_DEFAULT_BLOCK_LEN; + } else { + len_high = lzx_getbits ( lzx, 8 ); + if ( len_high < 0 ) + return len_high; + len_low = lzx_getbits ( lzx, 8 ); + if ( len_low < 0 ) + return len_low; + block_len = ( ( len_high << 8 ) | len_low ); + } + lzx->output.threshold = ( lzx->output.offset + block_len ); + + /* Handle block type */ + switch ( block_type ) { + case LZX_BLOCK_ALIGNOFFSET : + /* Generated aligned offset alphabet */ + if ( ( rc = lzx_alignoffset_alphabet ( lzx ) ) != 0 ) + return rc; + /* Fall through */ + case LZX_BLOCK_VERBATIM : + /* Generate main alphabet */ + if ( ( rc = lzx_main_alphabet ( lzx ) ) != 0 ) + return rc; + /* Generate lengths alphabet */ + if ( ( rc = lzx_length_alphabet ( lzx ) ) != 0 ) + return rc; + break; + case LZX_BLOCK_UNCOMPRESSED : + /* Align input stream */ + if ( ( rc = lzx_align ( lzx, 1 ) ) != 0 ) + return rc; + /* Read new repeated offsets */ + if ( ( rc = lzx_getbytes ( lzx, &lzx->repeated_offset, + sizeof ( lzx->repeated_offset )))!=0) + return rc; + break; + default: + DBG ( "Unrecognised block type %d\n", block_type ); + return -1; + } + + return 0; +} + +/** + * Process uncompressed data + * + * @v lzx Decompressor + * @ret rc Return status code + */ +static int lzx_uncompressed ( struct lzx *lzx ) { + void *data; + size_t len; + int rc; + + /* Copy bytes */ + data = ( lzx->output.data ? + ( lzx->output.data + lzx->output.offset ) : NULL ); + len = ( lzx->output.threshold - lzx->output.offset ); + if ( ( rc = lzx_getbytes ( lzx, data, len ) ) != 0 ) + return rc; + + /* Align input stream */ + if ( len % 2 ) + lzx->input.offset++; + + lzx->output.offset += len; + + return 0; +} + +/** + * Process an LZX token + * + * @v lzx Decompressor + * @ret rc Return status code + * + * Variable names are chosen to match the LZX specification + * pseudo-code. + */ +static int lzx_token ( struct lzx *lzx ) { + unsigned int length_header; + unsigned int position_slot; + unsigned int offset_bits; + unsigned int i; + size_t match_offset; + size_t match_length; + int verbatim_bits; + int aligned_bits; + int maindata; + int length; + uint8_t *copy; + + /* Get maindata symelse*/ + maindata = lzx_decode ( lzx, &lzx->main ); + if ( maindata < 0 ) + return maindata; + + /* Check for literals */ + if ( maindata < LZX_MAIN_LIT_CODES ) { + if ( lzx->output.data ) + lzx->output.data[lzx->output.offset] = maindata; + lzx->output.offset++; + return 0; + } + maindata -= LZX_MAIN_LIT_CODES; + + /* Calculate the match length */ + length_header = ( maindata & 7 ); + if ( length_header == 7 ) { + length = lzx_decode ( lzx, &lzx->length ); + if ( length < 0 ) + return length; + } else { + length = 0; + } + match_length = ( length_header + 2 + length ); + + /* Calculate the position slot */ + position_slot = ( maindata >> 3 ); + if ( position_slot < LZX_REPEATED_OFFSETS ) { + + /* Repeated offset */ + match_offset = lzx->repeated_offset[position_slot]; + lzx->repeated_offset[position_slot] = lzx->repeated_offset[0]; + lzx->repeated_offset[0] = match_offset; + + } else { + + /* Non-repeated offset */ + offset_bits = lzx_footer_bits ( position_slot ); + if ( ( lzx->block_type == LZX_BLOCK_ALIGNOFFSET ) && + ( offset_bits >= 3 ) ) { + verbatim_bits = lzx_getbits ( lzx, ( offset_bits - 3 )); + if ( verbatim_bits < 0 ) + return verbatim_bits; + verbatim_bits <<= 3; + aligned_bits = lzx_decode ( lzx, &lzx->alignoffset ); + if ( aligned_bits < 0 ) + return aligned_bits; + } else { + verbatim_bits = lzx_getbits ( lzx, offset_bits ); + if ( verbatim_bits < 0 ) + return verbatim_bits; + aligned_bits = 0; + } + match_offset = ( lzx_position_base[position_slot] + + verbatim_bits + aligned_bits - 2 ); + + /* Update repeated offset list */ + for ( i = ( LZX_REPEATED_OFFSETS - 1 ) ; i > 0 ; i-- ) + lzx->repeated_offset[i] = lzx->repeated_offset[ i - 1 ]; + lzx->repeated_offset[0] = match_offset; + } + + /* Copy data */ + if ( match_offset > lzx->output.offset ) { + DBG ( "LZX match underrun out 0x%x offset 0x%x len 0x%x\n", + lzx->output.offset, match_offset, match_length ); + return -1; + } + if ( lzx->output.data ) { + copy = &lzx->output.data[lzx->output.offset]; + for ( i = 0 ; i < match_length ; i++ ) + copy[i] = copy[ i - match_offset ]; + } + lzx->output.offset += match_length; + + return 0; +} + +/** + * Translate E8 jump addresses + * + * @v lzx Decompressor + */ +static void lzx_translate_jumps ( struct lzx *lzx ) { + size_t offset; + int32_t *target; + + /* Sanity check */ + if ( lzx->output.offset < 10 ) + return; + + /* Scan for jump instructions */ + for ( offset = 0 ; offset < ( lzx->output.offset - 10 ) ; offset++ ) { + + /* Check for jump instruction */ + if ( lzx->output.data[offset] != 0xe8 ) + continue; + + /* Translate jump target */ + target = ( ( int32_t * ) &lzx->output.data[ offset + 1 ] ); + if ( *target >= 0 ) { + if ( *target < LZX_WIM_MAGIC_FILESIZE ) + *target -= offset; + } else { + if ( *target >= -( ( int32_t ) offset ) ) + *target += LZX_WIM_MAGIC_FILESIZE; + } + offset += sizeof ( *target ); + } +} + +/** + * Decompress LZX-compressed data + * + * @v data Compressed data + * @v len Length of compressed data + * @v buf Decompression buffer, or NULL + * @ret out_len Length of decompressed data, or negative error + */ +ssize_t lzx_decompress ( const void *data, size_t len, void *buf ) { + struct lzx lzx; + unsigned int i; + int rc; + + /* Sanity check */ + if ( len % 2 ) { + DBG ( "LZX cannot handle odd-length input data\n" ); + //return -1; + } + + /* Initialise global state, if required */ + if ( ! lzx_position_base[ LZX_POSITION_SLOTS - 1 ] ) { + for ( i = 1 ; i < LZX_POSITION_SLOTS ; i++ ) { + lzx_position_base[i] = + ( lzx_position_base[i-1] + + ( 1 << lzx_footer_bits ( i - 1 ) ) ); + } + } + + /* Initialise decompressor */ + memset ( &lzx, 0, sizeof ( lzx ) ); + lzx.input.data = data; + lzx.input.len = len; + lzx.output.data = buf; + for ( i = 0 ; i < LZX_REPEATED_OFFSETS ; i++ ) + lzx.repeated_offset[i] = 1; + + /* Process blocks */ + while ( lzx.input.offset < lzx.input.len ) { + + /* Process block header */ + if ( ( rc = lzx_block_header ( &lzx ) ) != 0 ) + return rc; + + /* Process block contents */ + if ( lzx.block_type == LZX_BLOCK_UNCOMPRESSED ) { + + /* Copy uncompressed data */ + if ( ( rc = lzx_uncompressed ( &lzx ) ) != 0 ) + return rc; + + } else { + + /* Process token stream */ + while ( lzx.output.offset < lzx.output.threshold ) { + if ( ( rc = lzx_token ( &lzx ) ) != 0 ) + return rc; + } + } + } + + /* Postprocess to undo E8 jump compression */ + if ( lzx.output.data ) + lzx_translate_jumps ( &lzx ); + + return lzx.output.offset; +} diff --git a/src/grub2/lzx.h b/src/grub2/lzx.h new file mode 100644 index 0000000..6a4ed8f --- /dev/null +++ b/src/grub2/lzx.h @@ -0,0 +1,179 @@ +#ifndef _LZX_H +#define _LZX_H + +/* + * Copyright (C) 2014 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * LZX decompression + * + */ + +#include "huffman.h" + +/** Number of aligned offset codes */ +#define LZX_ALIGNOFFSET_CODES 8 + +/** Aligned offset code length (in bits) */ +#define LZX_ALIGNOFFSET_BITS 3 + +/** Number of pretree codes */ +#define LZX_PRETREE_CODES 20 + +/** Pretree code length (in bits) */ +#define LZX_PRETREE_BITS 4 + +/** Number of literal main codes */ +#define LZX_MAIN_LIT_CODES 256 + +/** Number of position slots */ +#define LZX_POSITION_SLOTS 30 + +/** Number of main codes */ +#define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) ) + +/** Number of length codes */ +#define LZX_LENGTH_CODES 249 + +/** Block type length (in bits) */ +#define LZX_BLOCK_TYPE_BITS 3 + +/** Default block length */ +#define LZX_DEFAULT_BLOCK_LEN 32768 + +/** Number of repeated offsets */ +#define LZX_REPEATED_OFFSETS 3 + +/** Don't ask */ +#define LZX_WIM_MAGIC_FILESIZE 12000000 + +/** Block types */ +enum lzx_block_type { + /** Verbatim block */ + LZX_BLOCK_VERBATIM = 1, + /** Aligned offset block */ + LZX_BLOCK_ALIGNOFFSET = 2, + /** Uncompressed block */ + LZX_BLOCK_UNCOMPRESSED = 3, +}; + +/** An LZX input stream */ +struct lzx_input_stream { + /** Data */ + const uint8_t *data; + /** Length */ + size_t len; + /** Offset within stream */ + size_t offset; +}; + +/** An LZX output stream */ +struct lzx_output_stream { + /** Data, or NULL */ + uint8_t *data; + /** Offset within stream */ + size_t offset; + /** End of current block within stream */ + size_t threshold; +}; + +/** LZX decompressor */ +struct lzx { + /** Input stream */ + struct lzx_input_stream input; + /** Output stream */ + struct lzx_output_stream output; + /** Accumulator */ + uint32_t accumulator; + /** Number of bits in accumulator */ + unsigned int bits; + /** Block type */ + enum lzx_block_type block_type; + /** Repeated offsets */ + unsigned int repeated_offset[LZX_REPEATED_OFFSETS]; + + /** Aligned offset Huffman alphabet */ + struct huffman_alphabet alignoffset; + /** Aligned offset raw symbols + * + * Must immediately follow the aligned offset Huffman + * alphabet. + */ + huffman_raw_symbol_t alignoffset_raw[LZX_ALIGNOFFSET_CODES]; + /** Aligned offset code lengths */ + uint8_t alignoffset_lengths[LZX_ALIGNOFFSET_CODES]; + + /** Pretree Huffman alphabet */ + struct huffman_alphabet pretree; + /** Pretree raw symbols + * + * Must immediately follow the pretree Huffman alphabet. + */ + huffman_raw_symbol_t pretree_raw[LZX_PRETREE_CODES]; + /** Preetree code lengths */ + uint8_t pretree_lengths[LZX_PRETREE_CODES]; + + /** Main Huffman alphabet */ + struct huffman_alphabet main; + /** Main raw symbols + * + * Must immediately follow the main Huffman alphabet. + */ + huffman_raw_symbol_t main_raw[LZX_MAIN_CODES]; + /** Main code lengths */ + struct { + /** Literals */ + uint8_t literals[LZX_MAIN_LIT_CODES]; + /** Remaining symbols */ + uint8_t remainder[ LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ]; + } __attribute__ (( packed )) main_lengths; + + /** Length Huffman alphabet */ + struct huffman_alphabet length; + /** Length raw symbols + * + * Must immediately follow the length Huffman alphabet. + */ + huffman_raw_symbol_t length_raw[LZX_LENGTH_CODES]; + /** Length code lengths */ + uint8_t length_lengths[LZX_LENGTH_CODES]; +}; + +/** + * Calculate number of footer bits for a given position slot + * + * @v position_slot Position slot + * @ret footer_bits Number of footer bits + */ +static inline unsigned int lzx_footer_bits ( unsigned int position_slot ) { + + if ( position_slot < 2 ) { + return 0; + } else if ( position_slot < 38 ) { + return ( ( position_slot / 2 ) - 1 ); + } else { + return 17; + } +} + +extern ssize_t lzx_decompress ( const void *data, size_t len, void *buf ); + +#endif /* _LZX_H */ diff --git a/src/grub2/miniz.c b/src/grub2/miniz.c new file mode 100644 index 0000000..60312a9 --- /dev/null +++ b/src/grub2/miniz.c @@ -0,0 +1,2587 @@ +/* miniz.c v1.12 - public domain deflate/inflate + See "unlicense" statement at the end of this file. + Rich Geldreich , last updated April 12, 2012 + Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt + + * Change History + 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. + level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. + 5/28/11 v1.11 - Added statement from unlicense.org + 5/27/11 v1.10 - Substantial compressor optimizations: + Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a + Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). + Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. + Refactored the compression code for better readability and maintainability. + Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large + drop in throughput on some files). + 5/15/11 v1.09 - Initial stable release. + + * Low-level Deflate/Inflate implementation notes: + + Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or + greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses + approximately as well as zlib. + + Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function + coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory + block large enough to hold the entire file. + + The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. + + * zlib-style API notes: + + miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in + zlib replacement in many apps: + The z_stream struct, optional memory allocation callbacks + deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound + inflateInit/inflateInit2/inflate/inflateEnd + compress, compress2, compressBound, uncompress + CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. + Supports raw deflate streams or standard zlib streams with adler-32 checking. + + Limitations: + The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. + I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but + there are no guarantees that miniz.c pulls this off perfectly. + + * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by + Alex Evans. Supports 1-4 bytes/pixel images. + + * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the + below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. + + * Important: For best perf. be sure to customize the below macros for your target platform: + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 + #define MINIZ_LITTLE_ENDIAN 1 + #define MINIZ_HAS_64BIT_REGISTERS 1 +*/ + +#ifndef MINIZ_HEADER_INCLUDED +#define MINIZ_HEADER_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" + +#define size_t grub_size_t +#define uint8_t grub_uint8_t +#define uint16_t grub_uint16_t +#define uint32_t grub_uint32_t +#define uint64_t grub_uint64_t + +#define assert(a) + +#define memset grub_memset +#define memcpy grub_memcpy +#define memcmp grub_memcmp + +// Defines to completely disable specific portions of miniz.c: +// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. + +// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. +//#define MINIZ_NO_ZLIB_APIS + +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. +//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. +// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc +// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user +// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. +//#define MINIZ_NO_MALLOC + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. +#define MINIZ_X86_OR_X64_CPU 1 +#endif + +#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. +#define MINIZ_LITTLE_ENDIAN 1 +#else +#error ("Not little endian") +#endif + +#if MINIZ_X86_OR_X64_CPU +// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +#endif + +#define MINIZ_HAS_64BIT_REGISTERS 1 + +// ------------------- zlib-style API Definitions. + +// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. +typedef unsigned long mz_ulong; + +// Heap allocation callbacks. +// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +#define MZ_ADLER32_INIT (1) +// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. +mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +// Compression strategies. +enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; + +// Method +#define MZ_DEFLATED 8 + +#ifndef MINIZ_NO_ZLIB_APIS + +#define MZ_VERSION "9.1.12" +#define MZ_VERNUM 0x91C0 +#define MZ_VER_MAJOR 9 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 12 +#define MZ_VER_SUBREVISION 0 + +// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). +enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + +// Return status codes. MZ_PARAM_ERROR is non-standard. +enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; + +// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. +enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + +// Window bits +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +// Compression/decompression stream struct. +typedef struct mz_stream_s +{ + const unsigned char *next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far + + unsigned char *next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far + + char *msg; // error msg (unused) + struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void *opaque; // heap alloc function user pointer + + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong crc32; // crc32 of the source or uncompressed data + mz_ulong reserved; +} mz_stream; + +typedef mz_stream *mz_streamp; + +// Returns the version string of miniz.c. +const char *mz_version(void); + +// mz_deflateInit() initializes a compressor with default options: +// Parameters: +// pStream must point to an initialized mz_stream struct. +// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. +// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. +// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if the input parameters are bogus. +// MZ_MEM_ERROR on out of memory. +int mz_deflateInit(mz_streamp pStream, int level); + +// mz_deflateInit2() is like mz_deflate(), except with more control: +// Additional parameters: +// method must be MZ_DEFLATED +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) +// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). +int mz_deflateReset(mz_streamp pStream); + +// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. +// Return values: +// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). +// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) +int mz_deflate(mz_streamp pStream, int flush); + +// mz_deflateEnd() deinitializes a compressor: +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +int mz_deflateEnd(mz_streamp pStream); + +// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +// Single-call compression functions mz_compress() and mz_compress2(): +// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). +mz_ulong mz_compressBound(mz_ulong source_len); + +// Initializes a decompressor. +int mz_inflateInit(mz_streamp pStream); + +// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). +int mz_inflateInit2(mz_streamp pStream, int window_bits); + +// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. +// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). +// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. +// Return values: +// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. +// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_DATA_ERROR if the deflate stream is invalid. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again +// with more input data, or with more room in the output buffer (except when using single call decompression, described above). +int mz_inflate(mz_streamp pStream, int flush); + +// Deinitializes a decompressor. +int mz_inflateEnd(mz_streamp pStream); + +// Single-call decompression. +// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + +// Returns a string description of the specified error code, or NULL if the error code is invalid. +const char *mz_error(int err); + +// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + typedef unsigned char Byte; + typedef unsigned int uInt; + typedef mz_ulong uLong; + typedef Byte Bytef; + typedef uInt uIntf; + typedef char charf; + typedef int intf; + typedef void *voidpf; + typedef uLong uLongf; + typedef void *voidp; + typedef void *const voidpc; + #define Z_NULL 0 + #define Z_NO_FLUSH MZ_NO_FLUSH + #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH + #define Z_SYNC_FLUSH MZ_SYNC_FLUSH + #define Z_FULL_FLUSH MZ_FULL_FLUSH + #define Z_FINISH MZ_FINISH + #define Z_BLOCK MZ_BLOCK + #define Z_OK MZ_OK + #define Z_STREAM_END MZ_STREAM_END + #define Z_NEED_DICT MZ_NEED_DICT + #define Z_ERRNO MZ_ERRNO + #define Z_STREAM_ERROR MZ_STREAM_ERROR + #define Z_DATA_ERROR MZ_DATA_ERROR + #define Z_MEM_ERROR MZ_MEM_ERROR + #define Z_BUF_ERROR MZ_BUF_ERROR + #define Z_VERSION_ERROR MZ_VERSION_ERROR + #define Z_PARAM_ERROR MZ_PARAM_ERROR + #define Z_NO_COMPRESSION MZ_NO_COMPRESSION + #define Z_BEST_SPEED MZ_BEST_SPEED + #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION + #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION + #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY + #define Z_FILTERED MZ_FILTERED + #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY + #define Z_RLE MZ_RLE + #define Z_FIXED MZ_FIXED + #define Z_DEFLATED MZ_DEFLATED + #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS + #define alloc_func mz_alloc_func + #define free_func mz_free_func + #define internal_state mz_internal_state + #define z_stream mz_stream + #define deflateInit mz_deflateInit + #define deflateInit2 mz_deflateInit2 + #define deflateReset mz_deflateReset + #define deflate mz_deflate + #define deflateEnd mz_deflateEnd + #define deflateBound mz_deflateBound + #define compress mz_compress + #define compress2 mz_compress2 + #define compressBound mz_compressBound + #define inflateInit mz_inflateInit + #define inflateInit2 mz_inflateInit2 + #define inflate mz_inflate + #define inflateEnd mz_inflateEnd + #define uncompress mz_uncompress + #define z_crc32 mz_crc32 + #define z_adler32 mz_adler32 + #define MAX_WBITS 15 + #define MAX_MEM_LEVEL 9 + #define zError mz_error + #define ZLIB_VERSION MZ_VERSION + #define ZLIB_VERNUM MZ_VERNUM + #define ZLIB_VER_MAJOR MZ_VER_MAJOR + #define ZLIB_VER_MINOR MZ_VER_MINOR + #define ZLIB_VER_REVISION MZ_VER_REVISION + #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION + #define zlibVersion mz_version + #define zlib_version mz_version() +#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +#endif // MINIZ_NO_ZLIB_APIS + +// ------------------- Types and macros + +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef long long mz_int64; +typedef unsigned long long mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +#ifndef __WIN__ +#define MZ_MACRO_END while (0) +#else +// Works around MSVC's spammy "warning C4127: conditional expression is constant" message. +#define MZ_MACRO_END while (0, 0) +#endif + +// ------------------- Low-level Decompression API Definitions + +// Decompression flags used by tinfl_decompress(). +// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. +// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. +// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). +// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +// High level decompression functions: +// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. +// On return: +// Function returns a pointer to the decompressed data, or NULL on failure. +// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must free() the returned block when it's no longer needed. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. +// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. +// Returns 1 on success or 0 on failure. +typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; + +// Max size of LZ dictionary. +#define TINFL_LZ_DICT_SIZE 32768 + +// Return status. +typedef enum +{ + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +// Initializes the decompressor to its initial state. +#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 +#define tinfl_get_crc32(r) (r)->m_check_crc32 + +// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. +// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +// Internal/private bits follow. +enum +{ + TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +typedef struct +{ + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; +} tinfl_huff_table; + +#if MINIZ_HAS_64BIT_REGISTERS + #define TINFL_USE_64BIT_BITBUF 1 +#endif + +#if TINFL_USE_64BIT_BITBUF + typedef mz_uint64 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (64) +#else + typedef mz_uint32 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_z_crc32, m_final, m_type, m_check_adler32, m_check_crc32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +// ------------------- Low-level Compression API Definitions + +// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). +#define TDEFL_LESS_MEMORY 0 + +// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): +// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). +enum +{ + TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. +// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). +// TDEFL_COMPUTE_CRC32: Always compute the crc-32 of the input data. +// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. +// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). +// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) +// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. +// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. +// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x001000, + TDEFL_COMPUTE_ADLER32 = 0x002000, + TDEFL_COMPUTE_CRC32 = 0x004000, + TDEFL_GREEDY_PARSING_FLAG = 0x008000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x010000, + TDEFL_RLE_MATCHES = 0x020000, + TDEFL_FILTER_MATCHES = 0x040000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x080000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x100000, +}; + +// High level compression functions: +// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of source block to compress. +// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must free() the returned block when it's no longer needed. +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. +// Returns 0 on failure. +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// Compresses an image to a compressed PNG file in memory. +// On entry: +// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pLen_out will be set to the size of the PNG image file. +// The caller must free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); + +// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; + +// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). +#if TDEFL_LESS_MEMORY +enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#else +enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#endif + +// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. +typedef enum +{ + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, +} tdefl_status; + +// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums +typedef enum +{ + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +// tdefl's compression state structure. +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_crc32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +// Initializes the compressor. +// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. +// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. +// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. +// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. +// tdefl_compress_buffer() always consumes the entire input buffer. +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +mz_uint32 tdefl_get_adler32(tdefl_compressor *d); +mz_uint32 tdefl_get_crc32(tdefl_compressor *d); + +// Create tdefl_compress() flags given zlib-style compression parameters. +// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) +// window_bits may be -15 (raw deflate) or 15 (zlib) +// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); + +#endif // MINIZ_HEADER_INCLUDED + +// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) + +#ifndef MINIZ_HEADER_FILE_ONLY + +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; + +#define MZ_ASSERT(x) assert(x) + +#ifdef MINIZ_NO_MALLOC + #define MZ_MALLOC(x) NULL + #define MZ_FREE(x) x, ((void)0) + #define MZ_REALLOC(p, x) NULL +#else + #define MZ_MALLOC(x) grub_malloc(x) + #define MZ_FREE(x) grub_free(x) + #define MZ_REALLOC(p, x) grub_realloc(p, x) +#endif + +#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) +#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) +#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) + #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#else + #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) + #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) +#endif + +#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__forceinline) + #define __forceinline +#endif + +// ------------------- zlib-style API's + +static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque; return MZ_MALLOC(items * size); } +static void def_free_func(void *opaque, void *address) { (void)opaque, MZ_FREE(address); } + +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +{ + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; + if (!ptr) return MZ_ADLER32_INIT; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + return (s2 << 16) + s1; +} + +// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +{ + static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + if (!ptr) return MZ_CRC32_INIT; + crc = ~crc; while (buf_len--) { mz_uint8 b = *ptr++; crc = (crc >> 4) ^ s_crc32[(crc & 0xF) ^ (b & 0xF)]; crc = (crc >> 4) ^ s_crc32[(crc & 0xF) ^ (b >> 4)]; } return ~crc; +} + +#ifndef MINIZ_NO_ZLIB_APIS + +const char *mz_version(void) +{ + return MZ_VERSION; +} + +int mz_deflateInit(mz_streamp pStream, int level) +{ + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); +} + +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) +{ + tdefl_compressor *pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | TDEFL_COMPUTE_CRC32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + + if (!pStream) return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->crc32 = MZ_CRC32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pComp; + + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +int mz_deflateReset(mz_streamp pStream) +{ + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); + return MZ_OK; +} + +int mz_deflate(mz_streamp pStream, int flush) +{ + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; + + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; + if (!pStream->avail_out) return MZ_BUF_ERROR; + + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + + if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + + orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; + for ( ; ; ) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + + defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); pStream->crc32 = tdefl_get_crc32((tdefl_compressor*)pStream->state); + + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; // Can't make forward progress without some input. + } + } + return mz_status; +} + +int mz_deflateEnd(mz_streamp pStream) +{ + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) +{ + (void)pStream; + // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); +} + +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +{ + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); +} + +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); +} + +mz_ulong mz_compressBound(mz_ulong source_len) +{ + return mz_deflateBound(NULL, source_len); +} + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->crc32 = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state* pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + + pState = (inflate_state*)pStream->state; + if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; pState->m_first_call = 0; + if (pState->m_last_status < 0) return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->crc32 = tinfl_get_crc32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + // flush != MZ_FINISH then we must assume there's more input. + if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for ( ; ; ) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); pStream->crc32 = tinfl_get_crc32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. + else if (flush == MZ_FINISH) + { + // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +const char *mz_error(int err) +{ + static struct { int m_err; const char *m_pDesc; } s_error_descs[] = + { + { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, + { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; + return NULL; +} + +#endif //MINIZ_NO_ZLIB_APIS + +// ------------------- Low-level Decompression (completely independent from all compression API's) + +#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +#define TINFL_MEMSET(p, c, l) memset(p, c, l) + +#define TINFL_CR_BEGIN switch(r->m_state) { case 0: +#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END +#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END +#define TINFL_CR_FINISH } + +// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never +// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. +#define TINFL_GET_BYTE(state_index, c) do { \ + if (pIn_buf_cur >= pIn_buf_end) { \ + for ( ; ; ) { \ + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ + TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ + if (pIn_buf_cur < pIn_buf_end) { \ + c = *pIn_buf_cur++; \ + break; \ + } \ + } else { \ + c = 0; \ + break; \ + } \ + } \ + } else c = *pIn_buf_cur++; } MZ_MACRO_END + +#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) +#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END +#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END + +// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. +// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a +// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the +// bit buffer contains >=15 bits (deflate's max. Huffman code size). +#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ + do { \ + temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ + } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ + } while (num_bits < 15); + +// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read +// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully +// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. +// The slow path is only executed at the very end of the input buffer. +#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ + int temp; mz_uint code_len, c; \ + if (num_bits < 15) { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) { \ + TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ + } else { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ + } \ + } \ + if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else { \ + code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ + } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END + +#if defined(__aarch64__) || defined(__arm__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmisleading-indentation" +#endif + +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +{ + static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; + static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static const int s_min_table_sizes[3] = { 257, 1, 4 }; + + tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + + // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } + + num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } + } + + do + { + TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } + while (pIn_buf_cur >= pIn_buf_end) + { + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) + { + TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); + } + else + { + TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); + } + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; + r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } + r->m_table_sizes[2] = 19; + } + for ( ; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; tinfl_huff_table *pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; + cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) + { + mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for ( ; ; ) + { + mz_uint8 *pSrc; + for ( ; ; ) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; mz_uint code_len; +#if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } +#else + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + counter = sym2; bit_buf >>= code_len; num_bits -= code_len; + if (counter & 256) + break; + +#if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + bit_buf >>= code_len; num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) break; + + num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } + + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do + { + ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; + ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +#endif + do + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; pSrc += 3; + } while ((int)(counter -= 3) > 2); + if ((int)counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + TINFL_CR_FINISH + +common_exit: + r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +#if defined(__aarch64__) || defined(__arm__) +#pragma GCC diagnostic pop +#endif + +// Higher level helper functions. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) break; + new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; +} + +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +// ------------------- Low-level Compression (independent from all decompression API's) + +// Purposely making these tables static for faster init and thread safety. +static const mz_uint16 s_tdefl_len_sym[256] = { + 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, + 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, + 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, + 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, + 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, + 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, + 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, + 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; + +static const mz_uint8 s_tdefl_len_extra[256] = { + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; + +static const mz_uint8 s_tdefl_small_dist_sym[512] = { + 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; + +static const mz_uint8 s_tdefl_small_dist_extra[512] = { + 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7 }; + +static const mz_uint8 s_tdefl_large_dist_sym[128] = { + 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, + 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; + +static const mz_uint8 s_tdefl_large_dist_extra[128] = { + 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; + +// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. +typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; +static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) +{ + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32* pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } + for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } + } + return pCur_syms; +} + +// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } + A[0].m_key += A[1].m_key; root = 0; leaf = 2; + for (next=1; next < n-1; next++) + { + if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; + avbl = 1; used = dpth = 0; root = n-2; next = n-1; + while (avbl>0) + { + while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } + while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } + avbl = 2*used; dpth++; used = 0; + } +} + +// Limits canonical Huffman code table's max code size. +enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; +static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + int i; mz_uint32 total = 0; if (code_list_len <= 1) return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } + total--; + } +} + +static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +{ + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; + code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } +} + +#define TDEFL_PUT_BITS(b, l) do { \ + mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ + while (d->m_bits_in >= 8) { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ +} MZ_MACRO_END + +#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ + if (rle_repeat_count < 3) { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } else { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ +} rle_repeat_count = 0; } } + +#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ + if (rle_z_count < 3) { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ + } else if (rle_z_count <= 10) { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } else { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ +} rle_z_count = 0; } } + +static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +static void tdefl_start_dynamic_block(tdefl_compressor *d) +{ + int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } +} + +static void tdefl_start_static_block(tdefl_compressor *d) +{ + mz_uint i; + mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) *p++ = 8; + for ( ; i <= 255; ++i) *p++ = 9; + for ( ; i <= 279; ++i) *p++ = 7; + for ( ; i <= 287; ++i) *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); +} + +static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + mz_uint8 *pOutput_buf = d->m_pOutput_buf; + mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + // This sequence coaxes MSVC into using cmov's vs. jmp's. + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; + + *(mz_uint64*)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +#undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + if (flags & 1) + { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) + { + sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } + else + { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS + +static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +{ + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); +} + +static int tdefl_flush_block(tdefl_compressor *d, int flush) +{ + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8 *pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; + + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); + } + + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + + pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; + + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + + // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. + if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) + { + mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } + + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } + } + else + { + mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; +} + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + +#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) +static __forceinline void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) + +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + if (!probe_len) + { + *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } +} + +#pragma GCC diagnostic pop + +#else + +#if defined(__aarch64__) || defined(__arm__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmisleading-indentation" +#endif + +static __forceinline void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; + if (probe_len > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; + c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; + } + } +} + +#if defined(__aarch64__) || defined(__arm__) +#pragma GCC diagnostic pop +#endif + +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +static mz_bool tdefl_compress_fast(tdefl_compressor *d) +{ + // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; + + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8 *pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16 *p = (const mz_uint16 *)pCur_dict; + const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + return MZ_TRUE; +} +#pragma GCC diagnostic pop +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + +static __forceinline void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +{ + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + d->m_huff_count[0][lit]++; +} + +static __forceinline void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +{ + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; +} + +static mz_bool tdefl_compress_normal(tdefl_compressor *d) +{ + const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; + + // Simple lazy/greedy parsing state machine. + len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[cur_pos]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + // Move the lookahead forward by len_to_move bytes. + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); + // Check if it's time to flush the current LZ codes to the internal output buffer. + if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) + { + int n; + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + return MZ_TRUE; +} + +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +{ + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +{ + if (!d) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if (d->m_flags & TDEFL_COMPUTE_CRC32) + d->m_crc32 = (mz_uint32)mz_crc32(d->m_crc32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); +} + +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +{ + MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); +} + +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; d->m_crc32 = 1; + d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +{ + return d->m_prev_return_status; +} + +mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +{ + return d->m_adler32; +} + +mz_uint32 tdefl_get_crc32(tdefl_compressor *d) +{ + return d->m_crc32; +} + +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; + pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); return succeeded; +} + +typedef struct +{ + size_t m_size, m_capacity; + mz_uint8 *m_pBuf; + mz_bool m_expandable; +} tdefl_output_buffer; + +static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +{ + tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; + do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); + pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; + p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; + } + memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; + return MZ_TRUE; +} + +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; + *pOut_len = out_buf.m_size; return out_buf.m_pBuf; +} + +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) return 0; + out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; + return out_buf.m_size; +} + +static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + +// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) +{ + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; +} + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) +#endif + +// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at +// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) +{ + tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; + if (!pComp) return NULL; + MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } + // write dummy header + for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); + // compress image data + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, TDEFL_DEFAULT_MAX_PROBES | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + y * bpl, bpl, TDEFL_NO_FLUSH); } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + // write real header + *pLen_out = out_buf.m_size-41; + { + mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, + 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,"\0\0\04\02\06"[num_chans],0,0,0,0,0,0,0, + (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; + c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + // write footer (IDAT CRC-32, followed by IEND chunk) + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); + // compute final size of file, grab compressed data buffer and return + *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; +} + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +#pragma GCC diagnostic pop + +#endif // MINIZ_HEADER_FILE_ONLY + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + 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 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. + + For more information, please refer to +*/ diff --git a/src/grub2/miniz.h b/src/grub2/miniz.h new file mode 100644 index 0000000..971d34e --- /dev/null +++ b/src/grub2/miniz.h @@ -0,0 +1,2 @@ +#define MINIZ_HEADER_FILE_ONLY +#include "miniz.c" diff --git a/src/grub2/wimboot.h b/src/grub2/wimboot.h new file mode 100644 index 0000000..f6f9a38 --- /dev/null +++ b/src/grub2/wimboot.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * wimboot.h + * + * Copyright (c) 2020, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ +#ifndef __WIMBOOT_H__ +#define __WIMBOOT_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hiperiso_def.h" + + +#define size_t grub_size_t +#define ssize_t grub_ssize_t +#define memset grub_memset +#define memcpy grub_memcpy + +#define uint8_t grub_uint8_t +#define uint16_t grub_uint16_t +#define uint32_t grub_uint32_t +#define uint64_t grub_uint64_t +#define int32_t grub_int32_t + + + +#define assert(exp) + +//#define DBG grub_printf +#define DBG(fmt, ...) + +const char * huffman_bin ( unsigned long value, unsigned int bits ); + +#endif + diff --git a/src/grub2/xpress.c b/src/grub2/xpress.c new file mode 100644 index 0000000..bfb3125 --- /dev/null +++ b/src/grub2/xpress.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * Xpress Compression Algorithm (MS-XCA) decompression + * + */ + +#include "wimboot.h" +#include "huffman.h" +#include "xpress.h" + +#pragma GCC diagnostic ignored "-Wcast-align" + +/** + * Decompress XCA-compressed data + * + * @v data Compressed data + * @v len Length of compressed data + * @v buf Decompression buffer, or NULL + * @ret out_len Length of decompressed data, or negative error + */ +ssize_t xca_decompress ( const void *data, size_t len, void *buf ) { + const void *src = data; + const void *end = ( uint8_t * ) src + len; + uint8_t *out = buf; + size_t out_len = 0; + size_t out_len_threshold = 0; + const struct xca_huf_len *lengths; + struct xca xca; + uint32_t accum = 0; + int extra_bits = 0; + unsigned int huf; + struct huffman_symbols *sym; + unsigned int raw; + unsigned int match_len; + unsigned int match_offset_bits; + unsigned int match_offset; + const uint8_t *copy; + int rc; + + /* Process data stream */ + while ( src < end ) { + + /* (Re)initialise decompressor if applicable */ + if ( out_len >= out_len_threshold ) { + + /* Construct symbol lengths */ + lengths = src; + src = ( uint8_t * ) src + sizeof ( *lengths ); + if ( src > end ) { + DBG ( "XCA too short to hold Huffman lengths table.\n"); + return -1; + } + for ( raw = 0 ; raw < XCA_CODES ; raw++ ) + xca.lengths[raw] = xca_huf_len ( lengths, raw ); + + /* Construct Huffman alphabet */ + if ( ( rc = huffman_alphabet ( &xca.alphabet, + xca.lengths, + XCA_CODES ) ) != 0 ) + return rc; + + /* Initialise state */ + accum = XCA_GET16 ( src ); + accum <<= 16; + accum |= XCA_GET16 ( src ); + extra_bits = 16; + + /* Determine next threshold */ + out_len_threshold = ( out_len + XCA_BLOCK_SIZE ); + } + + /* Determine symbol */ + huf = ( accum >> ( 32 - HUFFMAN_BITS ) ); + sym = huffman_sym ( &xca.alphabet, huf ); + raw = huffman_raw ( sym, huf ); + accum <<= huffman_len ( sym ); + extra_bits -= huffman_len ( sym ); + if ( extra_bits < 0 ) { + accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) ); + extra_bits += 16; + } + + /* Process symbol */ + if ( raw < XCA_END_MARKER ) { + + /* Literal symbol - add to output stream */ + if ( buf ) + *(out++) = raw; + out_len++; + + } else if ( ( raw == XCA_END_MARKER ) && + ( (uint8_t *) src >= ( ( uint8_t * ) end - 1 ) ) ) { + + /* End marker symbol */ + return out_len; + + } else { + + /* LZ77 match symbol */ + raw -= XCA_END_MARKER; + match_offset_bits = ( raw >> 4 ); + match_len = ( raw & 0x0f ); + if ( match_len == 0x0f ) { + match_len = XCA_GET8 ( src ); + if ( match_len == 0xff ) { + match_len = XCA_GET16 ( src ); + } else { + match_len += 0x0f; + } + } + match_len += 3; + if ( match_offset_bits ) { + match_offset = + ( ( accum >> ( 32 - match_offset_bits )) + + ( 1 << match_offset_bits ) ); + } else { + match_offset = 1; + } + accum <<= match_offset_bits; + extra_bits -= match_offset_bits; + if ( extra_bits < 0 ) { + accum |= ( XCA_GET16 ( src ) << (-extra_bits) ); + extra_bits += 16; + } + + /* Copy data */ + out_len += match_len; + if ( buf ) { + copy = ( out - match_offset ); + while ( match_len-- ) + *(out++) = *(copy++); + } + } + } + + return out_len; +} diff --git a/src/grub2/xpress.h b/src/grub2/xpress.h new file mode 100644 index 0000000..6a430f7 --- /dev/null +++ b/src/grub2/xpress.h @@ -0,0 +1,87 @@ +#ifndef _XCA_H +#define _XCA_H + +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * @file + * + * Xpress Compression Algorithm (MS-XCA) decompression + * + */ + +#include "huffman.h" + +/** Number of XCA codes */ +#define XCA_CODES 512 + +/** XCA decompressor */ +struct xca { + /** Huffman alphabet */ + struct huffman_alphabet alphabet; + /** Raw symbols + * + * Must immediately follow the Huffman alphabet. + */ + huffman_raw_symbol_t raw[XCA_CODES]; + /** Code lengths */ + uint8_t lengths[XCA_CODES]; +}; + +/** XCA symbol Huffman lengths table */ +struct xca_huf_len { + /** Lengths of each symbol */ + uint8_t nibbles[ XCA_CODES / 2 ]; +} __attribute__ (( packed )); + +/** + * Extract Huffman-coded length of a raw symbol + * + * @v lengths Huffman lengths table + * @v symbol Raw symbol + * @ret len Huffman-coded length + */ +static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths, + unsigned int symbol ) { + return ( ( ( lengths->nibbles[ symbol / 2 ] ) >> + ( 4 * ( symbol % 2 ) ) ) & 0x0f ); +} + +/** Get word from source data stream */ +#define XCA_GET16( src ) ( { \ + const uint16_t *src16 = src; \ + src = ( uint8_t * ) src + sizeof ( *src16 ); \ + *src16; } ) + +/** Get byte from source data stream */ +#define XCA_GET8( src ) ( { \ + const uint8_t *src8 = src; \ + src = ( uint8_t * ) src + sizeof ( *src8 ); \ + *src8; } ) + +/** XCA source data stream end marker */ +#define XCA_END_MARKER 256 + +/** XCA block size */ +#define XCA_BLOCK_SIZE ( 64 * 1024 ) + +extern ssize_t xca_decompress ( const void *data, size_t len, void *buf ); + +#endif /* _XCA_H */

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 my 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ʆIab>(NYVKaWyd4a>31ZL6UAxEul*78Tv;recH}G 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