commit 5d58b46bbe8e169af92ceb5d33d8c52b0576f8d0 Author: Thomas Oltmann Date: Sat Mar 15 18:48:09 2025 +0100 Set up a new repo based on BOOTBOOT sources diff --git a/include/bootboot.h b/include/bootboot.h new file mode 100644 index 0000000..406023f --- /dev/null +++ b/include/bootboot.h @@ -0,0 +1,155 @@ +/* + * bootboot.h + * https://gitlab.com/bztsrc/bootboot + * + * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This file is part of the BOOTBOOT Protocol package. + * @brief The BOOTBOOT structure + * + */ + +#ifndef _BOOTBOOT_H_ +#define _BOOTBOOT_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#ifndef _MSC_VER +#define _pack __attribute__((packed)) +#else +#define _pack +#pragma pack(push) +#pragma pack(1) +#endif + +#define BOOTBOOT_MAGIC "BOOT" + +/* default virtual addresses for level 0 and 1 static loaders */ +#define BOOTBOOT_MMIO 0xfffffffff8000000 /* memory mapped IO virtual address */ +#define BOOTBOOT_FB 0xfffffffffc000000 /* frame buffer virtual address */ +#define BOOTBOOT_INFO 0xffffffffffe00000 /* bootboot struct virtual address */ +#define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */ +#define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */ + +/* minimum protocol level: + * hardcoded kernel name, static kernel memory addresses */ +#define PROTOCOL_MINIMAL 0 +/* static protocol level: + * kernel name parsed from environment, static kernel memory addresses */ +#define PROTOCOL_STATIC 1 +/* dynamic protocol level: + * kernel name parsed, kernel memory addresses from ELF or PE symbols */ +#define PROTOCOL_DYNAMIC 2 +/* big-endian flag */ +#define PROTOCOL_BIGENDIAN 0x80 + +/* loader types, just informational */ +#define LOADER_BIOS (0<<2) +#define LOADER_UEFI (1<<2) +#define LOADER_RPI (2<<2) +#define LOADER_COREBOOT (3<<2) + +/* framebuffer pixel format, only 32 bits supported */ +#define FB_ARGB 0 +#define FB_RGBA 1 +#define FB_ABGR 2 +#define FB_BGRA 3 + +/* mmap entry, type is stored in least significant tetrad (half byte) of size + * this means size described in 16 byte units (not a problem, most modern + * firmware report memory in pages, 4096 byte units anyway). */ +typedef struct { + uint64_t ptr; + uint64_t size; +} _pack MMapEnt; +#define MMapEnt_Ptr(a) ((a)->ptr) +#define MMapEnt_Size(a) ((a)->size & 0xFFFFFFFFFFFFFFF0) +#define MMapEnt_Type(a) ((a)->size & 0xF) +#define MMapEnt_IsFree(a) (((a)->size&0xF)==1) + +#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ +#define MMAP_FREE 1 /* usable memory */ +#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ +#define MMAP_MMIO 3 /* memory mapped IO region */ + +#define INITRD_MAXSIZE 16 /* Mb */ + +typedef struct { + /* first 64 bytes is platform independent */ + uint8_t magic[4]; /* 'BOOT' magic */ + uint32_t size; /* length of bootboot structure, minimum 128 */ + uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ + uint8_t fb_type; /* framebuffer type, see FB_* above */ + uint16_t numcores; /* number of processor cores */ + uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ + int16_t timezone; /* in minutes -1440..1440 */ + uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ + uint64_t initrd_ptr; /* ramdisk image position and size */ + uint64_t initrd_size; + uint64_t fb_ptr; /* framebuffer pointer and dimensions */ + uint32_t fb_size; + uint32_t fb_width; + uint32_t fb_height; + uint32_t fb_scanline; + + /* the rest (64 bytes) is platform specific */ + union { + struct { + uint64_t acpi_ptr; + uint64_t smbi_ptr; + uint64_t efi_ptr; + uint64_t mp_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + } x86_64; + struct { + uint64_t acpi_ptr; + uint64_t mmio_ptr; + uint64_t efi_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + uint64_t unused4; + } aarch64; + } arch; + + /* from 128th byte, MMapEnt[], more records may follow */ + MMapEnt mmap; + /* use like this: + * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; + * until you reach bootboot->size, while(mmap_ent < bootboot + bootboot->size) */ +} _pack BOOTBOOT; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/x86_64-efi/.gitignore b/x86_64-efi/.gitignore new file mode 100644 index 0000000..9faefab --- /dev/null +++ b/x86_64-efi/.gitignore @@ -0,0 +1,2 @@ +*.o +!crt0-efi-x86_64.o diff --git a/x86_64-efi/Makefile b/x86_64-efi/Makefile new file mode 100644 index 0000000..7ae037a --- /dev/null +++ b/x86_64-efi/Makefile @@ -0,0 +1,35 @@ +ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) +GNUEFI_INCLUDES = -I/usr/include -I. -I/usr/include/efi -I/usr/include/efi/$(ARCH) -I/usr/include/efi/protocol -I../include +GNUEFI_CRT_OBJS = crt0-efi-$(ARCH).o +GNUEFI_LDS = elf_$(ARCH)_efi.lds + +CC ?= gcc +LD ?= ld +OBJCOPY ?= objcopy +CFLAGS = -mno-red-zone -mno-mmx -mno-sse -O2 -fpic -pedantic -Wall -Wextra -Werror -fshort-wchar -fno-strict-aliasing -ffreestanding -fno-stack-protector -fno-stack-check -DCONFIG_$(ARCH) -DGNU_EFI_USE_MS_ABI --std=c11 + +LDFLAGS = -nostdlib +LDFLAGS += -shared -Bsymbolic -L. $(GNUEFI_CRT_OBJS) + +TARGET = bootnetboot.efi + +all: tinflate.o smp.o $(TARGET) + +%.efi: %.so + @$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-$(ARCH) --subsystem=10 $^ $@ + @printf "BOOTBOOT Loader do not " | dd conv=notrunc of=$(TARGET) bs=1 seek=78 1>/dev/null 2>/dev/null + @$(CC) $(GNUEFI_INCLUDES) -Wall -fshort-wchar efirom.c -o efirom $(LIBS) + @./efirom $(TARGET) bootnetboot.rom || true + +%.so: %.o + @$(LD) $(LDFLAGS) tinflate.o smp.o $^ -o $@ -lefi -lgnuefi -T $(GNUEFI_LDS) + +%.o: %.c + @$(CC) $(GNUEFI_INCLUDES) $(CFLAGS) -c $< -o $@ + +%.o: %.S + @$(CC) $(GNUEFI_INCLUDES) $(CFLAGS) -c $< -o $@ + +clean: + @rm bootboot.o $(TARGET) $(TARGET) bootnetboot.rom *.so *.efi efirom tinflate.o smp.o 2>/dev/null || true + diff --git a/x86_64-efi/bootnetboot.c b/x86_64-efi/bootnetboot.c new file mode 100644 index 0000000..ff1864d --- /dev/null +++ b/x86_64-efi/bootnetboot.c @@ -0,0 +1,2193 @@ +/* + * x86_64-efi/bootboot.c + * + * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This file is part of the BOOTBOOT Protocol package. + * @brief Booting code for EFI + * + */ + +#define BBDEBUG 1 +//#define GOP_DEBUG BBDEBUG +#define USE_MP_SERVICES 0 /* without fallback to ACPI parser and APIC INIT + SIPI */ + +#if BBDEBUG +#define DBG(fmt, ...) do{Print(fmt,__VA_ARGS__); }while(0); +#else +#define DBG(fmt, ...) +#endif + +// get UEFI functions and environment +#include +#include +#include +#include +#include +#include "tinf.h" +// get BOOTBOOT specific stuff +#include + +/*** ELF64 defines and structs ***/ +#define ELFMAG "\177ELF" +#define SELFMAG 4 +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define PT_LOAD 1 /* Loadable program segment */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ + +typedef struct +{ + unsigned char e_ident[16];/* Magic number and other info */ + UINT16 e_type; /* Object file type */ + UINT16 e_machine; /* Architecture */ + UINT32 e_version; /* Object file version */ + UINT64 e_entry; /* Entry point virtual address */ + UINT64 e_phoff; /* Program header table file offset */ + UINT64 e_shoff; /* Section header table file offset */ + UINT32 e_flags; /* Processor-specific flags */ + UINT16 e_ehsize; /* ELF header size in bytes */ + UINT16 e_phentsize; /* Program header table entry size */ + UINT16 e_phnum; /* Program header table entry count */ + UINT16 e_shentsize; /* Section header table entry size */ + UINT16 e_shnum; /* Section header table entry count */ + UINT16 e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +typedef struct +{ + UINT32 p_type; /* Segment type */ + UINT32 p_flags; /* Segment flags */ + UINT64 p_offset; /* Segment file offset */ + UINT64 p_vaddr; /* Segment virtual address */ + UINT64 p_paddr; /* Segment physical address */ + UINT64 p_filesz; /* Segment size in file */ + UINT64 p_memsz; /* Segment size in memory */ + UINT64 p_align; /* Segment alignment */ +} Elf64_Phdr; + +typedef struct +{ + UINT32 sh_name; /* Section name (string tbl index) */ + UINT32 sh_type; /* Section type */ + UINT64 sh_flags; /* Section flags */ + UINT64 sh_addr; /* Section virtual addr at execution */ + UINT64 sh_offset; /* Section file offset */ + UINT64 sh_size; /* Section size in bytes */ + UINT32 sh_link; /* Link to another section */ + UINT32 sh_info; /* Additional section information */ + UINT64 sh_addralign; /* Section alignment */ + UINT64 sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +typedef struct +{ + UINT32 st_name; /* Symbol name (string tbl index) */ + UINT8 st_info; /* Symbol type and binding */ + UINT8 st_other; /* Symbol visibility */ + UINT16 st_shndx; /* Section index */ + UINT64 st_value; /* Symbol value */ + UINT64 st_size; /* Symbol size */ +} Elf64_Sym; + +/*** PE32+ defines and structs ***/ +#define MZ_MAGIC 0x5a4d /* "MZ" */ +#define PE_MAGIC 0x00004550 /* "PE\0\0" */ +#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* AMD x86_64 architecture */ +#define PE_OPT_MAGIC_PE32PLUS 0x020b /* PE32+ format */ +typedef struct +{ + UINT16 magic; /* MZ magic */ + UINT16 reserved[29]; /* reserved */ + UINT32 peaddr; /* address of pe header */ +} mz_hdr; + +typedef struct { + UINT32 magic; /* PE magic */ + UINT16 machine; /* machine type */ + UINT16 sections; /* number of sections */ + UINT32 timestamp; /* time_t */ + UINT32 sym_table; /* symbol table offset */ + INT32 numsym; /* number of symbols */ + UINT16 opt_hdr_size; /* size of optional header */ + UINT16 flags; /* flags */ + UINT16 file_type; /* file type, PE32PLUS magic */ + UINT8 ld_major; /* linker major version */ + UINT8 ld_minor; /* linker minor version */ + UINT32 text_size; /* size of text section(s) */ + UINT32 data_size; /* size of data section(s) */ + UINT32 bss_size; /* size of bss section(s) */ + INT32 entry_point; /* file offset of entry point */ + INT32 code_base; /* relative code addr in ram */ +} pe_hdr; + +typedef struct { + UINT32 iszero; /* if this is not zero, then iszero+nameoffs gives UTF-8 string */ + UINT32 nameoffs; + INT32 value; /* value of the symbol */ + UINT16 section; /* section it belongs to */ + UINT16 type; /* symbol type */ + UINT8 storclass; /* storage class */ + UINT8 auxsyms; /* number of pe_sym records following */ +} pe_sym; + +/*** EFI defines and structs ***/ +struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; +struct EFI_FILE_PROTOCOL; + +#if USE_MP_SERVICES +#ifndef EFI_MP_SERVICES_PROTOCOL_GUID +#define EFI_MP_SERVICES_PROTOCOL_GUID \ + { 0x3fdda605, 0xa76e, 0x4f46, {0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08} } +typedef struct _EFI_MP_SERVICES_PROTOCOL EFI_MP_SERVICES_PROTOCOL; + +#define PROCESSOR_AS_BSP_BIT 0x00000001 + +typedef struct { + UINT64 ProcessorId; + UINT32 StatusFlag; +} EFI_PROCESSOR_INFORMATION; + +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_DUMMY)( + IN EFI_MP_SERVICES_PROTOCOL *This + ); + +typedef +VOID +(EFIAPI *EFI_AP_PROCEDURE)( + IN OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS)( + IN EFI_MP_SERVICES_PROTOCOL *This, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_GET_PROCESSOR_INFO)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_STARTUP_THIS_AP)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT BOOLEAN *Finished OPTIONAL + ); + +struct _EFI_MP_SERVICES_PROTOCOL { + EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors; + EFI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo; + EFI_MP_SERVICES_DUMMY StartupAllAPs; + EFI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; + EFI_MP_SERVICES_DUMMY SwitchBSP; + EFI_MP_SERVICES_DUMMY EnableDisableAP; + EFI_MP_SERVICES_DUMMY WhoAmI; +}; +#endif +#else +extern void ap_trampoline(); +UINT16 lapic_ids[1024]; +UINT64 lapic_addr=0; +#endif + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( + IN struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT struct EFI_FILE_PROTOCOL **Root + ); + +/* Intel EFI headers has simple file protocol, but not GNU EFI */ +#ifndef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_FILE_PROTOCOL { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; +} EFI_FILE_PROTOCOL; +#endif + +#ifndef EFI_PCI_OPTION_ROM_TABLE_GUID +#define EFI_PCI_OPTION_ROM_TABLE_GUID \ + { 0x7462660f, 0x1cbd, 0x48da, {0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c} } +typedef struct { + EFI_PHYSICAL_ADDRESS RomAddress; + EFI_MEMORY_TYPE MemoryType; + UINT32 RomLength; + UINT32 Seg; + UINT8 Bus; + UINT8 Dev; + UINT8 Func; + BOOLEAN ExecutedLegacyBiosImage; + BOOLEAN DontLoadEfiRom; +} EFI_PCI_OPTION_ROM_DESCRIPTOR; + +typedef struct { + UINT64 PciOptionRomCount; + EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptors; +} EFI_PCI_OPTION_ROM_TABLE; +#endif + +#ifndef EFI_SERIAL_IO_PROTOCOL_GUID +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + { 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD} } + +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} EFI_PARITY_TYPE; + +typedef enum { + DefaultStopBits, + OneStopBit, // 1 stop bit + OneFiveStopBits, // 1.5 stop bits + TwoStopBits // 2 stop bits +} EFI_STOP_BITS_TYPE; + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_DUMMY)( + IN EFI_SERIAL_IO_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_ATTRIBUTES) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_WRITE) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_READ) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +typedef struct _EFI_SERIAL_IO_PROTOCOL { + UINT32 Revision; + EFI_SERIAL_DUMMY Reset; + EFI_SERIAL_SET_ATTRIBUTES SetAttributes; + EFI_SERIAL_DUMMY SetControl; + EFI_SERIAL_DUMMY GetControl; + EFI_SERIAL_WRITE Write; + EFI_SERIAL_READ Read; +} EFI_SERIAL_IO_PROTOCOL; +#endif + +/*** other defines and structs ***/ +typedef struct { + UINT8 magic[8]; + UINT8 chksum; + CHAR8 oemid[6]; + UINT8 revision; + UINT32 rsdt; + UINT32 length; + UINT64 xsdt; + UINT32 echksum; +} __attribute__((packed)) ACPI_RSDPTR; + +#define PAGESIZE 4096 + +/** + * return type for fs drivers + */ +typedef struct { + UINT8 *ptr; + UINTN size; +} file_t; + +/*** common variables ***/ +file_t env; // environment file descriptor +file_t initrd; // initrd file descriptor +file_t core; // kernel file descriptor +BOOTBOOT *bootboot; // the BOOTBOOT structure +UINT64 *paging; // paging table for MMU +UINT64 entrypoint; // kernel entry point +UINT64 fb_addr = BOOTBOOT_FB; // virtual addresses +UINT64 bb_addr = BOOTBOOT_INFO; +UINT64 env_addr= BOOTBOOT_ENV; +UINT64 core_addr=BOOTBOOT_CORE; + +UINT64 initstack = 1024; + +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; +EFI_FILE_HANDLE RootDir; +EFI_FILE_PROTOCOL *Root; +SIMPLE_INPUT_INTERFACE *CI; +unsigned char *kne, nosmp=0; +volatile char bsp_done=0, ap_done=0; + +// default environment variables. M$ states that 1024x768 must be supported +int reqwidth = 1024, reqheight = 768; +char *kernelname="sys/core"; + +// alternative environment name +char *cfgname="sys/config"; + +/** + * SHA-256 + */ +typedef struct { + UINT8 d[64]; + UINT32 l; + UINT32 b[2]; + UINT32 s[8]; +} SHA256_CTX; +#define SHA_ADD(a,b,c) if(a>0xffffffff-(c))b++;a+=c; +#define SHA_ROTL(a,b) (((a)<<(b))|((a)>>(32-(b)))) +#define SHA_ROTR(a,b) (((a)>>(b))|((a)<<(32-(b)))) +#define SHA_CH(x,y,z) (((x)&(y))^(~(x)&(z))) +#define SHA_MAJ(x,y,z) (((x)&(y))^((x)&(z))^((y)&(z))) +#define SHA_EP0(x) (SHA_ROTR(x,2)^SHA_ROTR(x,13)^SHA_ROTR(x,22)) +#define SHA_EP1(x) (SHA_ROTR(x,6)^SHA_ROTR(x,11)^SHA_ROTR(x,25)) +#define SHA_SIG0(x) (SHA_ROTR(x,7)^SHA_ROTR(x,18)^((x)>>3)) +#define SHA_SIG1(x) (SHA_ROTR(x,17)^SHA_ROTR(x,19)^((x)>>10)) +static UINT32 sha256_k[64]={ + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +}; +void sha256_t(SHA256_CTX *ctx) +{ + UINT32 a,b,c,d,e,f,g,h,i,j,t1,t2,m[64]; + for(i=0,j=0;i<16;i++,j+=4) m[i]=(ctx->d[j]<<24)|(ctx->d[j+1]<<16)|(ctx->d[j+2]<<8)|(ctx->d[j+3]); + for(;i<64;i++) m[i]=SHA_SIG1(m[i-2])+m[i-7]+SHA_SIG0(m[i-15])+m[i-16]; + a=ctx->s[0];b=ctx->s[1];c=ctx->s[2];d=ctx->s[3]; + e=ctx->s[4];f=ctx->s[5];g=ctx->s[6];h=ctx->s[7]; + for(i=0;i<64;i++) { + t1=h+SHA_EP1(e)+SHA_CH(e,f,g)+sha256_k[i]+m[i]; + t2=SHA_EP0(a)+SHA_MAJ(a,b,c);h=g;g=f;f=e;e=d+t1;d=c;c=b;b=a;a=t1+t2; + } + ctx->s[0]+=a;ctx->s[1]+=b;ctx->s[2]+=c;ctx->s[3]+=d; + ctx->s[4]+=e;ctx->s[5]+=f;ctx->s[6]+=g;ctx->s[7]+=h; +} +void SHA256_Init(SHA256_CTX *ctx) +{ + ctx->l=0;ctx->b[0]=ctx->b[1]=0; + ctx->s[0]=0x6a09e667;ctx->s[1]=0xbb67ae85;ctx->s[2]=0x3c6ef372;ctx->s[3]=0xa54ff53a; + ctx->s[4]=0x510e527f;ctx->s[5]=0x9b05688c;ctx->s[6]=0x1f83d9ab;ctx->s[7]=0x5be0cd19; +} +void SHA256_Update(SHA256_CTX *ctx, const void *data, int len) +{ + UINT8 *d=(UINT8 *)data; + for(;len--;d++) { + ctx->d[ctx->l++]=*d; + if(ctx->l==64) {sha256_t(ctx);SHA_ADD(ctx->b[0],ctx->b[1],512);ctx->l=0;} + } +} +void SHA256_Final(unsigned char *h, SHA256_CTX *ctx) +{ + UINT32 i=ctx->l; + ctx->d[i++]=0x80; + if(ctx->l<56) {while(i<56) ctx->d[i++]=0x00;} + else {while(i<64) ctx->d[i++]=0x00;sha256_t(ctx);ZeroMem(ctx->d,56);} + SHA_ADD(ctx->b[0],ctx->b[1],ctx->l*8); + ctx->d[63]=ctx->b[0];ctx->d[62]=ctx->b[0]>>8;ctx->d[61]=ctx->b[0]>>16;ctx->d[60]=ctx->b[0]>>24; + ctx->d[59]=ctx->b[1];ctx->d[58]=ctx->b[1]>>8;ctx->d[57]=ctx->b[1]>>16;ctx->d[56]=ctx->b[1]>>24; + sha256_t(ctx); + for(i=0;i<4;i++) { + h[i] =(ctx->s[0]>>(24-i*8)); h[i+4] =(ctx->s[1]>>(24-i*8)); + h[i+8] =(ctx->s[2]>>(24-i*8)); h[i+12]=(ctx->s[3]>>(24-i*8)); + h[i+16]=(ctx->s[4]>>(24-i*8)); h[i+20]=(ctx->s[5]>>(24-i*8)); + h[i+24]=(ctx->s[6]>>(24-i*8)); h[i+28]=(ctx->s[7]>>(24-i*8)); + } +} + +/** + * precalculated CRC32c lookup table for polynomial 0x1EDC6F41 (castagnoli-crc) + */ +UINT32 crc32c_lookup[256]={ + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, + 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, + 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, + 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, + 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, + 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, + 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, + 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, + 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, + 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, + 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, + 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, + 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, + 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, + 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, + 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, + 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, + 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; +UINT32 crc32_calc(char *start,int length) +{ + UINT32 crc32_val=0; + while(length--) crc32_val=(crc32_val>>8)^crc32c_lookup[(crc32_val&0xff)^(unsigned char)*start++]; + return crc32_val; +} + +/** + * AES-256-CBC + */ +#define GETU32(pt) (((UINT32)(pt)[0]<<24)^((UINT32)(pt)[1]<<16)^((UINT32)(pt)[2]<<8)^((UINT32)(pt)[3])) +#define PUTU32(ct,st) {(ct)[0]=(UINT8)((st)>>24);(ct)[1]=(UINT8)((st)>>16);(ct)[2]=(UINT8)((st)>>8);(ct)[3]=(UINT8)(st);} +static const UINT32 Te0[256]={ + 0xc66363a5U,0xf87c7c84U,0xee777799U,0xf67b7b8dU,0xfff2f20dU,0xd66b6bbdU,0xde6f6fb1U,0x91c5c554U, + 0x60303050U,0x02010103U,0xce6767a9U,0x562b2b7dU,0xe7fefe19U,0xb5d7d762U,0x4dababe6U,0xec76769aU, + 0x8fcaca45U,0x1f82829dU,0x89c9c940U,0xfa7d7d87U,0xeffafa15U,0xb25959ebU,0x8e4747c9U,0xfbf0f00bU, + 0x41adadecU,0xb3d4d467U,0x5fa2a2fdU,0x45afafeaU,0x239c9cbfU,0x53a4a4f7U,0xe4727296U,0x9bc0c05bU, + 0x75b7b7c2U,0xe1fdfd1cU,0x3d9393aeU,0x4c26266aU,0x6c36365aU,0x7e3f3f41U,0xf5f7f702U,0x83cccc4fU, + 0x6834345cU,0x51a5a5f4U,0xd1e5e534U,0xf9f1f108U,0xe2717193U,0xabd8d873U,0x62313153U,0x2a15153fU, + 0x0804040cU,0x95c7c752U,0x46232365U,0x9dc3c35eU,0x30181828U,0x379696a1U,0x0a05050fU,0x2f9a9ab5U, + 0x0e070709U,0x24121236U,0x1b80809bU,0xdfe2e23dU,0xcdebeb26U,0x4e272769U,0x7fb2b2cdU,0xea75759fU, + 0x1209091bU,0x1d83839eU,0x582c2c74U,0x341a1a2eU,0x361b1b2dU,0xdc6e6eb2U,0xb45a5aeeU,0x5ba0a0fbU, + 0xa45252f6U,0x763b3b4dU,0xb7d6d661U,0x7db3b3ceU,0x5229297bU,0xdde3e33eU,0x5e2f2f71U,0x13848497U, + 0xa65353f5U,0xb9d1d168U,0x00000000U,0xc1eded2cU,0x40202060U,0xe3fcfc1fU,0x79b1b1c8U,0xb65b5bedU, + 0xd46a6abeU,0x8dcbcb46U,0x67bebed9U,0x7239394bU,0x944a4adeU,0x984c4cd4U,0xb05858e8U,0x85cfcf4aU, + 0xbbd0d06bU,0xc5efef2aU,0x4faaaae5U,0xedfbfb16U,0x864343c5U,0x9a4d4dd7U,0x66333355U,0x11858594U, + 0x8a4545cfU,0xe9f9f910U,0x04020206U,0xfe7f7f81U,0xa05050f0U,0x783c3c44U,0x259f9fbaU,0x4ba8a8e3U, + 0xa25151f3U,0x5da3a3feU,0x804040c0U,0x058f8f8aU,0x3f9292adU,0x219d9dbcU,0x70383848U,0xf1f5f504U, + 0x63bcbcdfU,0x77b6b6c1U,0xafdada75U,0x42212163U,0x20101030U,0xe5ffff1aU,0xfdf3f30eU,0xbfd2d26dU, + 0x81cdcd4cU,0x180c0c14U,0x26131335U,0xc3ecec2fU,0xbe5f5fe1U,0x359797a2U,0x884444ccU,0x2e171739U, + 0x93c4c457U,0x55a7a7f2U,0xfc7e7e82U,0x7a3d3d47U,0xc86464acU,0xba5d5de7U,0x3219192bU,0xe6737395U, + 0xc06060a0U,0x19818198U,0x9e4f4fd1U,0xa3dcdc7fU,0x44222266U,0x542a2a7eU,0x3b9090abU,0x0b888883U, + 0x8c4646caU,0xc7eeee29U,0x6bb8b8d3U,0x2814143cU,0xa7dede79U,0xbc5e5ee2U,0x160b0b1dU,0xaddbdb76U, + 0xdbe0e03bU,0x64323256U,0x743a3a4eU,0x140a0a1eU,0x924949dbU,0x0c06060aU,0x4824246cU,0xb85c5ce4U, + 0x9fc2c25dU,0xbdd3d36eU,0x43acacefU,0xc46262a6U,0x399191a8U,0x319595a4U,0xd3e4e437U,0xf279798bU, + 0xd5e7e732U,0x8bc8c843U,0x6e373759U,0xda6d6db7U,0x018d8d8cU,0xb1d5d564U,0x9c4e4ed2U,0x49a9a9e0U, + 0xd86c6cb4U,0xac5656faU,0xf3f4f407U,0xcfeaea25U,0xca6565afU,0xf47a7a8eU,0x47aeaee9U,0x10080818U, + 0x6fbabad5U,0xf0787888U,0x4a25256fU,0x5c2e2e72U,0x381c1c24U,0x57a6a6f1U,0x73b4b4c7U,0x97c6c651U, + 0xcbe8e823U,0xa1dddd7cU,0xe874749cU,0x3e1f1f21U,0x964b4bddU,0x61bdbddcU,0x0d8b8b86U,0x0f8a8a85U, + 0xe0707090U,0x7c3e3e42U,0x71b5b5c4U,0xcc6666aaU,0x904848d8U,0x06030305U,0xf7f6f601U,0x1c0e0e12U, + 0xc26161a3U,0x6a35355fU,0xae5757f9U,0x69b9b9d0U,0x17868691U,0x99c1c158U,0x3a1d1d27U,0x279e9eb9U, + 0xd9e1e138U,0xebf8f813U,0x2b9898b3U,0x22111133U,0xd26969bbU,0xa9d9d970U,0x078e8e89U,0x339494a7U, + 0x2d9b9bb6U,0x3c1e1e22U,0x15878792U,0xc9e9e920U,0x87cece49U,0xaa5555ffU,0x50282878U,0xa5dfdf7aU, + 0x038c8c8fU,0x59a1a1f8U,0x09898980U,0x1a0d0d17U,0x65bfbfdaU,0xd7e6e631U,0x844242c6U,0xd06868b8U, + 0x824141c3U,0x299999b0U,0x5a2d2d77U,0x1e0f0f11U,0x7bb0b0cbU,0xa85454fcU,0x6dbbbbd6U,0x2c16163aU, +}; +static const UINT32 Te1[256]={ + 0xa5c66363U,0x84f87c7cU,0x99ee7777U,0x8df67b7bU,0x0dfff2f2U,0xbdd66b6bU,0xb1de6f6fU,0x5491c5c5U, + 0x50603030U,0x03020101U,0xa9ce6767U,0x7d562b2bU,0x19e7fefeU,0x62b5d7d7U,0xe64dababU,0x9aec7676U, + 0x458fcacaU,0x9d1f8282U,0x4089c9c9U,0x87fa7d7dU,0x15effafaU,0xebb25959U,0xc98e4747U,0x0bfbf0f0U, + 0xec41adadU,0x67b3d4d4U,0xfd5fa2a2U,0xea45afafU,0xbf239c9cU,0xf753a4a4U,0x96e47272U,0x5b9bc0c0U, + 0xc275b7b7U,0x1ce1fdfdU,0xae3d9393U,0x6a4c2626U,0x5a6c3636U,0x417e3f3fU,0x02f5f7f7U,0x4f83ccccU, + 0x5c683434U,0xf451a5a5U,0x34d1e5e5U,0x08f9f1f1U,0x93e27171U,0x73abd8d8U,0x53623131U,0x3f2a1515U, + 0x0c080404U,0x5295c7c7U,0x65462323U,0x5e9dc3c3U,0x28301818U,0xa1379696U,0x0f0a0505U,0xb52f9a9aU, + 0x090e0707U,0x36241212U,0x9b1b8080U,0x3ddfe2e2U,0x26cdebebU,0x694e2727U,0xcd7fb2b2U,0x9fea7575U, + 0x1b120909U,0x9e1d8383U,0x74582c2cU,0x2e341a1aU,0x2d361b1bU,0xb2dc6e6eU,0xeeb45a5aU,0xfb5ba0a0U, + 0xf6a45252U,0x4d763b3bU,0x61b7d6d6U,0xce7db3b3U,0x7b522929U,0x3edde3e3U,0x715e2f2fU,0x97138484U, + 0xf5a65353U,0x68b9d1d1U,0x00000000U,0x2cc1ededU,0x60402020U,0x1fe3fcfcU,0xc879b1b1U,0xedb65b5bU, + 0xbed46a6aU,0x468dcbcbU,0xd967bebeU,0x4b723939U,0xde944a4aU,0xd4984c4cU,0xe8b05858U,0x4a85cfcfU, + 0x6bbbd0d0U,0x2ac5efefU,0xe54faaaaU,0x16edfbfbU,0xc5864343U,0xd79a4d4dU,0x55663333U,0x94118585U, + 0xcf8a4545U,0x10e9f9f9U,0x06040202U,0x81fe7f7fU,0xf0a05050U,0x44783c3cU,0xba259f9fU,0xe34ba8a8U, + 0xf3a25151U,0xfe5da3a3U,0xc0804040U,0x8a058f8fU,0xad3f9292U,0xbc219d9dU,0x48703838U,0x04f1f5f5U, + 0xdf63bcbcU,0xc177b6b6U,0x75afdadaU,0x63422121U,0x30201010U,0x1ae5ffffU,0x0efdf3f3U,0x6dbfd2d2U, + 0x4c81cdcdU,0x14180c0cU,0x35261313U,0x2fc3ececU,0xe1be5f5fU,0xa2359797U,0xcc884444U,0x392e1717U, + 0x5793c4c4U,0xf255a7a7U,0x82fc7e7eU,0x477a3d3dU,0xacc86464U,0xe7ba5d5dU,0x2b321919U,0x95e67373U, + 0xa0c06060U,0x98198181U,0xd19e4f4fU,0x7fa3dcdcU,0x66442222U,0x7e542a2aU,0xab3b9090U,0x830b8888U, + 0xca8c4646U,0x29c7eeeeU,0xd36bb8b8U,0x3c281414U,0x79a7dedeU,0xe2bc5e5eU,0x1d160b0bU,0x76addbdbU, + 0x3bdbe0e0U,0x56643232U,0x4e743a3aU,0x1e140a0aU,0xdb924949U,0x0a0c0606U,0x6c482424U,0xe4b85c5cU, + 0x5d9fc2c2U,0x6ebdd3d3U,0xef43acacU,0xa6c46262U,0xa8399191U,0xa4319595U,0x37d3e4e4U,0x8bf27979U, + 0x32d5e7e7U,0x438bc8c8U,0x596e3737U,0xb7da6d6dU,0x8c018d8dU,0x64b1d5d5U,0xd29c4e4eU,0xe049a9a9U, + 0xb4d86c6cU,0xfaac5656U,0x07f3f4f4U,0x25cfeaeaU,0xafca6565U,0x8ef47a7aU,0xe947aeaeU,0x18100808U, + 0xd56fbabaU,0x88f07878U,0x6f4a2525U,0x725c2e2eU,0x24381c1cU,0xf157a6a6U,0xc773b4b4U,0x5197c6c6U, + 0x23cbe8e8U,0x7ca1ddddU,0x9ce87474U,0x213e1f1fU,0xdd964b4bU,0xdc61bdbdU,0x860d8b8bU,0x850f8a8aU, + 0x90e07070U,0x427c3e3eU,0xc471b5b5U,0xaacc6666U,0xd8904848U,0x05060303U,0x01f7f6f6U,0x121c0e0eU, + 0xa3c26161U,0x5f6a3535U,0xf9ae5757U,0xd069b9b9U,0x91178686U,0x5899c1c1U,0x273a1d1dU,0xb9279e9eU, + 0x38d9e1e1U,0x13ebf8f8U,0xb32b9898U,0x33221111U,0xbbd26969U,0x70a9d9d9U,0x89078e8eU,0xa7339494U, + 0xb62d9b9bU,0x223c1e1eU,0x92158787U,0x20c9e9e9U,0x4987ceceU,0xffaa5555U,0x78502828U,0x7aa5dfdfU, + 0x8f038c8cU,0xf859a1a1U,0x80098989U,0x171a0d0dU,0xda65bfbfU,0x31d7e6e6U,0xc6844242U,0xb8d06868U, + 0xc3824141U,0xb0299999U,0x775a2d2dU,0x111e0f0fU,0xcb7bb0b0U,0xfca85454U,0xd66dbbbbU,0x3a2c1616U, +}; +static const UINT32 Te2[256]={ + 0x63a5c663U,0x7c84f87cU,0x7799ee77U,0x7b8df67bU,0xf20dfff2U,0x6bbdd66bU,0x6fb1de6fU,0xc55491c5U, + 0x30506030U,0x01030201U,0x67a9ce67U,0x2b7d562bU,0xfe19e7feU,0xd762b5d7U,0xabe64dabU,0x769aec76U, + 0xca458fcaU,0x829d1f82U,0xc94089c9U,0x7d87fa7dU,0xfa15effaU,0x59ebb259U,0x47c98e47U,0xf00bfbf0U, + 0xadec41adU,0xd467b3d4U,0xa2fd5fa2U,0xafea45afU,0x9cbf239cU,0xa4f753a4U,0x7296e472U,0xc05b9bc0U, + 0xb7c275b7U,0xfd1ce1fdU,0x93ae3d93U,0x266a4c26U,0x365a6c36U,0x3f417e3fU,0xf702f5f7U,0xcc4f83ccU, + 0x345c6834U,0xa5f451a5U,0xe534d1e5U,0xf108f9f1U,0x7193e271U,0xd873abd8U,0x31536231U,0x153f2a15U, + 0x040c0804U,0xc75295c7U,0x23654623U,0xc35e9dc3U,0x18283018U,0x96a13796U,0x050f0a05U,0x9ab52f9aU, + 0x07090e07U,0x12362412U,0x809b1b80U,0xe23ddfe2U,0xeb26cdebU,0x27694e27U,0xb2cd7fb2U,0x759fea75U, + 0x091b1209U,0x839e1d83U,0x2c74582cU,0x1a2e341aU,0x1b2d361bU,0x6eb2dc6eU,0x5aeeb45aU,0xa0fb5ba0U, + 0x52f6a452U,0x3b4d763bU,0xd661b7d6U,0xb3ce7db3U,0x297b5229U,0xe33edde3U,0x2f715e2fU,0x84971384U, + 0x53f5a653U,0xd168b9d1U,0x00000000U,0xed2cc1edU,0x20604020U,0xfc1fe3fcU,0xb1c879b1U,0x5bedb65bU, + 0x6abed46aU,0xcb468dcbU,0xbed967beU,0x394b7239U,0x4ade944aU,0x4cd4984cU,0x58e8b058U,0xcf4a85cfU, + 0xd06bbbd0U,0xef2ac5efU,0xaae54faaU,0xfb16edfbU,0x43c58643U,0x4dd79a4dU,0x33556633U,0x85941185U, + 0x45cf8a45U,0xf910e9f9U,0x02060402U,0x7f81fe7fU,0x50f0a050U,0x3c44783cU,0x9fba259fU,0xa8e34ba8U, + 0x51f3a251U,0xa3fe5da3U,0x40c08040U,0x8f8a058fU,0x92ad3f92U,0x9dbc219dU,0x38487038U,0xf504f1f5U, + 0xbcdf63bcU,0xb6c177b6U,0xda75afdaU,0x21634221U,0x10302010U,0xff1ae5ffU,0xf30efdf3U,0xd26dbfd2U, + 0xcd4c81cdU,0x0c14180cU,0x13352613U,0xec2fc3ecU,0x5fe1be5fU,0x97a23597U,0x44cc8844U,0x17392e17U, + 0xc45793c4U,0xa7f255a7U,0x7e82fc7eU,0x3d477a3dU,0x64acc864U,0x5de7ba5dU,0x192b3219U,0x7395e673U, + 0x60a0c060U,0x81981981U,0x4fd19e4fU,0xdc7fa3dcU,0x22664422U,0x2a7e542aU,0x90ab3b90U,0x88830b88U, + 0x46ca8c46U,0xee29c7eeU,0xb8d36bb8U,0x143c2814U,0xde79a7deU,0x5ee2bc5eU,0x0b1d160bU,0xdb76addbU, + 0xe03bdbe0U,0x32566432U,0x3a4e743aU,0x0a1e140aU,0x49db9249U,0x060a0c06U,0x246c4824U,0x5ce4b85cU, + 0xc25d9fc2U,0xd36ebdd3U,0xacef43acU,0x62a6c462U,0x91a83991U,0x95a43195U,0xe437d3e4U,0x798bf279U, + 0xe732d5e7U,0xc8438bc8U,0x37596e37U,0x6db7da6dU,0x8d8c018dU,0xd564b1d5U,0x4ed29c4eU,0xa9e049a9U, + 0x6cb4d86cU,0x56faac56U,0xf407f3f4U,0xea25cfeaU,0x65afca65U,0x7a8ef47aU,0xaee947aeU,0x08181008U, + 0xbad56fbaU,0x7888f078U,0x256f4a25U,0x2e725c2eU,0x1c24381cU,0xa6f157a6U,0xb4c773b4U,0xc65197c6U, + 0xe823cbe8U,0xdd7ca1ddU,0x749ce874U,0x1f213e1fU,0x4bdd964bU,0xbddc61bdU,0x8b860d8bU,0x8a850f8aU, + 0x7090e070U,0x3e427c3eU,0xb5c471b5U,0x66aacc66U,0x48d89048U,0x03050603U,0xf601f7f6U,0x0e121c0eU, + 0x61a3c261U,0x355f6a35U,0x57f9ae57U,0xb9d069b9U,0x86911786U,0xc15899c1U,0x1d273a1dU,0x9eb9279eU, + 0xe138d9e1U,0xf813ebf8U,0x98b32b98U,0x11332211U,0x69bbd269U,0xd970a9d9U,0x8e89078eU,0x94a73394U, + 0x9bb62d9bU,0x1e223c1eU,0x87921587U,0xe920c9e9U,0xce4987ceU,0x55ffaa55U,0x28785028U,0xdf7aa5dfU, + 0x8c8f038cU,0xa1f859a1U,0x89800989U,0x0d171a0dU,0xbfda65bfU,0xe631d7e6U,0x42c68442U,0x68b8d068U, + 0x41c38241U,0x99b02999U,0x2d775a2dU,0x0f111e0fU,0xb0cb7bb0U,0x54fca854U,0xbbd66dbbU,0x163a2c16U, +}; +static const UINT32 Te3[256]={ + 0x6363a5c6U,0x7c7c84f8U,0x777799eeU,0x7b7b8df6U,0xf2f20dffU,0x6b6bbdd6U,0x6f6fb1deU,0xc5c55491U, + 0x30305060U,0x01010302U,0x6767a9ceU,0x2b2b7d56U,0xfefe19e7U,0xd7d762b5U,0xababe64dU,0x76769aecU, + 0xcaca458fU,0x82829d1fU,0xc9c94089U,0x7d7d87faU,0xfafa15efU,0x5959ebb2U,0x4747c98eU,0xf0f00bfbU, + 0xadadec41U,0xd4d467b3U,0xa2a2fd5fU,0xafafea45U,0x9c9cbf23U,0xa4a4f753U,0x727296e4U,0xc0c05b9bU, + 0xb7b7c275U,0xfdfd1ce1U,0x9393ae3dU,0x26266a4cU,0x36365a6cU,0x3f3f417eU,0xf7f702f5U,0xcccc4f83U, + 0x34345c68U,0xa5a5f451U,0xe5e534d1U,0xf1f108f9U,0x717193e2U,0xd8d873abU,0x31315362U,0x15153f2aU, + 0x04040c08U,0xc7c75295U,0x23236546U,0xc3c35e9dU,0x18182830U,0x9696a137U,0x05050f0aU,0x9a9ab52fU, + 0x0707090eU,0x12123624U,0x80809b1bU,0xe2e23ddfU,0xebeb26cdU,0x2727694eU,0xb2b2cd7fU,0x75759feaU, + 0x09091b12U,0x83839e1dU,0x2c2c7458U,0x1a1a2e34U,0x1b1b2d36U,0x6e6eb2dcU,0x5a5aeeb4U,0xa0a0fb5bU, + 0x5252f6a4U,0x3b3b4d76U,0xd6d661b7U,0xb3b3ce7dU,0x29297b52U,0xe3e33eddU,0x2f2f715eU,0x84849713U, + 0x5353f5a6U,0xd1d168b9U,0x00000000U,0xeded2cc1U,0x20206040U,0xfcfc1fe3U,0xb1b1c879U,0x5b5bedb6U, + 0x6a6abed4U,0xcbcb468dU,0xbebed967U,0x39394b72U,0x4a4ade94U,0x4c4cd498U,0x5858e8b0U,0xcfcf4a85U, + 0xd0d06bbbU,0xefef2ac5U,0xaaaae54fU,0xfbfb16edU,0x4343c586U,0x4d4dd79aU,0x33335566U,0x85859411U, + 0x4545cf8aU,0xf9f910e9U,0x02020604U,0x7f7f81feU,0x5050f0a0U,0x3c3c4478U,0x9f9fba25U,0xa8a8e34bU, + 0x5151f3a2U,0xa3a3fe5dU,0x4040c080U,0x8f8f8a05U,0x9292ad3fU,0x9d9dbc21U,0x38384870U,0xf5f504f1U, + 0xbcbcdf63U,0xb6b6c177U,0xdada75afU,0x21216342U,0x10103020U,0xffff1ae5U,0xf3f30efdU,0xd2d26dbfU, + 0xcdcd4c81U,0x0c0c1418U,0x13133526U,0xecec2fc3U,0x5f5fe1beU,0x9797a235U,0x4444cc88U,0x1717392eU, + 0xc4c45793U,0xa7a7f255U,0x7e7e82fcU,0x3d3d477aU,0x6464acc8U,0x5d5de7baU,0x19192b32U,0x737395e6U, + 0x6060a0c0U,0x81819819U,0x4f4fd19eU,0xdcdc7fa3U,0x22226644U,0x2a2a7e54U,0x9090ab3bU,0x8888830bU, + 0x4646ca8cU,0xeeee29c7U,0xb8b8d36bU,0x14143c28U,0xdede79a7U,0x5e5ee2bcU,0x0b0b1d16U,0xdbdb76adU, + 0xe0e03bdbU,0x32325664U,0x3a3a4e74U,0x0a0a1e14U,0x4949db92U,0x06060a0cU,0x24246c48U,0x5c5ce4b8U, + 0xc2c25d9fU,0xd3d36ebdU,0xacacef43U,0x6262a6c4U,0x9191a839U,0x9595a431U,0xe4e437d3U,0x79798bf2U, + 0xe7e732d5U,0xc8c8438bU,0x3737596eU,0x6d6db7daU,0x8d8d8c01U,0xd5d564b1U,0x4e4ed29cU,0xa9a9e049U, + 0x6c6cb4d8U,0x5656faacU,0xf4f407f3U,0xeaea25cfU,0x6565afcaU,0x7a7a8ef4U,0xaeaee947U,0x08081810U, + 0xbabad56fU,0x787888f0U,0x25256f4aU,0x2e2e725cU,0x1c1c2438U,0xa6a6f157U,0xb4b4c773U,0xc6c65197U, + 0xe8e823cbU,0xdddd7ca1U,0x74749ce8U,0x1f1f213eU,0x4b4bdd96U,0xbdbddc61U,0x8b8b860dU,0x8a8a850fU, + 0x707090e0U,0x3e3e427cU,0xb5b5c471U,0x6666aaccU,0x4848d890U,0x03030506U,0xf6f601f7U,0x0e0e121cU, + 0x6161a3c2U,0x35355f6aU,0x5757f9aeU,0xb9b9d069U,0x86869117U,0xc1c15899U,0x1d1d273aU,0x9e9eb927U, + 0xe1e138d9U,0xf8f813ebU,0x9898b32bU,0x11113322U,0x6969bbd2U,0xd9d970a9U,0x8e8e8907U,0x9494a733U, + 0x9b9bb62dU,0x1e1e223cU,0x87879215U,0xe9e920c9U,0xcece4987U,0x5555ffaaU,0x28287850U,0xdfdf7aa5U, + 0x8c8c8f03U,0xa1a1f859U,0x89898009U,0x0d0d171aU,0xbfbfda65U,0xe6e631d7U,0x4242c684U,0x6868b8d0U, + 0x4141c382U,0x9999b029U,0x2d2d775aU,0x0f0f111eU,0xb0b0cb7bU,0x5454fca8U,0xbbbbd66dU,0x16163a2cU, +}; + +static const UINT32 Td0[256]={ + 0x51f4a750U,0x7e416553U,0x1a17a4c3U,0x3a275e96U,0x3bab6bcbU,0x1f9d45f1U,0xacfa58abU,0x4be30393U, + 0x2030fa55U,0xad766df6U,0x88cc7691U,0xf5024c25U,0x4fe5d7fcU,0xc52acbd7U,0x26354480U,0xb562a38fU, + 0xdeb15a49U,0x25ba1b67U,0x45ea0e98U,0x5dfec0e1U,0xc32f7502U,0x814cf012U,0x8d4697a3U,0x6bd3f9c6U, + 0x038f5fe7U,0x15929c95U,0xbf6d7aebU,0x955259daU,0xd4be832dU,0x587421d3U,0x49e06929U,0x8ec9c844U, + 0x75c2896aU,0xf48e7978U,0x99583e6bU,0x27b971ddU,0xbee14fb6U,0xf088ad17U,0xc920ac66U,0x7dce3ab4U, + 0x63df4a18U,0xe51a3182U,0x97513360U,0x62537f45U,0xb16477e0U,0xbb6bae84U,0xfe81a01cU,0xf9082b94U, + 0x70486858U,0x8f45fd19U,0x94de6c87U,0x527bf8b7U,0xab73d323U,0x724b02e2U,0xe31f8f57U,0x6655ab2aU, + 0xb2eb2807U,0x2fb5c203U,0x86c57b9aU,0xd33708a5U,0x302887f2U,0x23bfa5b2U,0x02036abaU,0xed16825cU, + 0x8acf1c2bU,0xa779b492U,0xf307f2f0U,0x4e69e2a1U,0x65daf4cdU,0x0605bed5U,0xd134621fU,0xc4a6fe8aU, + 0x342e539dU,0xa2f355a0U,0x058ae132U,0xa4f6eb75U,0x0b83ec39U,0x4060efaaU,0x5e719f06U,0xbd6e1051U, + 0x3e218af9U,0x96dd063dU,0xdd3e05aeU,0x4de6bd46U,0x91548db5U,0x71c45d05U,0x0406d46fU,0x605015ffU, + 0x1998fb24U,0xd6bde997U,0x894043ccU,0x67d99e77U,0xb0e842bdU,0x07898b88U,0xe7195b38U,0x79c8eedbU, + 0xa17c0a47U,0x7c420fe9U,0xf8841ec9U,0x00000000U,0x09808683U,0x322bed48U,0x1e1170acU,0x6c5a724eU, + 0xfd0efffbU,0x0f853856U,0x3daed51eU,0x362d3927U,0x0a0fd964U,0x685ca621U,0x9b5b54d1U,0x24362e3aU, + 0x0c0a67b1U,0x9357e70fU,0xb4ee96d2U,0x1b9b919eU,0x80c0c54fU,0x61dc20a2U,0x5a774b69U,0x1c121a16U, + 0xe293ba0aU,0xc0a02ae5U,0x3c22e043U,0x121b171dU,0x0e090d0bU,0xf28bc7adU,0x2db6a8b9U,0x141ea9c8U, + 0x57f11985U,0xaf75074cU,0xee99ddbbU,0xa37f60fdU,0xf701269fU,0x5c72f5bcU,0x44663bc5U,0x5bfb7e34U, + 0x8b432976U,0xcb23c6dcU,0xb6edfc68U,0xb8e4f163U,0xd731dccaU,0x42638510U,0x13972240U,0x84c61120U, + 0x854a247dU,0xd2bb3df8U,0xaef93211U,0xc729a16dU,0x1d9e2f4bU,0xdcb230f3U,0x0d8652ecU,0x77c1e3d0U, + 0x2bb3166cU,0xa970b999U,0x119448faU,0x47e96422U,0xa8fc8cc4U,0xa0f03f1aU,0x567d2cd8U,0x223390efU, + 0x87494ec7U,0xd938d1c1U,0x8ccaa2feU,0x98d40b36U,0xa6f581cfU,0xa57ade28U,0xdab78e26U,0x3fadbfa4U, + 0x2c3a9de4U,0x5078920dU,0x6a5fcc9bU,0x547e4662U,0xf68d13c2U,0x90d8b8e8U,0x2e39f75eU,0x82c3aff5U, + 0x9f5d80beU,0x69d0937cU,0x6fd52da9U,0xcf2512b3U,0xc8ac993bU,0x10187da7U,0xe89c636eU,0xdb3bbb7bU, + 0xcd267809U,0x6e5918f4U,0xec9ab701U,0x834f9aa8U,0xe6956e65U,0xaaffe67eU,0x21bccf08U,0xef15e8e6U, + 0xbae79bd9U,0x4a6f36ceU,0xea9f09d4U,0x29b07cd6U,0x31a4b2afU,0x2a3f2331U,0xc6a59430U,0x35a266c0U, + 0x744ebc37U,0xfc82caa6U,0xe090d0b0U,0x33a7d815U,0xf104984aU,0x41ecdaf7U,0x7fcd500eU,0x1791f62fU, + 0x764dd68dU,0x43efb04dU,0xccaa4d54U,0xe49604dfU,0x9ed1b5e3U,0x4c6a881bU,0xc12c1fb8U,0x4665517fU, + 0x9d5eea04U,0x018c355dU,0xfa877473U,0xfb0b412eU,0xb3671d5aU,0x92dbd252U,0xe9105633U,0x6dd64713U, + 0x9ad7618cU,0x37a10c7aU,0x59f8148eU,0xeb133c89U,0xcea927eeU,0xb761c935U,0xe11ce5edU,0x7a47b13cU, + 0x9cd2df59U,0x55f2733fU,0x1814ce79U,0x73c737bfU,0x53f7cdeaU,0x5ffdaa5bU,0xdf3d6f14U,0x7844db86U, + 0xcaaff381U,0xb968c43eU,0x3824342cU,0xc2a3405fU,0x161dc372U,0xbce2250cU,0x283c498bU,0xff0d9541U, + 0x39a80171U,0x080cb3deU,0xd8b4e49cU,0x6456c190U,0x7bcb8461U,0xd532b670U,0x486c5c74U,0xd0b85742U, +}; +static const UINT32 Td1[256]={ + 0x5051f4a7U,0x537e4165U,0xc31a17a4U,0x963a275eU,0xcb3bab6bU,0xf11f9d45U,0xabacfa58U,0x934be303U, + 0x552030faU,0xf6ad766dU,0x9188cc76U,0x25f5024cU,0xfc4fe5d7U,0xd7c52acbU,0x80263544U,0x8fb562a3U, + 0x49deb15aU,0x6725ba1bU,0x9845ea0eU,0xe15dfec0U,0x02c32f75U,0x12814cf0U,0xa38d4697U,0xc66bd3f9U, + 0xe7038f5fU,0x9515929cU,0xebbf6d7aU,0xda955259U,0x2dd4be83U,0xd3587421U,0x2949e069U,0x448ec9c8U, + 0x6a75c289U,0x78f48e79U,0x6b99583eU,0xdd27b971U,0xb6bee14fU,0x17f088adU,0x66c920acU,0xb47dce3aU, + 0x1863df4aU,0x82e51a31U,0x60975133U,0x4562537fU,0xe0b16477U,0x84bb6baeU,0x1cfe81a0U,0x94f9082bU, + 0x58704868U,0x198f45fdU,0x8794de6cU,0xb7527bf8U,0x23ab73d3U,0xe2724b02U,0x57e31f8fU,0x2a6655abU, + 0x07b2eb28U,0x032fb5c2U,0x9a86c57bU,0xa5d33708U,0xf2302887U,0xb223bfa5U,0xba02036aU,0x5ced1682U, + 0x2b8acf1cU,0x92a779b4U,0xf0f307f2U,0xa14e69e2U,0xcd65daf4U,0xd50605beU,0x1fd13462U,0x8ac4a6feU, + 0x9d342e53U,0xa0a2f355U,0x32058ae1U,0x75a4f6ebU,0x390b83ecU,0xaa4060efU,0x065e719fU,0x51bd6e10U, + 0xf93e218aU,0x3d96dd06U,0xaedd3e05U,0x464de6bdU,0xb591548dU,0x0571c45dU,0x6f0406d4U,0xff605015U, + 0x241998fbU,0x97d6bde9U,0xcc894043U,0x7767d99eU,0xbdb0e842U,0x8807898bU,0x38e7195bU,0xdb79c8eeU, + 0x47a17c0aU,0xe97c420fU,0xc9f8841eU,0x00000000U,0x83098086U,0x48322bedU,0xac1e1170U,0x4e6c5a72U, + 0xfbfd0effU,0x560f8538U,0x1e3daed5U,0x27362d39U,0x640a0fd9U,0x21685ca6U,0xd19b5b54U,0x3a24362eU, + 0xb10c0a67U,0x0f9357e7U,0xd2b4ee96U,0x9e1b9b91U,0x4f80c0c5U,0xa261dc20U,0x695a774bU,0x161c121aU, + 0x0ae293baU,0xe5c0a02aU,0x433c22e0U,0x1d121b17U,0x0b0e090dU,0xadf28bc7U,0xb92db6a8U,0xc8141ea9U, + 0x8557f119U,0x4caf7507U,0xbbee99ddU,0xfda37f60U,0x9ff70126U,0xbc5c72f5U,0xc544663bU,0x345bfb7eU, + 0x768b4329U,0xdccb23c6U,0x68b6edfcU,0x63b8e4f1U,0xcad731dcU,0x10426385U,0x40139722U,0x2084c611U, + 0x7d854a24U,0xf8d2bb3dU,0x11aef932U,0x6dc729a1U,0x4b1d9e2fU,0xf3dcb230U,0xec0d8652U,0xd077c1e3U, + 0x6c2bb316U,0x99a970b9U,0xfa119448U,0x2247e964U,0xc4a8fc8cU,0x1aa0f03fU,0xd8567d2cU,0xef223390U, + 0xc787494eU,0xc1d938d1U,0xfe8ccaa2U,0x3698d40bU,0xcfa6f581U,0x28a57adeU,0x26dab78eU,0xa43fadbfU, + 0xe42c3a9dU,0x0d507892U,0x9b6a5fccU,0x62547e46U,0xc2f68d13U,0xe890d8b8U,0x5e2e39f7U,0xf582c3afU, + 0xbe9f5d80U,0x7c69d093U,0xa96fd52dU,0xb3cf2512U,0x3bc8ac99U,0xa710187dU,0x6ee89c63U,0x7bdb3bbbU, + 0x09cd2678U,0xf46e5918U,0x01ec9ab7U,0xa8834f9aU,0x65e6956eU,0x7eaaffe6U,0x0821bccfU,0xe6ef15e8U, + 0xd9bae79bU,0xce4a6f36U,0xd4ea9f09U,0xd629b07cU,0xaf31a4b2U,0x312a3f23U,0x30c6a594U,0xc035a266U, + 0x37744ebcU,0xa6fc82caU,0xb0e090d0U,0x1533a7d8U,0x4af10498U,0xf741ecdaU,0x0e7fcd50U,0x2f1791f6U, + 0x8d764dd6U,0x4d43efb0U,0x54ccaa4dU,0xdfe49604U,0xe39ed1b5U,0x1b4c6a88U,0xb8c12c1fU,0x7f466551U, + 0x049d5eeaU,0x5d018c35U,0x73fa8774U,0x2efb0b41U,0x5ab3671dU,0x5292dbd2U,0x33e91056U,0x136dd647U, + 0x8c9ad761U,0x7a37a10cU,0x8e59f814U,0x89eb133cU,0xeecea927U,0x35b761c9U,0xede11ce5U,0x3c7a47b1U, + 0x599cd2dfU,0x3f55f273U,0x791814ceU,0xbf73c737U,0xea53f7cdU,0x5b5ffdaaU,0x14df3d6fU,0x867844dbU, + 0x81caaff3U,0x3eb968c4U,0x2c382434U,0x5fc2a340U,0x72161dc3U,0x0cbce225U,0x8b283c49U,0x41ff0d95U, + 0x7139a801U,0xde080cb3U,0x9cd8b4e4U,0x906456c1U,0x617bcb84U,0x70d532b6U,0x74486c5cU,0x42d0b857U, +}; +static const UINT32 Td2[256]={ + 0xa75051f4U,0x65537e41U,0xa4c31a17U,0x5e963a27U,0x6bcb3babU,0x45f11f9dU,0x58abacfaU,0x03934be3U, + 0xfa552030U,0x6df6ad76U,0x769188ccU,0x4c25f502U,0xd7fc4fe5U,0xcbd7c52aU,0x44802635U,0xa38fb562U, + 0x5a49deb1U,0x1b6725baU,0x0e9845eaU,0xc0e15dfeU,0x7502c32fU,0xf012814cU,0x97a38d46U,0xf9c66bd3U, + 0x5fe7038fU,0x9c951592U,0x7aebbf6dU,0x59da9552U,0x832dd4beU,0x21d35874U,0x692949e0U,0xc8448ec9U, + 0x896a75c2U,0x7978f48eU,0x3e6b9958U,0x71dd27b9U,0x4fb6bee1U,0xad17f088U,0xac66c920U,0x3ab47dceU, + 0x4a1863dfU,0x3182e51aU,0x33609751U,0x7f456253U,0x77e0b164U,0xae84bb6bU,0xa01cfe81U,0x2b94f908U, + 0x68587048U,0xfd198f45U,0x6c8794deU,0xf8b7527bU,0xd323ab73U,0x02e2724bU,0x8f57e31fU,0xab2a6655U, + 0x2807b2ebU,0xc2032fb5U,0x7b9a86c5U,0x08a5d337U,0x87f23028U,0xa5b223bfU,0x6aba0203U,0x825ced16U, + 0x1c2b8acfU,0xb492a779U,0xf2f0f307U,0xe2a14e69U,0xf4cd65daU,0xbed50605U,0x621fd134U,0xfe8ac4a6U, + 0x539d342eU,0x55a0a2f3U,0xe132058aU,0xeb75a4f6U,0xec390b83U,0xefaa4060U,0x9f065e71U,0x1051bd6eU, + 0x8af93e21U,0x063d96ddU,0x05aedd3eU,0xbd464de6U,0x8db59154U,0x5d0571c4U,0xd46f0406U,0x15ff6050U, + 0xfb241998U,0xe997d6bdU,0x43cc8940U,0x9e7767d9U,0x42bdb0e8U,0x8b880789U,0x5b38e719U,0xeedb79c8U, + 0x0a47a17cU,0x0fe97c42U,0x1ec9f884U,0x00000000U,0x86830980U,0xed48322bU,0x70ac1e11U,0x724e6c5aU, + 0xfffbfd0eU,0x38560f85U,0xd51e3daeU,0x3927362dU,0xd9640a0fU,0xa621685cU,0x54d19b5bU,0x2e3a2436U, + 0x67b10c0aU,0xe70f9357U,0x96d2b4eeU,0x919e1b9bU,0xc54f80c0U,0x20a261dcU,0x4b695a77U,0x1a161c12U, + 0xba0ae293U,0x2ae5c0a0U,0xe0433c22U,0x171d121bU,0x0d0b0e09U,0xc7adf28bU,0xa8b92db6U,0xa9c8141eU, + 0x198557f1U,0x074caf75U,0xddbbee99U,0x60fda37fU,0x269ff701U,0xf5bc5c72U,0x3bc54466U,0x7e345bfbU, + 0x29768b43U,0xc6dccb23U,0xfc68b6edU,0xf163b8e4U,0xdccad731U,0x85104263U,0x22401397U,0x112084c6U, + 0x247d854aU,0x3df8d2bbU,0x3211aef9U,0xa16dc729U,0x2f4b1d9eU,0x30f3dcb2U,0x52ec0d86U,0xe3d077c1U, + 0x166c2bb3U,0xb999a970U,0x48fa1194U,0x642247e9U,0x8cc4a8fcU,0x3f1aa0f0U,0x2cd8567dU,0x90ef2233U, + 0x4ec78749U,0xd1c1d938U,0xa2fe8ccaU,0x0b3698d4U,0x81cfa6f5U,0xde28a57aU,0x8e26dab7U,0xbfa43fadU, + 0x9de42c3aU,0x920d5078U,0xcc9b6a5fU,0x4662547eU,0x13c2f68dU,0xb8e890d8U,0xf75e2e39U,0xaff582c3U, + 0x80be9f5dU,0x937c69d0U,0x2da96fd5U,0x12b3cf25U,0x993bc8acU,0x7da71018U,0x636ee89cU,0xbb7bdb3bU, + 0x7809cd26U,0x18f46e59U,0xb701ec9aU,0x9aa8834fU,0x6e65e695U,0xe67eaaffU,0xcf0821bcU,0xe8e6ef15U, + 0x9bd9bae7U,0x36ce4a6fU,0x09d4ea9fU,0x7cd629b0U,0xb2af31a4U,0x23312a3fU,0x9430c6a5U,0x66c035a2U, + 0xbc37744eU,0xcaa6fc82U,0xd0b0e090U,0xd81533a7U,0x984af104U,0xdaf741ecU,0x500e7fcdU,0xf62f1791U, + 0xd68d764dU,0xb04d43efU,0x4d54ccaaU,0x04dfe496U,0xb5e39ed1U,0x881b4c6aU,0x1fb8c12cU,0x517f4665U, + 0xea049d5eU,0x355d018cU,0x7473fa87U,0x412efb0bU,0x1d5ab367U,0xd25292dbU,0x5633e910U,0x47136dd6U, + 0x618c9ad7U,0x0c7a37a1U,0x148e59f8U,0x3c89eb13U,0x27eecea9U,0xc935b761U,0xe5ede11cU,0xb13c7a47U, + 0xdf599cd2U,0x733f55f2U,0xce791814U,0x37bf73c7U,0xcdea53f7U,0xaa5b5ffdU,0x6f14df3dU,0xdb867844U, + 0xf381caafU,0xc43eb968U,0x342c3824U,0x405fc2a3U,0xc372161dU,0x250cbce2U,0x498b283cU,0x9541ff0dU, + 0x017139a8U,0xb3de080cU,0xe49cd8b4U,0xc1906456U,0x84617bcbU,0xb670d532U,0x5c74486cU,0x5742d0b8U, +}; +static const UINT32 Td3[256]={ + 0xf4a75051U,0x4165537eU,0x17a4c31aU,0x275e963aU,0xab6bcb3bU,0x9d45f11fU,0xfa58abacU,0xe303934bU, + 0x30fa5520U,0x766df6adU,0xcc769188U,0x024c25f5U,0xe5d7fc4fU,0x2acbd7c5U,0x35448026U,0x62a38fb5U, + 0xb15a49deU,0xba1b6725U,0xea0e9845U,0xfec0e15dU,0x2f7502c3U,0x4cf01281U,0x4697a38dU,0xd3f9c66bU, + 0x8f5fe703U,0x929c9515U,0x6d7aebbfU,0x5259da95U,0xbe832dd4U,0x7421d358U,0xe0692949U,0xc9c8448eU, + 0xc2896a75U,0x8e7978f4U,0x583e6b99U,0xb971dd27U,0xe14fb6beU,0x88ad17f0U,0x20ac66c9U,0xce3ab47dU, + 0xdf4a1863U,0x1a3182e5U,0x51336097U,0x537f4562U,0x6477e0b1U,0x6bae84bbU,0x81a01cfeU,0x082b94f9U, + 0x48685870U,0x45fd198fU,0xde6c8794U,0x7bf8b752U,0x73d323abU,0x4b02e272U,0x1f8f57e3U,0x55ab2a66U, + 0xeb2807b2U,0xb5c2032fU,0xc57b9a86U,0x3708a5d3U,0x2887f230U,0xbfa5b223U,0x036aba02U,0x16825cedU, + 0xcf1c2b8aU,0x79b492a7U,0x07f2f0f3U,0x69e2a14eU,0xdaf4cd65U,0x05bed506U,0x34621fd1U,0xa6fe8ac4U, + 0x2e539d34U,0xf355a0a2U,0x8ae13205U,0xf6eb75a4U,0x83ec390bU,0x60efaa40U,0x719f065eU,0x6e1051bdU, + 0x218af93eU,0xdd063d96U,0x3e05aeddU,0xe6bd464dU,0x548db591U,0xc45d0571U,0x06d46f04U,0x5015ff60U, + 0x98fb2419U,0xbde997d6U,0x4043cc89U,0xd99e7767U,0xe842bdb0U,0x898b8807U,0x195b38e7U,0xc8eedb79U, + 0x7c0a47a1U,0x420fe97cU,0x841ec9f8U,0x00000000U,0x80868309U,0x2bed4832U,0x1170ac1eU,0x5a724e6cU, + 0x0efffbfdU,0x8538560fU,0xaed51e3dU,0x2d392736U,0x0fd9640aU,0x5ca62168U,0x5b54d19bU,0x362e3a24U, + 0x0a67b10cU,0x57e70f93U,0xee96d2b4U,0x9b919e1bU,0xc0c54f80U,0xdc20a261U,0x774b695aU,0x121a161cU, + 0x93ba0ae2U,0xa02ae5c0U,0x22e0433cU,0x1b171d12U,0x090d0b0eU,0x8bc7adf2U,0xb6a8b92dU,0x1ea9c814U, + 0xf1198557U,0x75074cafU,0x99ddbbeeU,0x7f60fda3U,0x01269ff7U,0x72f5bc5cU,0x663bc544U,0xfb7e345bU, + 0x4329768bU,0x23c6dccbU,0xedfc68b6U,0xe4f163b8U,0x31dccad7U,0x63851042U,0x97224013U,0xc6112084U, + 0x4a247d85U,0xbb3df8d2U,0xf93211aeU,0x29a16dc7U,0x9e2f4b1dU,0xb230f3dcU,0x8652ec0dU,0xc1e3d077U, + 0xb3166c2bU,0x70b999a9U,0x9448fa11U,0xe9642247U,0xfc8cc4a8U,0xf03f1aa0U,0x7d2cd856U,0x3390ef22U, + 0x494ec787U,0x38d1c1d9U,0xcaa2fe8cU,0xd40b3698U,0xf581cfa6U,0x7ade28a5U,0xb78e26daU,0xadbfa43fU, + 0x3a9de42cU,0x78920d50U,0x5fcc9b6aU,0x7e466254U,0x8d13c2f6U,0xd8b8e890U,0x39f75e2eU,0xc3aff582U, + 0x5d80be9fU,0xd0937c69U,0xd52da96fU,0x2512b3cfU,0xac993bc8U,0x187da710U,0x9c636ee8U,0x3bbb7bdbU, + 0x267809cdU,0x5918f46eU,0x9ab701ecU,0x4f9aa883U,0x956e65e6U,0xffe67eaaU,0xbccf0821U,0x15e8e6efU, + 0xe79bd9baU,0x6f36ce4aU,0x9f09d4eaU,0xb07cd629U,0xa4b2af31U,0x3f23312aU,0xa59430c6U,0xa266c035U, + 0x4ebc3774U,0x82caa6fcU,0x90d0b0e0U,0xa7d81533U,0x04984af1U,0xecdaf741U,0xcd500e7fU,0x91f62f17U, + 0x4dd68d76U,0xefb04d43U,0xaa4d54ccU,0x9604dfe4U,0xd1b5e39eU,0x6a881b4cU,0x2c1fb8c1U,0x65517f46U, + 0x5eea049dU,0x8c355d01U,0x877473faU,0x0b412efbU,0x671d5ab3U,0xdbd25292U,0x105633e9U,0xd647136dU, + 0xd7618c9aU,0xa10c7a37U,0xf8148e59U,0x133c89ebU,0xa927eeceU,0x61c935b7U,0x1ce5ede1U,0x47b13c7aU, + 0xd2df599cU,0xf2733f55U,0x14ce7918U,0xc737bf73U,0xf7cdea53U,0xfdaa5b5fU,0x3d6f14dfU,0x44db8678U, + 0xaff381caU,0x68c43eb9U,0x24342c38U,0xa3405fc2U,0x1dc37216U,0xe2250cbcU,0x3c498b28U,0x0d9541ffU, + 0xa8017139U,0x0cb3de08U,0xb4e49cd8U,0x56c19064U,0xcb84617bU,0x32b670d5U,0x6c5c7448U,0xb85742d0U, +}; +static const UINT8 Td4[256]={ + 0x52U,0x09U,0x6aU,0xd5U,0x30U,0x36U,0xa5U,0x38U,0xbfU,0x40U,0xa3U,0x9eU,0x81U,0xf3U,0xd7U,0xfbU, + 0x7cU,0xe3U,0x39U,0x82U,0x9bU,0x2fU,0xffU,0x87U,0x34U,0x8eU,0x43U,0x44U,0xc4U,0xdeU,0xe9U,0xcbU, + 0x54U,0x7bU,0x94U,0x32U,0xa6U,0xc2U,0x23U,0x3dU,0xeeU,0x4cU,0x95U,0x0bU,0x42U,0xfaU,0xc3U,0x4eU, + 0x08U,0x2eU,0xa1U,0x66U,0x28U,0xd9U,0x24U,0xb2U,0x76U,0x5bU,0xa2U,0x49U,0x6dU,0x8bU,0xd1U,0x25U, + 0x72U,0xf8U,0xf6U,0x64U,0x86U,0x68U,0x98U,0x16U,0xd4U,0xa4U,0x5cU,0xccU,0x5dU,0x65U,0xb6U,0x92U, + 0x6cU,0x70U,0x48U,0x50U,0xfdU,0xedU,0xb9U,0xdaU,0x5eU,0x15U,0x46U,0x57U,0xa7U,0x8dU,0x9dU,0x84U, + 0x90U,0xd8U,0xabU,0x00U,0x8cU,0xbcU,0xd3U,0x0aU,0xf7U,0xe4U,0x58U,0x05U,0xb8U,0xb3U,0x45U,0x06U, + 0xd0U,0x2cU,0x1eU,0x8fU,0xcaU,0x3fU,0x0fU,0x02U,0xc1U,0xafU,0xbdU,0x03U,0x01U,0x13U,0x8aU,0x6bU, + 0x3aU,0x91U,0x11U,0x41U,0x4fU,0x67U,0xdcU,0xeaU,0x97U,0xf2U,0xcfU,0xceU,0xf0U,0xb4U,0xe6U,0x73U, + 0x96U,0xacU,0x74U,0x22U,0xe7U,0xadU,0x35U,0x85U,0xe2U,0xf9U,0x37U,0xe8U,0x1cU,0x75U,0xdfU,0x6eU, + 0x47U,0xf1U,0x1aU,0x71U,0x1dU,0x29U,0xc5U,0x89U,0x6fU,0xb7U,0x62U,0x0eU,0xaaU,0x18U,0xbeU,0x1bU, + 0xfcU,0x56U,0x3eU,0x4bU,0xc6U,0xd2U,0x79U,0x20U,0x9aU,0xdbU,0xc0U,0xfeU,0x78U,0xcdU,0x5aU,0xf4U, + 0x1fU,0xddU,0xa8U,0x33U,0x88U,0x07U,0xc7U,0x31U,0xb1U,0x12U,0x10U,0x59U,0x27U,0x80U,0xecU,0x5fU, + 0x60U,0x51U,0x7fU,0xa9U,0x19U,0xb5U,0x4aU,0x0dU,0x2dU,0xe5U,0x7aU,0x9fU,0x93U,0xc9U,0x9cU,0xefU, + 0xa0U,0xe0U,0x3bU,0x4dU,0xaeU,0x2aU,0xf5U,0xb0U,0xc8U,0xebU,0xbbU,0x3cU,0x83U,0x53U,0x99U,0x61U, + 0x17U,0x2bU,0x04U,0x7eU,0xbaU,0x77U,0xd6U,0x26U,0xe1U,0x69U,0x14U,0x63U,0x55U,0x21U,0x0cU,0x7dU, +}; +static const UINT32 rcon[]={ + 0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1B000000 +}; +UINT32 decrd[4*15]; +UINT8 aes_iv[16]; + +void aes_init(unsigned char *pass) +{ + UINT32 i=0,j=0,t,*rk; + CopyMem(aes_iv,pass+(pass[0]&0xF),16); + rk=decrd; + rk[0]=GETU32(pass );rk[1]=GETU32(pass+ 4);rk[2]=GETU32(pass+ 8);rk[3]=GETU32(pass+12); + rk[4]=GETU32(pass+16);rk[5]=GETU32(pass+20);rk[6]=GETU32(pass+24);rk[7]=GETU32(pass+28); + while (1) { + t=rk[7];rk[8]=rk[0]^(Te2[(t>>16)&0xff]&0xff000000)^(Te3[(t>>8)&0xff]&0x00ff0000)^ + (Te0[(t)&0xff]&0x0000ff00)^(Te1[(t>>24)]&0x000000ff)^rcon[i]; + rk[9]=rk[1]^rk[8];rk[10]=rk[2]^rk[9];rk[11]=rk[3]^rk[10]; + if(++i==7) break; + t=rk[11];rk[12]=rk[4]^(Te2[(t>>24)]&0xff000000)^(Te3[(t>>16)&0xff]&0x00ff0000)^ + (Te0[(t>>8)&0xff]&0x0000ff00)^(Te1[(t)&0xff]&0x000000ff); + rk[13]=rk[5]^rk[12];rk[14]=rk[6]^rk[13];rk[15]=rk[7]^rk[14];rk+=8; + } + rk=decrd; + for(i=0,j=4*14;i>24)]&0xff]^Td1[Te1[(rk[0]>>16)&0xff]&0xff]^ + Td2[Te1[(rk[0]>>8)&0xff]&0xff]^Td3[Te1[(rk[0])&0xff]&0xff]; + rk[1]=Td0[Te1[(rk[1]>>24)]&0xff]^Td1[Te1[(rk[1]>>16)&0xff]&0xff]^ + Td2[Te1[(rk[1]>>8)&0xff]&0xff]^Td3[Te1[(rk[1])&0xff]&0xff]; + rk[2]=Td0[Te1[(rk[2]>>24)]&0xff]^Td1[Te1[(rk[2]>>16)&0xff]&0xff]^ + Td2[Te1[(rk[2]>>8)&0xff]&0xff]^Td3[Te1[(rk[2])&0xff]&0xff]; + rk[3]=Td0[Te1[(rk[3]>>24)]&0xff]^Td1[Te1[(rk[3]>>16)&0xff]&0xff]^ + Td2[Te1[(rk[3]>>8)&0xff]&0xff]^Td3[Te1[(rk[3])&0xff]&0xff]; + } +} + +void aes_dec(unsigned char *data, UINT32 l) +{ + UINT32 rd[4*15],*rk=rd,n,s0,s1,s2,s3,t0,t1,t2,t3; + unsigned char ivec[16],c[sizeof(ivec)],d,*out=data; + CopyMem(&rd,&decrd,sizeof(rd)); + CopyMem(ivec,aes_iv,sizeof(ivec)); + while(l>=16) { + rk=rd;s0=GETU32(out)^rk[0];s1=GETU32(out+4)^rk[1];s2=GETU32(out+8)^rk[2];s3=GETU32(out+12)^rk[3]; + for(n=14>>1;;){ + t0=Td0[(s0>>24)]^Td1[(s3>>16)&0xff]^Td2[(s2>>8)&0xff]^Td3[(s1)&0xff]^rk[4]; + t1=Td0[(s1>>24)]^Td1[(s0>>16)&0xff]^Td2[(s3>>8)&0xff]^Td3[(s2)&0xff]^rk[5]; + t2=Td0[(s2>>24)]^Td1[(s1>>16)&0xff]^Td2[(s0>>8)&0xff]^Td3[(s3)&0xff]^rk[6]; + t3=Td0[(s3>>24)]^Td1[(s2>>16)&0xff]^Td2[(s1>>8)&0xff]^Td3[(s0)&0xff]^rk[7]; + rk+=8; + if(--n==0) break; + s0=Td0[(t0>>24)]^Td1[(t3>>16)&0xff]^Td2[(t2>>8)&0xff]^Td3[(t1)&0xff]^rk[0]; + s1=Td0[(t1>>24)]^Td1[(t0>>16)&0xff]^Td2[(t3>>8)&0xff]^Td3[(t2)&0xff]^rk[1]; + s2=Td0[(t2>>24)]^Td1[(t1>>16)&0xff]^Td2[(t0>>8)&0xff]^Td3[(t3)&0xff]^rk[2]; + s3=Td0[(t3>>24)]^Td1[(t2>>16)&0xff]^Td2[(t1>>8)&0xff]^Td3[(t0)&0xff]^rk[3]; + } + s0=((uint32_t)Td4[(t0>>24)]<<24)^((uint32_t)Td4[(t3>>16)&0xff]<<16)^ + ((uint32_t)Td4[(t2>>8)&0xff]<<8)^((uint32_t)Td4[(t1)&0xff])^rk[0]; + PUTU32(c,s0); + s1=((uint32_t)Td4[(t1>>24)]<<24)^((uint32_t)Td4[(t0>>16)&0xff]<<16)^ + ((uint32_t)Td4[(t3>>8)&0xff]<<8)^((uint32_t)Td4[(t2)&0xff])^rk[1]; + PUTU32(c+4,s1); + s2=((uint32_t)Td4[(t2>>24)]<<24)^((uint32_t)Td4[(t1>>16)&0xff]<<16)^ + ((uint32_t)Td4[(t0>>8)&0xff]<<8)^((uint32_t)Td4[(t3)&0xff])^rk[2]; + PUTU32(c+8,s2); + s3=((uint32_t)Td4[(t3>>24)]<<24)^((uint32_t)Td4[(t2>>16)&0xff]<<16)^ + ((uint32_t)Td4[(t1>>8)&0xff]<<8)^((uint32_t)Td4[(t0)&0xff])^rk[3]; + PUTU32(c+12,s3); + for(n=0;n<16;n++) {d=out[n];out[n]=c[n]^ivec[n];ivec[n]=d;} + l-=16; + out+=16; + } +} + +/** + * Read a line from ConIn + */ +int ReadLine(unsigned char *buf, int l) +{ + int i=0; + EFI_INPUT_KEY key; + while(1) { + if(!uefi_call_wrapper(CI->ReadKeyStroke, 2, CI, &key)) { + if(key.UnicodeChar==CHAR_LINEFEED || key.UnicodeChar==CHAR_CARRIAGE_RETURN) { + break; + } else + if(key.UnicodeChar==CHAR_BACKSPACE || key.ScanCode==SCAN_DELETE) { + if(i) i--; + buf[i]=0; + continue; + } else + if(key.ScanCode==SCAN_ESC) { + buf[0]=0; + return 0; + } else + if(key.UnicodeChar && i>6)&0x1F)|0xC0; + buf[i++]=(key.UnicodeChar&0x3F)|0x80; + } else { + buf[i++]=((key.UnicodeChar>>12)&0xF)|0xE0; + buf[i++]=((key.UnicodeChar>>6)&0x3F)|0x80; + buf[i++]=(key.UnicodeChar&0x3F)|0x80; + } + buf[i]=0; + } + } + } + return i; +} + +/** + * function to convert ascii to number + */ +int atoi(unsigned char*c) +{ + int r=0; + while(*c>='0'&&*c<='9') { + r*=10; r+=*c-'0'; + c++; + } + return r; +} + +/** + * convert ascii to unicode characters + */ +CHAR16 * +a2u (char *str) +{ + static CHAR16 mem[PAGESIZE]; + int i; + + for (i = 0; str[i]; ++i) + mem[i] = (CHAR16) str[i]; + mem[i] = 0; + return mem; +} + +/** + * report status with message to standard output + */ +EFI_STATUS +report(EFI_STATUS Status,CHAR16 *Msg) +{ + Print(L"BOOTBOOT-PANIC: %s (EFI %r)\n",Msg,Status); + return Status; +} + +/** + * convert ascii octal number to binary number + */ +int oct2bin(unsigned char *str,int size) +{ + int s=0; + unsigned char *c=str; + while(size-->0){ + s*=8; + s+=*c-'0'; + c++; + } + return s; +} + +/** + * convert ascii hex number to binary number + */ +int hex2bin(unsigned char *str, int size) +{ + int v=0; + while(size-->0){ + v <<= 4; + if(*str>='0' && *str<='9') + v += (int)((unsigned char)(*str)-'0'); + else if(*str >= 'A' && *str <= 'F') + v += (int)((unsigned char)(*str)-'A'+10); + str++; + } + return v; +} + +/** + * Add a mapping to paging tables + */ +int freep = 24; +void MapPage(UINT64 virt, UINT64 phys) +{ + int i,j; + j = (virt>>(9+12)) & 0x1FF; + if(!paging[22*512 + j] || (paging[22*512 + j] & 0xFF) == 0x83) { + if(freep == 37) return; + paging[22*512 + j]=(UINT64)((UINT8 *)paging+freep*PAGESIZE+3); + freep++; + } + i = (paging[22*512 + j] - (UINT64)((UINT8 *)paging)) >> 12; + j = (virt>>(12)) & 0x1FF; + paging[i*512 + j] = phys | 1; +} + +// get filesystem drivers for initrd +#include "fs.h" + +/** + * Parse FS0:\BOOTBOOT\CONFIG or /sys/config + */ +EFI_STATUS +ParseEnvironment(unsigned char *cfg, int len, INTN argc, CHAR16 **argv) +{ + unsigned char *ptr=cfg-1; + int i; + // failsafe + if(len>PAGESIZE-1) { + len=PAGESIZE-1; + } + // append temporary variables provided on EFI command line + // if a key exists multiple times, the last is used + cfg[len]=0; + if(argc>2){ + ptr=cfg+len; + for(i=3;icfg && ptr[-1]!=' '&&ptr[-1]!='\t'&&ptr[-1]!='\r'&&ptr[-1]!='\n') + continue; + // parse screen dimensions + if(!CompareMem(ptr,(const CHAR8 *)"screen=",7)){ + ptr+=7; + reqwidth=atoi(ptr); + while(ptrLocateProtocol, 3, &gopGuid, NULL, (void**)&gop); + if(EFI_ERROR(status) && gop) + return status; + + // minimum resolution + if(reqwidth < 640) reqwidth = 640; + if(reqheight < 480) reqheight = 480; + + // get current video mode + status = uefi_call_wrapper(gop->QueryMode, 4, gop, gop->Mode==NULL?0:gop->Mode->Mode, &SizeOfInfo, &info); + if (status == EFI_NOT_STARTED) + status = uefi_call_wrapper(gop->SetMode, 2, gop, 0); + if(EFI_ERROR(status)) + return status; + nativeMode = gop->Mode->Mode; + imax=gop->Mode->MaxMode; + for (i = 0; i < imax; i++) { + status = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, &info); + // failsafe + if (EFI_ERROR(status)) + continue; +#if GOP_DEBUG + valid=0; +#endif + // get the mode for the closest resolution + if((info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor || + info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor +// there's a bug in TianoCore, it reports bad masks in PixelInformation, so we don't use PixelBitMask +// || (info->PixelFormat == PixelBitMask) + )){ + if(info->HorizontalResolution >= (unsigned int)reqwidth && + info->VerticalResolution >= (unsigned int)reqheight && + (selectedMode==9999||(info->HorizontalResolutionVerticalResolution < sh))) { + selectedMode = i; + sw = info->HorizontalResolution; + sh = info->VerticalResolution; + } +#if GOP_DEBUG + valid=1; +#endif + } +#if GOP_DEBUG + DBG(L" %c%2d %4d x %4d, %d%c ", i==selectedMode?'+':(i==nativeMode?'-':' '), + i, info->HorizontalResolution, info->VerticalResolution, info->PixelFormat,valid?' ':'?'); + DBG(L"r:%x g:%x b:%x\n", + info->PixelFormat==PixelRedGreenBlueReserved8BitPerColor?0xff:( + info->PixelFormat==PixelBlueGreenRedReserved8BitPerColor?0xff0000:( + info->PixelFormat==PixelBitMask?info->PixelInformation.RedMask:0)), + info->PixelFormat==PixelRedGreenBlueReserved8BitPerColor || + info->PixelFormat==PixelBlueGreenRedReserved8BitPerColor?0xff00:( + info->PixelFormat==PixelBitMask?info->PixelInformation.GreenMask:0), + info->PixelFormat==PixelRedGreenBlueReserved8BitPerColor?0xff0000:( + info->PixelFormat==PixelBlueGreenRedReserved8BitPerColor?0xff:( + info->PixelFormat==PixelBitMask?info->PixelInformation.BlueMask:0))); +#endif + } + // if we have found a new, better mode + if(selectedMode != 9999 && selectedMode != nativeMode) { + status = uefi_call_wrapper(gop->SetMode, 2, gop, selectedMode); + if(!EFI_ERROR(status)) + nativeMode = selectedMode; + } + // get framebuffer properties + bootboot->fb_ptr=(uint64_t)gop->Mode->FrameBufferBase; + bootboot->fb_size=gop->Mode->FrameBufferSize; + bootboot->fb_scanline=4*gop->Mode->Info->PixelsPerScanLine; + bootboot->fb_width=gop->Mode->Info->HorizontalResolution; + bootboot->fb_height=gop->Mode->Info->VerticalResolution; + bootboot->fb_type= + gop->Mode->Info->PixelFormat==PixelBlueGreenRedReserved8BitPerColor || + (gop->Mode->Info->PixelFormat==PixelBitMask && gop->Mode->Info->PixelInformation.BlueMask==0)? FB_ARGB : ( + gop->Mode->Info->PixelFormat==PixelRedGreenBlueReserved8BitPerColor || + (gop->Mode->Info->PixelFormat==PixelBitMask && gop->Mode->Info->PixelInformation.RedMask==0)? FB_ABGR : ( + gop->Mode->Info->PixelInformation.BlueMask==0xFF00? FB_RGBA : FB_BGRA + )); + DBG(L" * Screen %d x %d, scanline %d, fb @%lx %d bytes, type %d %s\n", + bootboot->fb_width, bootboot->fb_height, bootboot->fb_scanline, + bootboot->fb_ptr, bootboot->fb_size, gop->Mode->Info->PixelFormat, + bootboot->fb_type==FB_ARGB?L"ARGB":(bootboot->fb_type==FB_ABGR?L"ABGR":( + bootboot->fb_type==FB_RGBA?L"RGBA":L"BGRA"))); + return EFI_SUCCESS; +} + +/** + * Load a file from FS0 into memory + */ +EFI_STATUS +LoadFile(IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength) +{ + EFI_STATUS status; + EFI_FILE_HANDLE FileHandle; + EFI_FILE_INFO *FileInfo; + UINT64 ReadSize; + UINTN BufferSize; + UINT8 *Buffer = NULL; + + if ((RootDir == NULL) || (FileName == NULL)) { + return report(EFI_NOT_FOUND,L"Empty Root or FileName\n"); + } + + status = uefi_call_wrapper(RootDir->Open, 5, RootDir, &FileHandle, FileName, + EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); + if (EFI_ERROR(status)) { + return status; +// Print(L"%s not found\n",FileName); +// return report(status,L"Open error"); + } + FileInfo = LibFileInfo(FileHandle); + if (FileInfo == NULL) { + uefi_call_wrapper(FileHandle->Close, 1, FileHandle); + Print(L"%s not found\n",FileName); + return report(EFI_NOT_FOUND,L"FileInfo error"); + } + ReadSize = FileInfo->FileSize; + if (ReadSize > 16*1024*1024) + ReadSize = 16*1024*1024; + FreePool(FileInfo); + + BufferSize = (UINTN)((ReadSize+PAGESIZE-1)/PAGESIZE); + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, BufferSize, (EFI_PHYSICAL_ADDRESS*)&Buffer); + if (EFI_ERROR(status) || Buffer == NULL) { + uefi_call_wrapper(FileHandle->Close, 1, FileHandle); + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + status = uefi_call_wrapper(FileHandle->Read, 3, FileHandle, &ReadSize, Buffer); + uefi_call_wrapper(FileHandle->Close, 1, FileHandle); + if (EFI_ERROR(status)) { + uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)(Buffer), BufferSize); + Print(L"%s not found\n",FileName); + return report(status,L"Read error"); + } + + *FileData = Buffer; + *FileDataLength = ReadSize; + return EFI_SUCCESS; +} + +/** + * Locate and load the kernel in initrd + */ +EFI_STATUS +LoadCore() +{ + EFI_STATUS status; + int i=0,bss=0; + UINT8 *ptr; + core.ptr=ptr=NULL; + while(core.ptr==NULL && fsdrivers[i]!=NULL) { + core=(*fsdrivers[i++])((unsigned char*)initrd.ptr,kernelname); + } + // if every driver failed, try brute force, scan for the first elf or pe executable + if(core.ptr==NULL) { + DBG(L" * Autodetecting kernel%s\n",L""); + i=initrd.size; + ptr=initrd.ptr; + while(i-->0) { + Elf64_Ehdr *ehdr=(Elf64_Ehdr *)(ptr); + pe_hdr *pehdr=(pe_hdr*)(ptr + ((mz_hdr*)(ptr))->peaddr); + if((!CompareMem(ehdr->e_ident,ELFMAG,SELFMAG)||!CompareMem(ehdr->e_ident,"OS/Z",4))&& + ehdr->e_ident[EI_CLASS]==ELFCLASS64&& + ehdr->e_ident[EI_DATA]==ELFDATA2LSB&& + ehdr->e_machine==EM_X86_64&& + ehdr->e_phnum>0){ + core.ptr=ptr; + break; + } + if(((mz_hdr*)(ptr))->magic==MZ_MAGIC && ((mz_hdr*)(ptr))->peaddr<65536 && pehdr->magic == PE_MAGIC && + pehdr->machine == IMAGE_FILE_MACHINE_AMD64 && pehdr->file_type == PE_OPT_MAGIC_PE32PLUS) { + core.ptr=ptr; + break; + } + ptr++; + } + } + + if(core.ptr!=NULL) { + Elf64_Ehdr *ehdr=(Elf64_Ehdr *)(core.ptr); + pe_hdr *pehdr=(pe_hdr*)(core.ptr + ((mz_hdr*)(core.ptr))->peaddr); + if((!CompareMem(ehdr->e_ident,ELFMAG,SELFMAG)||!CompareMem(ehdr->e_ident,"OS/Z",4))&& + ehdr->e_ident[EI_CLASS]==ELFCLASS64&&ehdr->e_ident[EI_DATA]==ELFDATA2LSB&& + ehdr->e_machine==EM_X86_64&&ehdr->e_phnum>0){ + // Parse ELF64 + DBG(L" * Parsing ELF64 @%lx\n",core.ptr); + Elf64_Phdr *phdr=(Elf64_Phdr *)((UINT8 *)ehdr+ehdr->e_phoff); + for(i=0;ie_phnum;i++){ + if(phdr->p_type==PT_LOAD && (phdr->p_vaddr >> 30) == 0x3FFFFFFFF) { + // hack to keep symtab and strtab for shared libraries + core.size = phdr->p_filesz + (ehdr->e_type==3?0x4000:0); + ptr = (UINT8*)ehdr + phdr->p_offset; + bss = phdr->p_memsz - core.size; + core_addr = phdr->p_vaddr; + entrypoint = ehdr->e_entry; + break; + } + phdr=(Elf64_Phdr *)((UINT8 *)phdr+ehdr->e_phentsize); + } + if(ehdr->e_shoff > 0) { + Elf64_Shdr *shdr=(Elf64_Shdr *)((UINT8 *)ehdr + ehdr->e_shoff), *sym_sh = NULL, *str_sh = NULL; + Elf64_Shdr *strt=(Elf64_Shdr *)((UINT8 *)shdr+(UINT64)ehdr->e_shstrndx*(UINT64)ehdr->e_shentsize); + Elf64_Sym *sym = NULL, *s; + char *strtable = (char *)ehdr + strt->sh_offset; + UINT32 strsz = 0, syment = 0; + for(i = 0; i < ehdr->e_shnum; i++){ + /* checking shdr->sh_type is not enough, there can be multiple SHT_STRTAB records... */ + if(!CompareMem(strtable + shdr->sh_name, ".symtab", 8)) sym_sh = shdr; + if(!CompareMem(strtable + shdr->sh_name, ".strtab", 8)) str_sh = shdr; + shdr = (Elf64_Shdr *)((UINT8 *)shdr + ehdr->e_shentsize); + } + if(str_sh && sym_sh) { + strtable = (char *)ehdr + str_sh->sh_offset; strsz = str_sh->sh_size; + sym = (Elf64_Sym *)((UINT8*)ehdr + sym_sh->sh_offset); syment = sym_sh->sh_entsize; + if(str_sh->sh_offset && strsz > 0 && sym_sh->sh_offset && syment > 0) + for(s = sym, i = 0; i<(strtable-(char*)sym)/syment && s->st_name < strsz; i++, s++) { + if(!CompareMem(strtable + s->st_name, "bootboot", 9)) bb_addr = s->st_value; + if(!CompareMem(strtable + s->st_name, "environment", 12)) env_addr = s->st_value; + if(!CompareMem(strtable + s->st_name, "fb", 3)) fb_addr = s->st_value; + if(!CompareMem(strtable + s->st_name, "initstack", 10)) initstack = s->st_value; + } + } + } + } else if(((mz_hdr*)(core.ptr))->magic==MZ_MAGIC && ((mz_hdr*)(core.ptr))->peaddr<65536 && pehdr->magic == PE_MAGIC && + pehdr->machine == IMAGE_FILE_MACHINE_AMD64 && pehdr->file_type == PE_OPT_MAGIC_PE32PLUS && + (pehdr->code_base & 0xC0000000)) { + // Parse PE32+ + DBG(L" * Parsing PE32+ @%lx\n",core.ptr); + core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size; + ptr = core.ptr; + bss = pehdr->bss_size; + core_addr = (INT64)pehdr->code_base; + entrypoint = (INT64)pehdr->entry_point; + if(pehdr->sym_table > 0 && pehdr->numsym > 0) { + pe_sym *s; + char *strtable = (char *)pehdr + pehdr->sym_table + pehdr->numsym * 18 + 4, *name; + for(i = 0; i < pehdr->numsym; i++) { + s = (pe_sym*)((UINT8 *)pehdr + pehdr->sym_table + i * 18); + name = !s->iszero ? (char*)&s->iszero : strtable + s->nameoffs; + if(!CompareMem(name, "bootboot", 9)) bb_addr = (INT64)s->value; + if(!CompareMem(name, "environment", 12)) env_addr = (INT64)s->value; + if(!CompareMem(name, "fb", 3)) fb_addr = (INT64)s->value; + if(!CompareMem(name, "initstack", 10)) initstack = (INT64)s->value; + i += s->auxsyms; + } + } + } + if(ptr==NULL || core.size<2 || entrypoint==0 || (core_addr&(PAGESIZE-1)) || (bb_addr>>30)!=0x3FFFFFFFF || + (bb_addr & (PAGESIZE-1)) || (env_addr>>30)!=0x3FFFFFFFF || (env_addr&(PAGESIZE-1)) || (fb_addr>>30)!=0x3FFFFFFFF || + (fb_addr&(1024*1024*2-1))) + return report(EFI_LOAD_ERROR,L"Kernel is not a valid executable"); + if(core.size+bss > 16*1024*1024) + return report(EFI_LOAD_ERROR,L"Kernel is too big"); + if(initstack < 1024) initstack = 1024; + if(initstack > 16384) initstack = 16384; + // create core segment + core.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, + (core.size + bss + PAGESIZE-1)/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&core.ptr); + if (EFI_ERROR(status) || core.ptr == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + CopyMem((void*)core.ptr,ptr,core.size); + if(bss>0) + ZeroMem((UINT8*)core.ptr + core.size, bss); + core.size += bss; + DBG(L" * fb @%lx\n", fb_addr); + DBG(L" * bootboot @%lx\n", bb_addr); + DBG(L" * environment @%lx\n", env_addr); + DBG(L" * Entry point @%lx, text @%lx %d bytes\n",entrypoint, core.ptr, core.size); + if(initstack != 1024) { + DBG(L" * Stack size %ld bytes per core\n", initstack); + } + core.size = ((core.size+PAGESIZE-1)/PAGESIZE)*PAGESIZE; + return EFI_SUCCESS; + + } + return report(EFI_LOAD_ERROR,L"Kernel not found in initrd"); +} + +/** + * Initialize logical cores + * Because Local APIC ID is not contiguous, core id != core num + */ +VOID EFIAPI bootboot_startcore(IN VOID* buf) +{ +#if USE_MP_SERVICES + // we have a scalar number, not a pointer, so cast it + register UINTN core_num = (UINTN)buf; +#else + (void)buf; + register UINT16 core_num = 0; + if(lapic_addr) { + // enable Local APIC + *((volatile uint32_t*)(lapic_addr + 0x0F0)) = *((volatile uint32_t*)(lapic_addr + 0x0F0)) | 0x100; + core_num = lapic_ids[*((volatile uint32_t*)(lapic_addr + 0x20)) >> 24]; + } +#endif + ap_done = 1; + + // spinlock until BSP finishes (or forever if we got an invalid lapicid, should never happen) + do { __asm__ __volatile__ ("pause" : : : "memory"); } while(!bsp_done && core_num != 0xFFFF); + + // enable SSE + __asm__ __volatile__ ( + "movl $0xC0000011, %%eax;" + "movq %%rax, %%cr0;" + "movq %%cr4, %%rax;" + "orw $3 << 8, %%ax;" + "mov %%rax, %%cr4" + : ); + + // set up paging + __asm__ __volatile__ ( + "mov %0, %%rax;" + "mov %%rax, %%cr3" + : : "b"(paging) : "memory" ); + + // set stack and call _start() in sys/core + __asm__ __volatile__ ( + // get a valid stack for the core we're running on + "xorq %%rsp, %%rsp;" + "subq %0, %%rsp;" // sp = core_num * -initstack + // pass control over + "pushq %1;" + "movq %2, %%rdi;" + "retq" + : : "a"((UINTN)core_num*initstack), "b"(entrypoint), "c"((UINTN)core_num) : "memory" ); +} + +/** + * Main EFI application entry point + */ +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_LOADED_IMAGE *loaded_image = NULL; + EFI_GUID lipGuid = LOADED_IMAGE_PROTOCOL; + EFI_GUID RomTableGuid = EFI_PCI_OPTION_ROM_TABLE_GUID; + EFI_PCI_OPTION_ROM_TABLE *RomTable; + EFI_GUID bioGuid = BLOCK_IO_PROTOCOL; + EFI_BLOCK_IO *bio; + EFI_HANDLE *handles = NULL; + EFI_STATUS status=EFI_SUCCESS; + EFI_MEMORY_DESCRIPTOR *memory_map = NULL, *mement; + EFI_PARTITION_TABLE_HEADER *gptHdr; + EFI_PARTITION_ENTRY *gptEnt; + EFI_INPUT_KEY key; +#if USE_MP_SERVICES + EFI_EVENT Event; + EFI_GUID mpspGuid = EFI_MP_SERVICES_PROTOCOL_GUID; + EFI_MP_SERVICES_PROTOCOL *mp = NULL; + UINT8 pibuffer[100]; + EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer; +#else + UINT64 ncycles = 0, currtime, endtime; + UINTN bad_madt=0; +#endif + EFI_GUID SerIoGuid = EFI_SERIAL_IO_PROTOCOL_GUID; + EFI_SERIAL_IO_PROTOCOL *ser = NULL; + UINTN bsp_num=0, i, j=0, x,y, handle_size=0,memory_map_size=0, map_key=0, desc_size=0; + UINT32 desc_version=0, a, b; + UINT64 lba_s=0,lba_e=0,sysptr; + MMapEnt *mmapent, *last=NULL, *sort; + file_t ret={NULL,0}; + CHAR16 **argv, *initrdfile, *configfile, *help= + L"SYNOPSIS\n BOOTBOOT.EFI [ -h | -? | /h | /? | -s ] [ INITRDFILE [ ENVIRONFILE [...] ] ]\n\nDESCRIPTION\n Bootstraps an operating system via the BOOTBOOT Protocol.\n If arguments not given, defaults to\n FS0:\\BOOTBOOT\\INITRD as ramdisk image and\n FS0:\\BOOTBOOT\\CONFIG for boot environment.\n Additional \"key=value\" command line arguments will be appended to the\n environment. If INITRD not found, it will use the first bootable partition\n in GPT. If CONFIG not found, it will look for /sys/config inside the\n INITRD (or partition). With -s it will scan the memory for an initrd ROM.\n\n As this is a loader, it is not supposed to return control to the shell.\n\n"; + INTN argc, scanmemory=0; + + // Initialize UEFI Library + InitializeLib(image, systab); + BS = systab->BootServices; + CI = systab->ConIn; + + // Parse command line arguments + // BOOTBOOT.EFI [-?|-h|/?|/h] [initrd [config [key=value...]] + argc = GetShellArgcArgv(image, &argv); + if(argc>1) { + if((argv[1][0]=='-'||argv[1][0]=='/')&&(argv[1][1]=='?'||argv[1][1]=='h')){ + Print(L"BOOTBOOT LOADER (build %s)\n\n%s",a2u(__DATE__),help); + return EFI_SUCCESS; + } + if(argv[1][0]=='-'||argv[1][0]=='s') { + argc--; argv++; scanmemory = 1; + } + } + if(argc>1) { + initrdfile=argv[1]; + } else { + initrdfile=L"\\BOOTBOOT\\INITRD"; + } + if(argc>2) { + configfile=argv[2]; + } else { + configfile=L"\\BOOTBOOT\\CONFIG"; + } + + Print(L"Booting OS...\n"); + + // get memory for bootboot structure + bootboot = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 1, (EFI_PHYSICAL_ADDRESS*)&bootboot); + if (EFI_ERROR(status) || bootboot == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + ZeroMem((void*)bootboot,PAGESIZE); + CopyMem(bootboot->magic,BOOTBOOT_MAGIC,4); + // unlike BIOS+MultiBoot bootboot, no need to check if we have + // PAE + MSR + LME, as we're already in long mode. + __asm__ __volatile__ ( + "mov $1, %%eax;" + "cpuid;" + "shrl $24, %%ebx;" + "mov %%bx,%0" + : "=b"(bootboot->bspid) : : ); +#if !defined(USE_MP_SERVICES) || !USE_MP_SERVICES + // should be no need to check for RDSTC, available since Pentium, therefore + // all long mode capable CPUs should have it. But just to be on the safe side + __asm__ __volatile__ ("mov $1, %%eax; cpuid;" : "=d"(a) : : ); + if(a & (1<<4)) { + // calibrate CPU clock cycles + __asm__ __volatile__ ( "rdtsc" : "=a"(a),"=d"(b)); currtime=((UINT64)b << 32)|a; + uefi_call_wrapper(BS->Stall, 1, 1); + __asm__ __volatile__ ( "rdtsc" : "=a"(a),"=d"(b)); ncycles=((UINT64)b << 32)|a; + ncycles -= currtime; + ncycles /= 5; + if(ncycles < 1) ncycles = 1; + } else { + // fallback to dummy loops without RDTSC (should never happen) + ncycles = 0; + } +#define sleep(n) do { \ + if(ncycles) { \ + __asm__ __volatile__ ( "rdtsc" : "=a"(a),"=d"(b)); endtime=(((UINT64)b << 32)|a) + n*ncycles; \ + do { \ + __asm__ __volatile__ ( "rdtsc" : "=a"(a),"=d"(b)); currtime=((UINT64)b << 32)|a; \ + } while(currtime < endtime); \ + } else \ + __asm__ __volatile__ ("1: pause; dec %%ecx; or %%ecx, %%ecx; jnz 1b" : : "c"(n*1000) : "memory"); \ + } while(0) +#define send_ipi(a,m,v) do { \ + while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12)) __asm__ __volatile__ ("pause" : : : "memory"); \ + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (a << 24); \ + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & m) | v; \ +} while(0) +#endif + + // locate InitRD in ROM + DBG(L" * Locate initrd in Option ROMs%s\n",L""); + RomTable = NULL; initrd.ptr = NULL; initrd.size = 0; + status=EFI_LOAD_ERROR; + // first, try RomTable + LibGetSystemConfigurationTable(&RomTableGuid,(void *)&(RomTable)); + if(RomTable!=NULL) { + for (i=0;iPciOptionRomCount;i++) { + ret.ptr=(UINT8*)RomTable->PciOptionRomDescriptors[i].RomAddress; + if(ret.ptr[0]==0x55 && ret.ptr[1]==0xAA && !CompareMem(ret.ptr+8,(const CHAR8 *)"INITRD",6)) { + CopyMem(&initrd.size,ret.ptr+16,4); + initrd.ptr=ret.ptr+32; + status=EFI_SUCCESS; + break; + } + } + } + //if not found, scan memory + if(scanmemory && (EFI_ERROR(status) || initrd.ptr==NULL)){ + status = uefi_call_wrapper(BS->GetMemoryMap, 5, + &memory_map_size, memory_map, NULL, &desc_size, NULL); + if (status!=EFI_BUFFER_TOO_SMALL || memory_map_size==0) { + return report(EFI_OUT_OF_RESOURCES,L"GetMemoryMap getSize"); + } + memory_map_size+=2*desc_size; + memory_map = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, + (memory_map_size+PAGESIZE-1)/PAGESIZE, + (EFI_PHYSICAL_ADDRESS*)&memory_map); + if (EFI_ERROR(status) || memory_map == NULL) { + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + status = uefi_call_wrapper(BS->GetMemoryMap, 5, + &memory_map_size, memory_map, &map_key, &desc_size, &desc_version); + status=EFI_LOAD_ERROR; + for(mement=memory_map; + mementPhysicalStart==0 && mement->NumberOfPages==0)) + break; + // skip free and ACPI memory + if(mement->Type==7||(mement->Type>=9&&mement->Type<=13)) + continue; + // according to spec, EFI Option ROMs must start on 512 bytes boundary, not 2048 + for(ret.ptr=(UINT8*)mement->PhysicalStart; + ret.ptr+512<(UINT8*)mement->PhysicalStart+mement->NumberOfPages*PAGESIZE; + ret.ptr+=512) { + if(ret.ptr[0]==0x55 && ret.ptr[1]==0xAA && !CompareMem(ret.ptr+8,(const CHAR8 *)"INITRD",6)) { + CopyMem(&initrd.size,ret.ptr+16,4); + initrd.ptr=ret.ptr+32; + status=EFI_SUCCESS; + goto foundinrom; + } + } + } +foundinrom: + uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)memory_map, (memory_map_size+PAGESIZE-1)/PAGESIZE); + } + // try reading the initrd from serial line + if(EFI_ERROR(status) || initrd.ptr==NULL){ + status = uefi_call_wrapper(BS->LocateProtocol, 3, &SerIoGuid, NULL, (void**)&ser); + if(!EFI_ERROR(status) && ser) { + // 1000 microsec timeout, mode 115200,8,n,1 + status = uefi_call_wrapper(ser->SetAttributes, 7, ser, 115200, 0, 1000, NoParity, 8, OneStopBit); + if(!EFI_ERROR(status)) { + i = 3; + uefi_call_wrapper(ser->Write, 3, ser, &i, "\003\003\003"); + i = 4; initrd.size = 0; + status = uefi_call_wrapper(ser->Read, 3, ser, &i, (VOID*)&initrd.size); + if(!EFI_ERROR(status) && i == 4) { + i = 2; + if(initrd.size < 32 || initrd.size >= INITRD_MAXSIZE*1024*1024) { + uefi_call_wrapper(ser->Write, 3, ser, &i, "SE"); + initrd.size = 0; + status = EFI_LOAD_ERROR; + } else { + initrd.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (initrd.size+PAGESIZE-1)/PAGESIZE, + (EFI_PHYSICAL_ADDRESS*)&initrd.ptr); + if (EFI_ERROR(status) || initrd.ptr == NULL) { + uefi_call_wrapper(ser->Write, 3, ser, &i, "SE"); + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + uefi_call_wrapper(ser->Write, 3, ser, &i, "OK"); + i = initrd.size; + status = uefi_call_wrapper(ser->Read, 3, ser, &i, (VOID*)initrd.ptr); + if(EFI_ERROR(status) || i != initrd.size) { + uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)initrd.ptr, + (initrd.size+PAGESIZE-1)/PAGESIZE); + initrd.ptr = NULL; + initrd.size = 0; + status = EFI_LOAD_ERROR; + } + } + } + } + } + } + // fall back to INITRD on filesystem + if(EFI_ERROR(status) || initrd.ptr==NULL){ + // if the user presses any key now, we fallback to backup initrd + for(i=0;i<500;i++) { + if(!uefi_call_wrapper(BS->CheckEvent, 1, CI->WaitForKey)) { + uefi_call_wrapper(CI->ReadKeyStroke, 2, CI, &key); + Print(L" * Backup initrd\n"); + initrdfile=L"\\BOOTBOOT\\INITRD.BAK"; + break; + } + // delay 1ms + uefi_call_wrapper(BS->Stall, 1, 1000); + } + DBG(L" * Locate initrd in %s\n",initrdfile); + // Initialize FS with the DeviceHandler from loaded image protocol + status = uefi_call_wrapper(BS->HandleProtocol, + 3, + image, + &lipGuid, + (void **) &loaded_image); + if (!EFI_ERROR(status) && loaded_image!=NULL) { + status=EFI_LOAD_ERROR; + RootDir = LibOpenRoot(loaded_image->DeviceHandle); + // load ramdisk + status=LoadFile(initrdfile,&initrd.ptr, &initrd.size); + } + } + // if not found, try architecture specific initrd file + if(EFI_ERROR(status) || initrd.ptr==NULL){ + initrdfile=L"\\BOOTBOOT\\X86_64"; + DBG(L" * Locate initrd in %s\n",initrdfile); + status=LoadFile(initrdfile,&initrd.ptr, &initrd.size); + } + // if even that failed, look for a partition + if(status!=EFI_SUCCESS || initrd.size==0){ + DBG(L" * Locate initrd in GPT%s\n",L""); + status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles); + if (status!=EFI_BUFFER_TOO_SMALL || handle_size==0) { + return report(EFI_OUT_OF_RESOURCES,L"LocateHandle getSize"); + } + handles = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (handle_size+PAGESIZE-1)/PAGESIZE, + (EFI_PHYSICAL_ADDRESS*)&handles); + if(EFI_ERROR(status) || handles == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages\n"); + initrd.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 1, (EFI_PHYSICAL_ADDRESS*)&initrd.ptr); + if (EFI_ERROR(status) || initrd.ptr == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + lba_s=lba_e=0; + status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles); + for(i=0;iHandleProtocol, 3, handles[i], &bioGuid, (void **) &bio); + if(status!=EFI_SUCCESS || bio==NULL || bio->Media->BlockSize==0) + continue; + status = uefi_call_wrapper(bio->ReadBlocks, 5, bio, bio->Media->MediaId, 1, PAGESIZE, initrd.ptr); + if(status!=EFI_SUCCESS || CompareMem(initrd.ptr,EFI_PTAB_HEADER_ID,8)) + continue; + gptHdr = (EFI_PARTITION_TABLE_HEADER*)initrd.ptr; + if(gptHdr->NumberOfPartitionEntries>127) gptHdr->NumberOfPartitionEntries=127; + // first, look for a partition with bootable flag + ret.ptr= (UINT8*)(initrd.ptr + (gptHdr->PartitionEntryLBA-1) * bio->Media->BlockSize); + for(j=0;jNumberOfPartitionEntries;j++) { + gptEnt=(EFI_PARTITION_ENTRY*)ret.ptr; + if((ret.ptr[0]==0 && ret.ptr[1]==0 && ret.ptr[2]==0 && ret.ptr[3]==0) || gptEnt->StartingLBA==0) + break; + // use first partition with bootable flag as INITRD + if((gptEnt->Attributes & EFI_PART_USED_BY_OS)) goto partfound; + ret.ptr+=gptHdr->SizeOfPartitionEntry; + } + // if none, look for specific partition types + ret.ptr= (UINT8*)(initrd.ptr + (gptHdr->PartitionEntryLBA-1) * bio->Media->BlockSize); + for(j=0;jNumberOfPartitionEntries;j++) { + gptEnt=(EFI_PARTITION_ENTRY*)ret.ptr; + if((ret.ptr[0]==0 && ret.ptr[1]==0 && ret.ptr[2]==0 && ret.ptr[3]==0) || gptEnt->StartingLBA==0) + break; + // use the first OS/Z root partition for this architecture + if(!CompareMem(&gptEnt->PartitionTypeGUID.Data1,"OS/Z",4) && + gptEnt->PartitionTypeGUID.Data2==0x8664 && + !CompareMem(&gptEnt->PartitionTypeGUID.Data4[4],"root",4)) { +partfound: lba_s=gptEnt->StartingLBA; lba_e=gptEnt->EndingLBA; + initrd.size = (((lba_e-lba_s)*bio->Media->BlockSize + PAGESIZE-1)/PAGESIZE)*PAGESIZE; + status=EFI_SUCCESS; + goto partok; + } + ret.ptr+=gptHdr->SizeOfPartitionEntry; + } + } + return report(EFI_LOAD_ERROR,L"No boot partition"); +partok: + uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)initrd.ptr, 1); + if(initrd.size>0 && bio!=NULL) { + initrd.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, initrd.size/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&initrd.ptr); + if (EFI_ERROR(status) || initrd.ptr == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + status = uefi_call_wrapper(bio->ReadBlocks, 5, bio, bio->Media->MediaId, lba_s, initrd.size, initrd.ptr); + } else + status=EFI_LOAD_ERROR; + } + if(status==EFI_SUCCESS && initrd.size>0){ + //check if initrd is gzipped + if(initrd.ptr[0]==0x1f && initrd.ptr[1]==0x8b){ + unsigned char *addr,f; + int len=0, r; + TINF_DATA d; + DBG(L" * Gzip compressed initrd @%lx %d bytes\n",initrd.ptr,initrd.size); + // skip gzip header + addr=initrd.ptr+2; + if(*addr++!=8) goto gzerr; + f=*addr++; addr+=6; + if(f&4) { r=*addr++; r+=(*addr++ << 8); addr+=r; } + if(f&8) { while(*addr++ != 0); } + if(f&16) { while(*addr++ != 0); } + if(f&2) addr+=2; + d.source = addr; + // allocate destination buffer + CopyMem(&len,initrd.ptr+initrd.size-4,4); + addr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (len+PAGESIZE-1)/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&addr); + if(EFI_ERROR(status) || addr == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages\n"); + // decompress + d.bitcount = 0; + d.bfinal = 0; + d.btype = -1; + d.dict_size = 0; + d.dict_ring = NULL; + d.dict_idx = 0; + d.curlen = 0; + d.dest = addr; + d.destSize = len; + do { r = uzlib_uncompress(&d); } while (!r); + if (r != TINF_DONE) { +gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress"); + } + // swap initrd.ptr with the uncompressed buffer + // if it's not page aligned, we came from ROM, no FreePages + if(((UINT64)initrd.ptr&(PAGESIZE-1))==0) + uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)initrd.ptr, (initrd.size+PAGESIZE-1)/PAGESIZE); + initrd.ptr=addr; + initrd.size=len; + } + DBG(L" * Initrd loaded @%lx %d bytes\n",initrd.ptr,initrd.size); + kne=env.ptr=NULL; + // if there's an environment file, load it + if(loaded_image!=NULL && LoadFile(configfile,&env.ptr,&env.size)!=EFI_SUCCESS) { + env.ptr=NULL; + } + if(env.ptr==NULL) { + // if there were no environment file on boot partition, find it inside the INITRD + j=0; ret.ptr=NULL; ret.size=0; + while(ret.ptr==NULL && fsdrivers[j]!=NULL) { + ret=(*fsdrivers[j++])((unsigned char*)initrd.ptr,cfgname); + } + if(ret.ptr!=NULL) { + if(ret.size>PAGESIZE-1) + ret.size=PAGESIZE-1; + env.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 1, (EFI_PHYSICAL_ADDRESS*)&env.ptr); + if(EFI_ERROR(status) || env.ptr == NULL) + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + ZeroMem((void*)env.ptr,PAGESIZE); + CopyMem((void*)env.ptr,ret.ptr,ret.size); + env.size=ret.size; + } + } + if(env.ptr!=NULL) { + ParseEnvironment(env.ptr,env.size, argc, argv); + } else { + // provide an empty environment for the OS + env.size = 0; + env.ptr = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 1, (EFI_PHYSICAL_ADDRESS*)&env.ptr); + if (EFI_ERROR(status) || env.ptr == NULL) { + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + ZeroMem((void*)env.ptr,PAGESIZE); + CopyMem((void*)env.ptr,"// N/A",8); + } + + // get linear frame buffer + status = GetLFB(); + if (EFI_ERROR(status) || bootboot->fb_width==0 || bootboot->fb_ptr==0) + return report(status, L"GOP failed, no framebuffer"); + + // collect information on system + bootboot->protocol=PROTOCOL_DYNAMIC | LOADER_UEFI; + bootboot->size=128; + CopyMem((void *)&(bootboot->initrd_ptr),&initrd.ptr,8); + bootboot->initrd_size=((initrd.size+PAGESIZE-1)/PAGESIZE)*PAGESIZE; + CopyMem((void *)&(bootboot->arch.x86_64.efi_ptr),&systab,8); + + // System tables and structures + DBG(L" * System tables%s\n",L""); + sysptr = 0; LibGetSystemConfigurationTable(&AcpiTableGuid,(void *)&sysptr); bootboot->arch.x86_64.acpi_ptr = sysptr; + sysptr = 0; LibGetSystemConfigurationTable(&SMBIOSTableGuid,(void *)&sysptr); bootboot->arch.x86_64.smbi_ptr = sysptr; + sysptr = 0; LibGetSystemConfigurationTable(&MpsTableGuid,(void *)&sysptr); bootboot->arch.x86_64.mp_ptr = sysptr; + + // FIX ACPI table pointer on TianoCore... + ret.ptr = (UINT8*)(bootboot->arch.x86_64.acpi_ptr); + if(CompareMem(ret.ptr,(const CHAR8 *)"RSDT", 4) && CompareMem(ret.ptr,(const CHAR8 *)"XSDT", 4)) { + // scan for the real rsd ptr, as AcpiTableGuid returns bad address + for(i=1;i<256;i++) { + if(!CompareMem(ret.ptr+i, (const CHAR8 *)"RSD PTR ", 8)){ + ret.ptr+=i; + break; + } + } + // get ACPI system table + ACPI_RSDPTR *rsd = (ACPI_RSDPTR*)ret.ptr; + if(rsd->xsdt!=0) + bootboot->arch.x86_64.acpi_ptr = rsd->xsdt; + else + bootboot->arch.x86_64.acpi_ptr = (UINT64)((UINT32)rsd->rsdt); + } + + // Date and time + EFI_TIME t; + uefi_call_wrapper(ST->RuntimeServices->GetTime, 2, &t, NULL); + bootboot->datetime[0]=DecimaltoBCD(t.Year/100); + bootboot->datetime[1]=DecimaltoBCD(t.Year%100); + bootboot->datetime[2]=DecimaltoBCD(t.Month); + bootboot->datetime[3]=DecimaltoBCD(t.Day); + bootboot->datetime[4]=DecimaltoBCD(t.Hour); + bootboot->datetime[5]=DecimaltoBCD(t.Minute); + bootboot->datetime[6]=DecimaltoBCD(t.Second); + bootboot->datetime[7]=DecimaltoBCD(t.Daylight); + CopyMem((void *)&bootboot->timezone, &t.TimeZone, 2); + if(bootboot->timezone<-1440||bootboot->timezone>1440) // TZ in mins + bootboot->timezone=0; + DBG(L" * System time %d-%02d-%02d %02d:%02d:%02d GMT%s%d:%02d %s\n", + t.Year,t.Month,t.Day,t.Hour,t.Minute,t.Second, + bootboot->timezone>=0?L"+":L"",bootboot->timezone/60,bootboot->timezone%60, + t.Daylight?L"summertime":L""); + // get sys/core and parse + status=LoadCore(); + if (EFI_ERROR(status)) + return status; + if(kne!=NULL) + *kne='\n'; + + // Symmetric Multi Processing support +#if USE_MP_SERVICES + status = uefi_call_wrapper(BS->LocateProtocol, 3, &mpspGuid, NULL, (void**)&mp); + if(!nosmp && !EFI_ERROR(status) && mp) { + // override default values in bootboot struct + status = uefi_call_wrapper(mp->GetNumberOfProcessors, 3, mp, &i, &j); + if(!EFI_ERROR(status)) { + // failsafe: we cannot map more stacks (each core has 1k) + if(i>PAGESIZE/8/2*4) i=PAGESIZE/8/2*4; + if(i<1) i = 1; + bootboot->numcores = i; + } + DBG(L" * SMP numcores %d\n", bootboot->numcores); + // start APs + status = uefi_call_wrapper(BS->CreateEvent, 5, 0, TPL_NOTIFY, NULL, NULL, &Event); + if(!EFI_ERROR(status)) { + for(i=0; inumcores; i++) { + status = uefi_call_wrapper(mp->GetProcessorInfo, 5, mp, i, pibuf); + if(!EFI_ERROR(status)) { + if(pibuf->StatusFlag & PROCESSOR_AS_BSP_BIT) { + bootboot->bspid = pibuf->ProcessorId; + bsp_num = i; + } else { + uefi_call_wrapper(mp->StartupThisAP, 7, mp, bootboot_startcore, i, Event, 0, (VOID*)i, NULL); + } + } + } + } + } else + bootboot->numcores = 1; +#else + UINT8 *ptr = (UINT8*)bootboot->arch.x86_64.acpi_ptr, *pe, *data; + UINT64 r; + for(i = 0; i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); i++) lapic_ids[i] = 0xFFFF; + if(!nosmp && ptr && (ptr[0]=='X' || ptr[0]=='R') && ptr[1]=='S' && ptr[2]=='D' && ptr[3]=='T') { + pe = ptr; ptr += 36; + // iterate on ACPI table pointers + for(r = *((uint32_t*)(pe + 4)); ptr < pe + r; ptr += pe[0] == 'X' ? 8 : 4) { + data = (uint8_t*)(uintptr_t)(pe[0] == 'X' ? *((uint64_t*)ptr) : *((uint32_t*)ptr)); + if(!CompareMem(data, "APIC", 4)) { + // found MADT, iterate on its variable length entries + lapic_addr = (uint64_t)(*((uint32_t*)(data+0x24))); + for(r = *((uint32_t*)(data + 4)), ptr = data + 44, i = 0; ptr < data + r && + i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); ptr += ptr[1]) { + switch(ptr[0]) { + case 0: // found Processor Local APIC + if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(INTN)ptr[3]] == 0xFFFF) + lapic_ids[(INTN)ptr[3]] = i++; + else bad_madt++; + break; + case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address + } + } + if(i) { + bsp_num = lapic_ids[bootboot->bspid]; + if(bsp_num == 0xFFFF) bsp_num = 0; + else { + bootboot->numcores = i; + DBG(L" * SMP numcores %d%s\n", bootboot->numcores, bad_madt ? L" (bad MADT)" : L""); + } + } + break; + } + } + } + if(nosmp || bootboot->numcores < 2 || !lapic_addr) { + bootboot->numcores = 1; + lapic_addr = 0; + } +#endif + + // query size of memory map + status = uefi_call_wrapper(BS->GetMemoryMap, 5, + &memory_map_size, memory_map, NULL, &desc_size, NULL); + if (status!=EFI_BUFFER_TOO_SMALL || memory_map_size==0) { + return report(EFI_OUT_OF_RESOURCES,L"GetMemoryMap getSize"); + } + // allocate memory for memory descriptors. We assume that one or two new memory + // descriptor may be created by our next allocate calls and we round up to page size + memory_map_size+=16*desc_size; + memory_map = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, + (memory_map_size+PAGESIZE-1)/PAGESIZE, + (EFI_PHYSICAL_ADDRESS*)&memory_map); + if (EFI_ERROR(status) || memory_map == NULL) { + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + + // create page tables + paging = NULL; + status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 37+ + (bootboot->numcores*initstack+PAGESIZE-1)/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&paging); + if (EFI_ERROR(status) || paging == NULL) { + return report(EFI_OUT_OF_RESOURCES,L"AllocatePages"); + } + ZeroMem((void*)paging,(37+(bootboot->numcores*initstack+PAGESIZE-1)/PAGESIZE)*PAGESIZE); + DBG(L" * Pagetables PML4 @%lx\n",paging); + //PML4 + paging[0]=(UINT64)((UINT8 *)paging+PAGESIZE)+3; // pointer to 2M PDPE (16G RAM identity mapped) + paging[511]=(UINT64)((UINT8 *)paging+20*PAGESIZE)+3; // pointer to 4k PDPE (core mapped at -2M) + //identity mapping + //2M PDPE + for(i=0;i<16;i++) + paging[512+i]=(UINT64)((UINT8 *)paging+(3+i)*PAGESIZE+3); + //first 2M mapped per page + paging[3*512]=(UINT64)((UINT8 *)paging+2*PAGESIZE+3); + for(i=0;i<512;i++) + paging[2*512+i]=(UINT64)(i*PAGESIZE+3); + //2M PDE + for(i=1;i<512*16;i++) + paging[3*512+i]=(UINT64)((i<<21)+0x83); + //kernel mapping + //4k PDPE + paging[20*512+511]=(UINT64)((UINT8 *)paging+22*PAGESIZE+3); + //4k PDE + j = (fb_addr>>(9+12)) & 0x1FF; + for(i=0;j+i<511 && i<63;i++) + paging[22*512+j+i]=(UINT64)((bootboot->fb_ptr+(i<<21))+0x83); // map framebuffer + paging[22*512+511]=(UINT64)((UINT8 *)paging+23*PAGESIZE+3); + //4k PT + //dynamically map these. Main struct, environment string and code segment + for(i=0;i<(core.size/PAGESIZE);i++) + MapPage(core_addr + i*PAGESIZE, (UINT64)((UINT8 *)core.ptr+i*PAGESIZE+3)); + MapPage(bb_addr, (UINT64)(bootboot)+1); + MapPage(env_addr, (UINT64)(env.ptr)+1); + // stack at the top of the memory + for(i=0; i<(UINTN)((bootboot->numcores*initstack+PAGESIZE-1)/PAGESIZE); i++) { + if(paging[23*512+511-i]) + return report(EFI_OUT_OF_RESOURCES,L"Stack smash"); + paging[23*512+511-i]=(UINT64)((UINT8 *)paging+(37+i)*PAGESIZE+3); // core stacks + } + + // Get memory map + int cnt = 3, apmemfree = 0; +get_memory_map: + DBG(L" * Memory Map @%lx %d bytes try #%d\n", memory_map, memory_map_size, 4-cnt); + mmapent = (MMapEnt *)&(bootboot->mmap); + bootboot->size = 128; + status = uefi_call_wrapper(BS->GetMemoryMap, 5, + &memory_map_size, memory_map, &map_key, &desc_size, &desc_version); + if (EFI_ERROR(status)) { + return report(status,L"GetMemoryMap"); + } + last=NULL; + for(mement=memory_map; + mementsize>=PAGESIZE-128 || + (mement->PhysicalStart==0 && mement->NumberOfPages==0)) + break; + // check if the AP trampoline code's memory is free + if( mement->Type==7 && mement->PhysicalStart <= (UINT64)0x8000 && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)0x8000) + apmemfree = 1; + // failsafe, don't report our own structures as free + if( mement->NumberOfPages==0 || + ((mement->PhysicalStart <= (UINT64)bootboot && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)bootboot) || + (mement->PhysicalStart <= (UINT64)env.ptr && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)env.ptr) || + (mement->PhysicalStart <= (UINT64)initrd.ptr && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)initrd.ptr) || + (mement->PhysicalStart <= (UINT64)core.ptr && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)core.ptr) || + (mement->PhysicalStart <= (UINT64)paging && + mement->PhysicalStart+(mement->NumberOfPages*PAGESIZE) > (UINT64)paging) + )) { + continue; + } + mmapent->ptr=mement->PhysicalStart; + mmapent->size=(mement->NumberOfPages*PAGESIZE)+ + ((mement->Type>0&&mement->Type<5)||mement->Type==7?MMAP_FREE: + (mement->Type==9 || mement->Type==10 || (bootboot->arch.x86_64.acpi_ptr >= mmapent->ptr && + bootboot->arch.x86_64.acpi_ptr < mmapent->ptr+mement->NumberOfPages*PAGESIZE)?MMAP_ACPI: + (mement->Type==11||mement->Type==12?MMAP_MMIO: + MMAP_USED))); + // merge continous areas of the same type + if(last!=NULL && + MMapEnt_Type(last) == MMapEnt_Type(mmapent) && + MMapEnt_Ptr(last)+MMapEnt_Size(last) == MMapEnt_Ptr(mmapent)) { + last->size+=MMapEnt_Size(mmapent); + mmapent->ptr=mmapent->size=0; + } else { + last=mmapent; + bootboot->size+=16; + // bubble up record. It's okay to use an ineffective, but simple sort here, because there are no + // more records than a couple hundred, and in most scenearios they are already sorted, meaning this + // loop will never run at all. But in the unlikely event they aren't sorted, this will fix that. + for(sort = mmapent - 1; sort >= (MMapEnt *)&(bootboot->mmap) && sort[0].ptr > sort[1].ptr; sort--) { + lba_s = sort[0].ptr; lba_e = sort[0].size; + sort[0].ptr = sort[1].ptr; sort[0].size = sort[1].size; + sort[1].ptr = lba_s; sort[1].size = lba_e; + } + mmapent++; + } + } + // --- NO PRINT AFTER THIS POINT --- + + // blue (or red) dot on the top left corner (sort of status report) + *((volatile uint64_t*)(bootboot->fb_ptr)) = + *((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x000000FF000000FFUL; + __asm__ __volatile__ ("invlpg (%0)" : : "a"(bootboot->fb_ptr) : "memory"); // memory barrier and flush screen + + //inform firmware that we're about to leave it's realm + status = uefi_call_wrapper(BS->ExitBootServices, 2, image, map_key); + if(EFI_ERROR(status)){ + cnt--; + if(cnt>0) goto get_memory_map; + return report(status,L"ExitBootServices"); + } + + // disable PIC and NMI + __asm__ __volatile__ ( + "movb $0xFF, %%al; outb %%al, $0x21; outb %%al, $0xA1;" // disable PIC + "inb $0x70, %%al; orb $0x80, %%al; outb %%al, $0x70;" // disable NMI + : : :); + +#if !defined(USE_MP_SERVICES) || !USE_MP_SERVICES + // green dot on the top left corner (do not allow gcc to rearrange this!!!) + *((volatile uint64_t*)(bootboot->fb_ptr)) = + *((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x0000FF000000FF00UL; + __asm__ __volatile__ ("invlpg (%0)" : : "a"(bootboot->fb_ptr) : "memory"); // memory barrier and flush screen + + // start APs + if(bootboot->numcores > 1 && apmemfree) { + + // copy trampoline and save UEFI's 64 bit system registers for the trampoline code + __asm__ __volatile__ ( + "movq $32, %%rcx; movq %0, %%rsi; movq $0x8000, %%rdi; repnz movsq;" + "movq %%cr3, %%rax; movq %%rax, 0x80C0;" + "movl %%cs, %%eax; movl %%eax, 0x80CC;" + "movl %%ds, %%eax; movl %%eax, 0x80D0;" + "movq %%rbx, 0x80D8;" + "sgdt 0x80E0;" : : "d"((uint64_t)&ap_trampoline), "b"((uint64_t)&bootboot_startcore) : ); + + // enable Local APIC + *((volatile uint32_t*)(lapic_addr + 0x0D0)) = (1 << 24); + *((volatile uint32_t*)(lapic_addr + 0x0E0)) = 0xFFFFFFFF; + *((volatile uint32_t*)(lapic_addr + 0x0F0)) = *((volatile uint32_t*)(lapic_addr + 0x0F0)) | 0x1FF; + *((volatile uint32_t*)(lapic_addr + 0x080)) = 0; + // make sure we use the correct Local APIC ID for the BSP + bootboot->bspid = *((volatile uint32_t*)(lapic_addr + 0x20)) >> 24; + +#if 0 + // use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled) + if(!bad_madt) { + // send Broadcast INIT IPI + *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500; + sleep(50); // wait 10 msec + // send Broadcast STARTUP IPI + *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // start at 0800:0000h + sleep(1); // wait 200 usec + // send second SIPI + *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; + sleep(1); // wait 200 usec + } else +#endif + { + // supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more + for(i = 0; i < 255; i++) { + if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue; + *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors + a = *((volatile uint32_t*)(lapic_addr + 0x280)); + send_ipi(i, 0xfff00000, 0x00C500); // trigger INIT IPI + sleep(1); + send_ipi(i, 0xfff00000, 0x008500); // deassert INIT IPI + } + sleep(50); // wait 10 msec + for(i = 0; i < 255; i++) { + if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue; + ap_done = 0; + send_ipi(i, 0xfff0f800, 0x004608); // trigger SIPI, start at 0800:0000h + for(a = 250; !ap_done && a > 0; a--) sleep(1); // wait for AP with 50 msec timeout + if(!ap_done) { + send_ipi(i, 0xfff0f800, 0x004608); + sleep(250); + } + } + } + } + __asm__ __volatile__ ("pause" : : : "memory"); // memory barrier +#endif + + // clear the screen + for(j=y=0;yfb_height;y++) { + i=j; + for(x=0;xfb_width;x+=2,i+=8) + *((uint64_t*)(bootboot->fb_ptr + i))=0; + j+=bootboot->fb_scanline; + } + + // release AP spinlock + bsp_done = 1; + __asm__ __volatile__ ("pause" : : : "memory"); // memory barrier + bootboot_startcore((VOID*)bsp_num); + } + return report(status,L"Initrd not found"); +} + diff --git a/x86_64-efi/crt0-efi-x86_64.o b/x86_64-efi/crt0-efi-x86_64.o new file mode 100644 index 0000000..82ed97d Binary files /dev/null and b/x86_64-efi/crt0-efi-x86_64.o differ diff --git a/x86_64-efi/efirom.c b/x86_64-efi/efirom.c new file mode 100644 index 0000000..f3a65be --- /dev/null +++ b/x86_64-efi/efirom.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2009 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * modifications for gnuefi by bzt (bztsrc@gitlab) + */ + +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define eprintf(...) fprintf ( stderr, __VA_ARGS__ ) + +/** Command-line options */ +struct options { + uint16_t vendor; + uint16_t device; +}; + +/** + * Allocate memory + * + * @v len Length of memory to allocate + * @ret ptr Pointer to allocated memory + */ +static void * xmalloc ( size_t len ) { + void *ptr; + + ptr = malloc ( len ); + if ( ! ptr ) { + eprintf ( "Could not allocate %zd bytes\n", len ); + exit ( 1 ); + } + + return ptr; +} + +/** + * Get file size + * + * @v file File + * @v len File size + */ +/* +static size_t file_size ( FILE *file ) { + ssize_t len; + + return len; +} +*/ +/** + * Read information from PE headers + * + * @v pe PE file + * @ret machine Machine type + * @ret subsystem EFI subsystem + */ +static void read_pe_info ( void *pe, uint16_t *machine, + uint16_t *subsystem ) { + IMAGE_DOS_HEADER *dos; + union { + IMAGE_NT_HEADERS nt64; + } *nt; + + /* Locate NT header */ + dos = pe; + nt = ( pe + dos->e_lfanew ); + + /* issue 4: TianoCore demands subsystem 10, so we must use EFI_APPLICATION + * in the PE header. Therefore we force EFI_ROM subsystem in this code here. */ + if(nt->nt64.OptionalHeader.Subsystem == 10) + nt->nt64.OptionalHeader.Subsystem = 13; + + /* Parse out PE information */ + *machine = nt->nt64.FileHeader.Machine; + *subsystem = nt->nt64.OptionalHeader.Subsystem; +} + +/** + * Convert EFI image to ROM image + * + * @v pe EFI file + * @v rom ROM file + */ +static void make_efi_rom ( FILE *pe, FILE *rom, struct options *opts ) { + struct { + EFI_PCI_EXPANSION_ROM_HEADER rom; + PCI_DATA_STRUCTURE pci __attribute__ (( aligned ( 4 ) )); + uint8_t checksum; + } *headers; + struct stat pe_stat; + size_t pe_size; + size_t rom_size; + void *buf; + void *payload; + unsigned int i; + uint8_t checksum; + + /* Determine PE file size */ + if ( fstat ( fileno ( pe ), &pe_stat ) != 0 ) { + eprintf ( "Could not stat PE file: %s\n", + strerror ( errno ) ); + exit ( 1 ); + } + pe_size = pe_stat.st_size; + + /* Determine ROM file size */ + rom_size = ( ( pe_size + sizeof ( *headers ) + 511 ) & ~511 ); + + /* Allocate ROM buffer and read in PE file */ + buf = xmalloc ( rom_size ); + memset ( buf, 0, rom_size ); + headers = buf; + payload = ( buf + sizeof ( *headers ) ); + if ( fread ( payload, pe_size, 1, pe ) != 1 ) { + eprintf ( "Could not read PE file: %s\n", + strerror ( errno ) ); + exit ( 1 ); + } + + /* Construct ROM header */ + headers->rom.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE; + headers->rom.InitializationSize = ( rom_size / 512 ); + headers->rom.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE; + read_pe_info ( payload, &headers->rom.EfiMachineType, + &headers->rom.EfiSubsystem ); + headers->rom.EfiImageHeaderOffset = sizeof ( *headers ); + headers->rom.PcirOffset = + offsetof ( typeof ( *headers ), pci ); + headers->pci.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + headers->pci.VendorId = opts->vendor ? opts->vendor : 0x8086; + headers->pci.DeviceId = opts->device ? opts->device : 0x100E; + headers->pci.Length = sizeof ( headers->pci ); + headers->pci.ClassCode[0] = PCI_CLASS_NETWORK; + headers->pci.ImageLength = ( rom_size / 512 ); + headers->pci.CodeType = 0x03; /* No constant in EFI headers? */ + headers->pci.Indicator = 0x80; /* No constant in EFI headers? */ + + /* Fix image checksum */ + for ( i = 0, checksum = 0 ; i < rom_size ; i++ ) + checksum += *( ( uint8_t * ) buf + i ); + headers->checksum -= checksum; + + /* Write out ROM */ + if ( fwrite ( buf, rom_size, 1, rom ) != 1 ) { + eprintf ( "Could not write ROM file: %s\n", + strerror ( errno ) ); + exit ( 1 ); + } +} + +/** + * Print help + * + * @v program_name Program name + */ +static void print_help ( const char *program_name ) { + eprintf ( "Syntax: %s [--vendor=VVVV] [--device=DDDD] " + "infile outfile\n", program_name ); +} + +/** + * Parse command-line options + * + * @v argc Argument count + * @v argv Argument list + * @v opts Options structure to populate + */ +static int parse_options ( const int argc, char **argv, + struct options *opts ) { + char *end; + int c; + + while (1) { + int option_index = 0; + static struct option long_options[] = { + { "vendor", required_argument, NULL, 'v' }, + { "device", required_argument, NULL, 'd' }, + { "help", 0, NULL, 'h' }, + { 0, 0, 0, 0 } + }; + + if ( ( c = getopt_long ( argc, argv, "v:d:h", + long_options, + &option_index ) ) == -1 ) { + break; + } + + switch ( c ) { + case 'v': + opts->vendor = strtoul ( optarg, &end, 16 ); + if ( *end ) { + eprintf ( "Invalid vendor \"%s\"\n", optarg ); + exit ( 2 ); + } + break; + case 'd': + opts->device = strtoul ( optarg, &end, 16 ); + if ( *end ) { + eprintf ( "Invalid device \"%s\"\n", optarg ); + exit ( 2 ); + } + break; + case 'h': + print_help ( argv[0] ); + exit ( 0 ); + case '?': + default: + exit ( 2 ); + } + } + return optind; +} + +int main ( int argc, char **argv ) { + struct options opts = { + }; + unsigned int infile_index; + const char *infile_name; + const char *outfile_name; + FILE *infile; + FILE *outfile; + + /* Parse command-line arguments */ + infile_index = parse_options ( argc, argv, &opts ); + if ( argc != ( infile_index + 2 ) ) { + print_help ( argv[0] ); + exit ( 2 ); + } + infile_name = argv[infile_index]; + outfile_name = argv[infile_index + 1]; + + /* Open input and output files */ + infile = fopen ( infile_name, "r" ); + if ( ! infile ) { + eprintf ( "Could not open %s for reading: %s\n", + infile_name, strerror ( errno ) ); + exit ( 1 ); + } + outfile = fopen ( outfile_name, "w" ); + if ( ! outfile ) { + eprintf ( "Could not open %s for writing: %s\n", + outfile_name, strerror ( errno ) ); + exit ( 1 ); + } + + /* Convert file */ + make_efi_rom ( infile, outfile, &opts ); + + fclose ( outfile ); + fclose ( infile ); + + return 0; +} diff --git a/x86_64-efi/elf_x86_64_efi.lds b/x86_64-efi/elf_x86_64_efi.lds new file mode 100644 index 0000000..942d1f3 --- /dev/null +++ b/x86_64-efi/elf_x86_64_efi.lds @@ -0,0 +1,74 @@ +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + .reloc : + { + *(.reloc) + } + . = ALIGN(4096); + .data : + { + _data = .; + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : + { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/x86_64-efi/fs.h b/x86_64-efi/fs.h new file mode 100644 index 0000000..81e3e36 --- /dev/null +++ b/x86_64-efi/fs.h @@ -0,0 +1,356 @@ +/* + * x86_64-efi/fs.h + * + * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This file is part of the BOOTBOOT Protocol package. + * @brief Filesystem drivers for initial ramdisk. + * + */ + +/** + * FS/Z initrd (OS/Z's native file system) + */ +file_t fsz_initrd(unsigned char *initrd_p, char *kernel) +{ + file_t ret = { NULL, 0 }; + if(initrd_p==NULL || CompareMem(initrd_p + 512,"FS/Z",4) || kernel==NULL){ + return ret; + } + unsigned char passphrase[256],chk[32],iv[32]; + unsigned int i,j,k,l,ss=1<<(initrd_p[518]+11); + unsigned char *ent, *in=(initrd_p+*((uint64_t*)(initrd_p+560))*ss); + SHA256_CTX ctx; + DBG(L" * FS/Z %s\n",a2u(kernel)); + //decrypt initrd + while(*((uint32_t*)(initrd_p+520))!=0) { + Print(L" * Passphrase? "); + l=ReadLine(passphrase,sizeof(passphrase)); + if(!l) { + Print(L"\n"); + return ret; + } + if(*((uint32_t*)(initrd_p+520))!=crc32_calc((char*)passphrase,l)) { + Print(L"\rBOOTBOOT-ERROR: Bad passphrase\n"); + continue; + } + Print(L"\r * Decrypting...\r"); + SHA256_Init(&ctx); + SHA256_Update(&ctx,passphrase,l); + SHA256_Update(&ctx,initrd_p+512,6); + SHA256_Final(chk,&ctx); + for(i=0;i<32;i++) initrd_p[i+680]^=chk[i]; + SHA256_Init(&ctx); + SHA256_Update(&ctx,initrd_p+680,32); + SHA256_Final(iv,&ctx); + if(((initrd_p[519]>>4)&15)==1) { + // FSZ_SB_EALG_AESCBC + aes_init(iv); + for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));k+=ss,j++) { + aes_dec(initrd_p+k,ss); + } + } else { + // FSZ_SB_EALG_SHACBC + for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));j++) { + CopyMem(chk,iv,32); + for(i=0;i0){ + if(!CompareMem(ent + 16,s,e-s)) { + if(*e==0) { + i=*((uint64_t*)(ent+0)); + break; + } else { + s=e; + in=(initrd_p+*((uint64_t*)(ent+0))*ss); + goto again; + } + } + ent+=128; + } + } else { + i=0; + } + if(i!=0) { + // fid -> inode ptr -> data ptr + unsigned char *in=(initrd_p+i*ss); + if(!CompareMem(in,"FSIN",4)){ + ret.size=*((uint64_t*)(in+464)); + if(*((uint64_t*)(in+448)) == i) { + if(!(in[488]&31)) { + // inline data + ret.ptr=(uint8_t*)(initrd_p+i*ss+(initrd_p[520]&1? 2048 : 1024)); + } else { + // sector directory or list inlined + ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p[520]&1? in + 2048 : in + 1024))*ss); + } + } else + if(*((uint64_t*)(in+448))) { + switch((in[488]&15) + (in[488]&16 ? 1 : 0)) { + case 0: // direct data + ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(in+448)) * ss); + break; + case 1: // sector directory or list (only one level supported here, and no holes in files) + ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p + *((uint64_t*)(in+448))*ss)) * ss); + break; + } + } else ret.size=0; + } + } + return ret; +} + +/** + * Minix3 file system + * directories only checked for their first block, and kernel must be defragmented + */ +file_t mfs_initrd(unsigned char *initrd_p, char *kernel) +{ + UINT32 o, bs, ino_tbl; + UINT8 *ino, *d; + char *s = kernel, *e; + file_t ret = { NULL, 0 }; + if(initrd_p[1048] != 'Z' || initrd_p[1049] != 'M') return ret; + DBG(L" * MFS %s\n",a2u(kernel)); + bs = *((UINT16*)(initrd_p + 1052)); + ino_tbl = (2 + *((UINT16*)(initrd_p + 1030)) + *((UINT16*)(initrd_p + 1032))) * bs; + ino = initrd_p + ino_tbl; +again: + for(e = s; *e && *e != '/'; e++); + d = initrd_p + *((UINT32*)(ino + 24)) * bs; + for(o = 0; o < *((UINT32*)(ino + 8)) && o < bs; o += 64, d += 64) { + if(*((UINT32*)d) && !CompareMem(s, d + 4, e - s) && !d[e - s]) { + ino = initrd_p + ino_tbl + (*((UINT32*)d) - 1) * 64; + d = initrd_p + *((UINT32*)(ino + 24)) * bs; + if(!*e) { ret.ptr = d; ret.size = *((UINT32*)(ino + 8)); return ret; } + s = e + 1; goto again; + } + } + return ret; +} + +/** + * cpio archive + */ +file_t cpio_initrd(unsigned char *initrd_p, char *kernel) +{ + unsigned char *ptr=initrd_p; + int k; + file_t ret = { NULL, 0 }; + if(initrd_p==NULL || kernel==NULL || + (CompareMem(initrd_p,"070701",6) && CompareMem(initrd_p,"070702",6) && CompareMem(initrd_p,"070707",6))) + return ret; + DBG(L" * cpio %s\n",a2u(kernel)); + k=strlena(kernel); + // hpodc archive + while(!CompareMem(ptr,"070707",6)){ + int ns=oct2bin(ptr+8*6+11,6); + int fs=oct2bin(ptr+8*6+11+6,11); + if(!CompareMem(ptr+9*6+2*11,kernel,k+1) || + (ptr[9*6+2*11] == '.' && ptr[9*6+2*11+1] == '/' && !CompareMem(ptr+9*6+2*11+2,kernel,k+1))) { + ret.size=fs; + ret.ptr=(UINT8*)(ptr+9*6+2*11+ns); + return ret; + } + ptr+=(76+ns+fs); + } + // newc and crc archive + while(!CompareMem(ptr,"07070",5)){ + int fs=hex2bin(ptr+8*6+6,8); + int ns=hex2bin(ptr+8*11+6,8); + if(!CompareMem(ptr+110,kernel,k+1) || (ptr[110] == '.' && ptr[111] == '/' && !CompareMem(ptr+112,kernel,k+1))) { + ret.size=fs; + ret.ptr=(UINT8*)(ptr+((110+ns+3)/4)*4); + return ret; + } + ptr+=((110+ns+3)/4)*4 + ((fs+3)/4)*4; + } + return ret; +} + +/** + * ustar tarball archive + */ +file_t tar_initrd(unsigned char *initrd_p, char *kernel) +{ + unsigned char *ptr=initrd_p; + int k; + file_t ret = { NULL, 0 }; + if(initrd_p==NULL || kernel==NULL || CompareMem(initrd_p+257,"ustar",5)) + return ret; + DBG(L" * tar %s\n",a2u(kernel)); + k=strlena(kernel); + while(!CompareMem(ptr+257,"ustar",5)){ + int fs=oct2bin(ptr+0x7c,11); + if(!CompareMem(ptr,kernel,k+1) || (ptr[0] == '.' && ptr[1] == '/' && !CompareMem(ptr+2,kernel,k+1))) { + ret.size=fs; + ret.ptr=(UINT8*)(ptr+512); + return ret; + } + ptr+=(((fs+511)/512)+1)*512; + } + return ret; +} + +/** + * Simple File System + */ +file_t sfs_initrd(unsigned char *initrd_p, char *kernel) +{ + unsigned char *ptr, *end; + int k,bs,ver; + file_t ret = { NULL, 0 }; + if(initrd_p==NULL || kernel==NULL || (CompareMem(initrd_p+0x1AC,"SFS",3) && CompareMem(initrd_p+0x1A6,"SFS",3))) + return ret; + // 1.0 Brendan's version, 1.10 BenLunt's version + ver=!CompareMem(initrd_p+0x1A6,"SFS",3)?10:0; + bs=1<<(7+(UINT8)initrd_p[ver?0x1B6:0x1BC]); + end=initrd_p + *((UINT64 *)&initrd_p[ver?0x1AA:0x1B0]) * bs; // base + total_number_of_blocks * blocksize + // get index area + ptr=end - *((UINT64 *)&initrd_p[ver?0x19E:0x1A4]); // end - size of index area + // got a Starting Marker Entry? + if(ptr[0]!=2) + return ret; + DBG(L" * SFS 1.%d %s\n",ver,a2u(kernel)); + k=strlena(kernel); + // iterate on index until we reach the end or Volume Identifier + while(ptr + +/* calling convention */ +#ifndef TINFCC + #ifdef __WATCOMC__ + #define TINFCC __cdecl + #else + #define TINFCC + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ok status, more data produced */ +#define TINF_OK 0 +/* end of compressed stream reached */ +#define TINF_DONE 1 +#define TINF_DATA_ERROR (-3) +#define TINF_CHKSUM_ERROR (-4) +#define TINF_DICT_ERROR (-5) + +/* checksum types */ +#define TINF_CHKSUM_NONE 0 +#define TINF_CHKSUM_ADLER 1 +#define TINF_CHKSUM_CRC 2 + +/* data structures */ + +typedef struct { + unsigned short table[16]; /* table of code length counts */ + unsigned short trans[288]; /* code -> symbol translation table */ +} TINF_TREE; + +struct TINF_DATA; +typedef struct TINF_DATA { + const unsigned char *source; + /* If source above is NULL, this function will be used to read + next byte from source stream */ + unsigned char (*readSource)(struct TINF_DATA *data); + + unsigned int tag; + unsigned int bitcount; + + /* Buffer start */ + unsigned char *destStart; + /* Buffer total size */ + unsigned int destSize; + /* Current pointer in buffer */ + unsigned char *dest; + /* Remaining bytes in buffer */ + unsigned int destRemaining; + + /* Accumulating checksum */ + unsigned int checksum; + char checksum_type; + + int btype; + int bfinal; + unsigned int curlen; + int lzOff; + unsigned char *dict_ring; + unsigned int dict_size; + unsigned int dict_idx; + + TINF_TREE ltree; /* dynamic length/symbol tree */ + TINF_TREE dtree; /* dynamic distance tree */ +} TINF_DATA; + +#define TINF_PUT(d, c) \ + { \ + *d->dest++ = c; \ + if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \ + } + +unsigned char TINFCC uzlib_get_byte(TINF_DATA *d); + +/* Decompression API */ + +void TINFCC uzlib_init(void); +void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen); +int TINFCC uzlib_uncompress(TINF_DATA *d); +int TINFCC uzlib_uncompress_chksum(TINF_DATA *d); + +int TINFCC uzlib_zlib_parse_header(TINF_DATA *d); +int TINFCC uzlib_gzip_parse_header(TINF_DATA *d); + +/* Compression API */ + +void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen); + +/* Checksum API */ + +/* prev_sum is previous value for incremental computation, 1 initially */ +uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum); +/* crc is previous value for incremental computation, 0xffffffff initially */ +uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TINF_H_INCLUDED */ diff --git a/x86_64-efi/tinflate.c b/x86_64-efi/tinflate.c new file mode 100644 index 0000000..fc609fc --- /dev/null +++ b/x86_64-efi/tinflate.c @@ -0,0 +1,475 @@ +/* + * tinflate - tiny inflate + * + * Copyright (c) 2003 by Joergen Ibsen / Jibz + * All Rights Reserved + * http://www.ibsensoftware.com/ + * + * Copyright (c) 2014-2016 by Paul Sokolovsky + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be + * held liable for any damages arising from the use of + * this software. + * + * Permission is granted to anyone to use this software + * for any purpose, including commercial applications, + * and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The origin of this software must not be + * misrepresented; you must not claim that you + * wrote the original software. If you use this + * software in a product, an acknowledgment in + * the product documentation would be appreciated + * but is not required. + * + * 2. Altered source versions must be plainly marked + * as such, and must not be misrepresented as + * being the original software. + * + * 3. This notice may not be removed or altered from + * any source distribution. + */ + +#include "tinf.h" + +uint32_t tinf_get_le_uint32(TINF_DATA *d); +uint32_t tinf_get_be_uint32(TINF_DATA *d); + +/* --------------------------------------------------- * + * -- uninitialized global data (static structures) -- * + * --------------------------------------------------- */ + +#ifdef RUNTIME_BITS_TABLES + +/* extra bits and base tables for length codes */ +unsigned char length_bits[30]; +unsigned short length_base[30]; + +/* extra bits and base tables for distance codes */ +unsigned char dist_bits[30]; +unsigned short dist_base[30]; + +#else + +const unsigned char length_bits[30] = { + 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 +}; +const unsigned short length_base[30] = { + 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 +}; + +const unsigned char dist_bits[30] = { + 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 +}; +const unsigned short dist_base[30] = { + 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 +}; + +#endif + +/* special ordering of code length codes */ +const unsigned char clcidx[] = { + 16, 17, 18, 0, 8, 7, 9, 6, + 10, 5, 11, 4, 12, 3, 13, 2, + 14, 1, 15 +}; + +/* ----------------------- * + * -- utility functions -- * + * ----------------------- */ + +#ifdef RUNTIME_BITS_TABLES +/* build extra bits and base tables */ +static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first) +{ + int i, sum; + + /* build bits table */ + for (i = 0; i < delta; ++i) bits[i] = 0; + for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta; + + /* build base table */ + for (sum = first, i = 0; i < 30; ++i) + { + base[i] = sum; + sum += 1 << bits[i]; + } +} +#endif + +/* build the fixed huffman trees */ +static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt) +{ + int i; + + /* build fixed length tree */ + for (i = 0; i < 7; ++i) lt->table[i] = 0; + + lt->table[7] = 24; + lt->table[8] = 152; + lt->table[9] = 112; + + for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i; + for (i = 0; i < 144; ++i) lt->trans[24 + i] = i; + for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i; + for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i; + + /* build fixed distance tree */ + for (i = 0; i < 5; ++i) dt->table[i] = 0; + + dt->table[5] = 32; + + for (i = 0; i < 32; ++i) dt->trans[i] = i; +} + +/* given an array of code lengths, build a tree */ +static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num) +{ + unsigned short offs[16]; + unsigned int i, sum; + + /* clear code length count table */ + for (i = 0; i < 16; ++i) t->table[i] = 0; + + /* scan symbol lengths, and sum code length counts */ + for (i = 0; i < num; ++i) t->table[lengths[i]]++; + + t->table[0] = 0; + + /* compute offset table for distribution sort */ + for (sum = 0, i = 0; i < 16; ++i) + { + offs[i] = sum; + sum += t->table[i]; + } + + /* create code->symbol translation table (symbols sorted by code) */ + for (i = 0; i < num; ++i) + { + if (lengths[i]) t->trans[offs[lengths[i]]++] = i; + } +} + +/* ---------------------- * + * -- decode functions -- * + * ---------------------- */ + +unsigned char uzlib_get_byte(TINF_DATA *d) +{ + if (d->source) { + return *d->source++; + } + return d->readSource(d); +} + +uint32_t tinf_get_le_uint32(TINF_DATA *d) +{ + uint32_t val = 0; + int i; + for (i = 4; i--;) { + val = val >> 8 | uzlib_get_byte(d) << 24; + } + return val; +} + +uint32_t tinf_get_be_uint32(TINF_DATA *d) +{ + uint32_t val = 0; + int i; + for (i = 4; i--;) { + val = val << 8 | uzlib_get_byte(d); + } + return val; +} + +/* get one bit from source stream */ +static int tinf_getbit(TINF_DATA *d) +{ + unsigned int bit; + + /* check if tag is empty */ + if (!d->bitcount--) + { + /* load next tag */ + d->tag = uzlib_get_byte(d); + d->bitcount = 7; + } + + /* shift bit out of tag */ + bit = d->tag & 0x01; + d->tag >>= 1; + + return bit; +} + +/* read a num bit value from a stream and add base */ +static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base) +{ + unsigned int val = 0; + + /* read num bits */ + if (num) + { + unsigned int limit = 1 << (num); + unsigned int mask; + + for (mask = 1; mask < limit; mask *= 2) + if (tinf_getbit(d)) val += mask; + } + + return val + base; +} + +/* given a data stream and a tree, decode a symbol */ +static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) +{ + int sum = 0, cur = 0, len = 0; + + /* get more bits while code value is above sum */ + do { + + cur = 2*cur + tinf_getbit(d); + + ++len; + + sum += t->table[len]; + cur -= t->table[len]; + + } while (cur >= 0); + + return t->trans[sum + cur]; +} + +/* given a data stream, decode dynamic trees from it */ +static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) +{ + unsigned char lengths[288+32]; + unsigned int hlit, hdist, hclen; + unsigned int i, num, length; + + /* get 5 bits HLIT (257-286) */ + hlit = tinf_read_bits(d, 5, 257); + + /* get 5 bits HDIST (1-32) */ + hdist = tinf_read_bits(d, 5, 1); + + /* get 4 bits HCLEN (4-19) */ + hclen = tinf_read_bits(d, 4, 4); + + for (i = 0; i < 19; ++i) lengths[i] = 0; + + /* read code lengths for code length alphabet */ + for (i = 0; i < hclen; ++i) + { + /* get 3 bits code length (0-7) */ + unsigned int clen = tinf_read_bits(d, 3, 0); + + lengths[clcidx[i]] = clen; + } + + /* build code length tree, temporarily use length tree */ + tinf_build_tree(lt, lengths, 19); + + /* decode code lengths for the dynamic trees */ + for (num = 0; num < hlit + hdist; ) + { + int sym = tinf_decode_symbol(d, lt); + + switch (sym) + { + case 16: + /* copy previous code length 3-6 times (read 2 bits) */ + { + unsigned char prev = lengths[num - 1]; + for (length = tinf_read_bits(d, 2, 3); length; --length) + { + lengths[num++] = prev; + } + } + break; + case 17: + /* repeat code length 0 for 3-10 times (read 3 bits) */ + for (length = tinf_read_bits(d, 3, 3); length; --length) + { + lengths[num++] = 0; + } + break; + case 18: + /* repeat code length 0 for 11-138 times (read 7 bits) */ + for (length = tinf_read_bits(d, 7, 11); length; --length) + { + lengths[num++] = 0; + } + break; + default: + /* values 0-15 represent the actual code lengths */ + lengths[num++] = sym; + break; + } + } + + /* build dynamic trees */ + tinf_build_tree(lt, lengths, hlit); + tinf_build_tree(dt, lengths + hlit, hdist); +} + +/* ----------------------------- * + * -- block inflate functions -- * + * ----------------------------- */ + +/* given a stream and two trees, inflate a block of data */ +static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) +{ + if (d->curlen == 0) { + unsigned int offs; + int dist; + int sym = tinf_decode_symbol(d, lt); + //printf("huff sym: %02x\n", sym); + + /* literal byte */ + if (sym < 256) { + TINF_PUT(d, sym); + return TINF_OK; + } + + /* end of block */ + if (sym == 256) { + return TINF_DONE; + } + + /* substring from sliding dictionary */ + sym -= 257; + /* possibly get more bits from length code */ + d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]); + + dist = tinf_decode_symbol(d, dt); + /* possibly get more bits from distance code */ + offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); + d->lzOff = -offs; + } + + /* copy next byte from dict substring */ + d->dest[0] = d->dest[d->lzOff]; + d->dest++; + d->curlen--; + return TINF_OK; +} + +/* inflate an uncompressed block of data */ +static int tinf_inflate_uncompressed_block(TINF_DATA *d) +{ + if (d->curlen == 0) { + unsigned int length, invlength; + + /* get length */ + length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + /* get one's complement of length */ + invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + /* check length */ + if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; + + /* increment length to properly return TINF_DONE below, without + producing data at the same time */ + d->curlen = length + 1; + + /* make sure we start next block on a byte boundary */ + d->bitcount = 0; + } + + if (--d->curlen == 0) { + return TINF_DONE; + } + + unsigned char c = uzlib_get_byte(d); + TINF_PUT(d, c); + return TINF_OK; +} + +/* ---------------------- * + * -- public functions -- * + * ---------------------- */ + +/* initialize global (static) data */ +void uzlib_init(void) +{ +#ifdef RUNTIME_BITS_TABLES + /* build extra bits and base tables */ + tinf_build_bits_base(length_bits, length_base, 4, 3); + tinf_build_bits_base(dist_bits, dist_base, 2, 1); + + /* fix a special case */ + length_bits[28] = 0; + length_base[28] = 258; +#endif +} + +/* inflate next byte of compressed stream */ +int uzlib_uncompress(TINF_DATA *d) +{ + do { + int res; + + /* start a new block */ + if (d->btype == -1) { +next_blk: + /* read final block flag */ + d->bfinal = tinf_getbit(d); + /* read block type (2 bits) */ + d->btype = tinf_read_bits(d, 2, 0); + + //printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal); + + if (d->btype == 1) { + /* build fixed huffman trees */ + tinf_build_fixed_trees(&d->ltree, &d->dtree); + } else if (d->btype == 2) { + /* decode trees from stream */ + tinf_decode_trees(d, &d->ltree, &d->dtree); + } + } + + /* process current block */ + switch (d->btype) + { + case 0: + /* decompress uncompressed block */ + res = tinf_inflate_uncompressed_block(d); + break; + case 1: + case 2: + /* decompress block with fixed/dyanamic huffman trees */ + /* trees were decoded previously, so it's the same routine for both */ + res = tinf_inflate_block_data(d, &d->ltree, &d->dtree); + break; + default: + return TINF_DATA_ERROR; + } + + if (res == TINF_DONE && !d->bfinal) { + /* the block has ended (without producing more data), but we + can't return without data, so start procesing next block */ + goto next_blk; + } + + if (res != TINF_OK) { + return res; + } + + } while (--d->destSize); + + return TINF_OK; +}