/* * 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 "../dist/bootboot.h" /*** 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"); }