diff -u --recursive ../clean/linux-4.9.38/arch/x86/boot/compressed/eboot.c linux-4.9.38/arch/x86/boot/compressed/eboot.c --- ../clean/linux-4.9.38/arch/x86/boot/compressed/eboot.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/arch/x86/boot/compressed/eboot.c 2017-09-22 14:55:37.055153767 -0400 @@ -16,6 +16,71 @@ #include "../string.h" #include "eboot.h" +#define PORT 0x3f8 /* COM1 */ + +#define DLAB 0x80 + +#define TXR 0 /* Transmit register (WRITE) */ +#define RXR 0 /* Receive register (READ) */ +#define IER 1 /* Interrupt Enable */ +#define IIR 2 /* Interrupt ID */ +#define FCR 2 /* FIFO control */ +#define LCR 3 /* Line control */ +#define MCR 4 /* Modem control */ +#define LSR 5 /* Line Status */ +#define MSR 6 /* Modem Status */ +#define DLL 0 /* Divisor Latch Low */ +#define DLH 1 /* Divisor latch High */ + +static void early_serial_init(int port, int baud) +{ + unsigned char c; + unsigned divisor; + + outb(0x3, port + LCR); /* 8n1 */ + outb(0, port + IER); /* no interrupt */ + outb(0, port + FCR); /* no fifo */ + outb(0x3, port + MCR); /* DTR + RTS */ + + divisor = 115200 / baud; + c = inb(port + LCR); + outb(c | DLAB, port + LCR); + outb(divisor & 0xff, port + DLL); + outb((divisor >> 8) & 0xff, port + DLH); + outb(c & ~DLAB, port + LCR); +} + +static int is_transmit_empty() { + return inb(PORT + 5) & 0x20; +} + +void serial_char(char a) { + outb(a, PORT); + while (is_transmit_empty() == 0); +} + +void serial_string(const char * s) +{ + while(*s) + serial_char(*s++); +} + +void serial_hex(unsigned long x, unsigned digits) +{ + while(digits-- > 0) + { + unsigned d = (x >> (digits * 4)) & 0xF; + if (d >= 0xA) + serial_char(d + 'A' - 0xA); + else + serial_char(d + '0'); + } + serial_char('\r'); + serial_char('\n'); +} + + + static efi_system_table_t *sys_table; static struct efi_config *efi_early; @@ -249,6 +314,12 @@ void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) { +#if 0 + while(*str) + { + write_serial((char) *str++); + } +#else unsigned long output_string; size_t offset; @@ -273,6 +344,7 @@ efi_early->call(*func, out, str); } +#endif } static efi_status_t @@ -710,6 +782,100 @@ } } +#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID EFI_GUID(0x220e73b6, 0x6bdb, 0x4413, 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a) +typedef struct _EFI_FIRMWARE_VOLUME2_PROTOCOL { + uint64_t GetVolumeAttributes; + uint64_t SetVolumeAttributes; + uint64_t ReadFile; + uint64_t ReadSection; + uint64_t WriteFile; + uint64_t GetNextFile; + uint32_t KeySize; + uint64_t ParentHandle; + uint64_t GetInfo; + uint64_t SetInfo; +} efi_firmware_volume2_protocol_t; + + +/* + * attempt to locate the ramdisk in our firmware volume. + * This assumes that it has a well-known GUID. + */ +static int nerf_find_initrd(const efi_guid_t * initrd_guid, void ** buffer, uint32_t * size) +{ + efi_status_t status; + efi_guid_t fv_proto = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID; + void ** handles = NULL; + unsigned long handle_count; + + status = efi_call_early(locate_handle_buffer, + EFI_LOCATE_BY_PROTOCOL, + &fv_proto, + NULL, + &handle_count, + &handles + ); + + if (status != 0) + { + serial_string("locate_handle rc="); + serial_hex(status, 8); + return -1; + } + + for(unsigned i = 0 ; i < handle_count ; i++) + { + efi_firmware_volume2_protocol_t * fv = NULL; + uint32_t auth_status = 0; + + serial_string("handle="); + serial_hex((unsigned long) handles[i], 16); + + status = efi_call_early(handle_protocol, + handles[i], + &fv_proto, + (void**) &fv + ); + + if (status != 0) + { + serial_string("handle proto rc="); + serial_hex(status, 8); + continue; + } + + serial_string("fv="); + serial_hex((unsigned long) fv, 16); + serial_hex((unsigned long) &fv->ReadSection, 16); + serial_hex((unsigned long) fv->ReadSection, 16); + + status = efi_early->call(fv->ReadSection, + fv, + initrd_guid, + 0x19, // EFI_SECTION_RAW + 0, + buffer, + size, + &auth_status + ); + if (status != 0) + { + serial_string("read section rc="); + serial_hex(status, 8); + continue; + } + + serial_string("initrd "); + serial_hex((unsigned long) *buffer, 16); + serial_hex(*size, 8); + return 0; + } + + // this leaks the handle buffer. + serial_string("initrd not found\r\n"); + return -1; +} + /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create @@ -739,8 +905,18 @@ sys_table = (efi_system_table_t *)(unsigned long)efi_early->table; handle = (void *)(unsigned long)efi_early->image_handle; + if(!sys_table) + { + // We're NERFed and are the "DxeCore", so there is no system + // table. The efi_config argument is actually the HobStart + // pointer, but who cares about that stuff. + // TODO: actually handle this case + while(1) + outb('!', 0x3f8); + } + /* Check if we were booted by the EFI firmware */ - if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + if (!sys_table || sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) return NULL; if (efi_early->is64) @@ -751,7 +927,6 @@ status = efi_call_early(handle_protocol, handle, &proto, (void *)&image); if (status != EFI_SUCCESS) { - efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); return NULL; } @@ -814,6 +989,21 @@ if (status != EFI_SUCCESS) goto fail2; + +#if 1 + void * initrd_ptr = NULL; + uint32_t initrd_size = 0; + if (nerf_find_initrd( + (const efi_guid_t*) "initrd.cpio/bios", + &initrd_ptr, + &initrd_size + ) == 0 ) + { + ramdisk_addr = (uintptr_t) initrd_ptr; + ramdisk_size = initrd_size; + } +#endif + hdr->ramdisk_image = ramdisk_addr & 0xffffffff; hdr->ramdisk_size = ramdisk_size & 0xffffffff; boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; @@ -1068,6 +1262,7 @@ struct boot_params *efi_main(struct efi_config *c, struct boot_params *boot_params) { +serial_string("efi_main\r\n"); struct desc_ptr *gdt = NULL; efi_loaded_image_t *image; struct setup_header *hdr = &boot_params->hdr; diff -u --recursive ../clean/linux-4.9.38/arch/x86/boot/compressed/head_64.S linux-4.9.38/arch/x86/boot/compressed/head_64.S --- ../clean/linux-4.9.38/arch/x86/boot/compressed/head_64.S 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/arch/x86/boot/compressed/head_64.S 2017-09-20 10:58:06.101915625 -0400 @@ -294,8 +294,12 @@ jne 2f fail: /* EFI init failed, so hang. */ + mov $0x3f8, %dx /* ttyS0 */ + mov '@', %ax +fail_loop: + outb %al, (%dx) hlt - jmp fail + jmp fail_loop 2: movl BP_code32_start(%esi), %eax leaq preferred_addr(%rax), %rax diff -u --recursive ../clean/linux-4.9.38/arch/x86/realmode/init.c linux-4.9.38/arch/x86/realmode/init.c --- ../clean/linux-4.9.38/arch/x86/realmode/init.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/arch/x86/realmode/init.c 2017-09-20 10:58:06.101915625 -0400 @@ -35,8 +35,8 @@ /* Has to be under 1M so we can execute real-mode AP code. */ mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); if (!mem) { - pr_info("No sub-1M memory is available for the trampoline\n"); - return; + mem = 0x4000; + pr_info("No sub-1M memory is available for the trampoline, guessing %p\n", mem); } memblock_reserve(mem, size); @@ -138,7 +138,12 @@ static int __init init_real_mode(void) { if (!real_mode_header) - panic("Real mode trampoline was not allocated"); + { + // ignore for now + //panic("Real mode trampoline was not allocated"); + pr_warn("Real mode trampoline was not allocated"); + return 0; + } setup_real_mode(); set_real_mode_permissions(); diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/acpica/evxfevnt.c linux-4.9.38/drivers/acpi/acpica/evxfevnt.c --- ../clean/linux-4.9.38/drivers/acpi/acpica/evxfevnt.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/acpica/evxfevnt.c 2017-09-20 10:58:06.101915625 -0400 @@ -111,6 +111,8 @@ } ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode")); +printk("%s:%d faking ACPI mode\n", __func__, __LINE__); + return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/acpica/hwacpi.c linux-4.9.38/drivers/acpi/acpica/hwacpi.c --- ../clean/linux-4.9.38/drivers/acpi/acpica/hwacpi.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/acpica/hwacpi.c 2017-09-20 10:58:06.101915625 -0400 @@ -168,12 +168,16 @@ status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); if (ACPI_FAILURE(status)) { +printk("%s:%d faking ACPI mode\n", __func__, __LINE__); + return_UINT32(ACPI_SYS_MODE_ACPI); return_UINT32(ACPI_SYS_MODE_LEGACY); } if (value) { return_UINT32(ACPI_SYS_MODE_ACPI); } else { +//printk("%s:%d faking ACPI mode\n", __func__, __LINE__); +// return_UINT32(ACPI_SYS_MODE_ACPI); return_UINT32(ACPI_SYS_MODE_LEGACY); } } diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/acpica/tbfadt.c linux-4.9.38/drivers/acpi/acpica/tbfadt.c --- ../clean/linux-4.9.38/drivers/acpi/acpica/tbfadt.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/acpica/tbfadt.c 2017-09-20 10:58:06.101915625 -0400 @@ -344,6 +344,7 @@ /* Obtain the DSDT and FACS tables via their addresses within the FADT */ +#if 0 // NERF: the dsdt and facs tables will be updated later acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT. Xdsdt, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, @@ -367,6 +368,7 @@ &acpi_gbl_xfacs_index); } } +#endif } /******************************************************************************* diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/acpica/tbxface.c linux-4.9.38/drivers/acpi/acpica/tbxface.c --- ../clean/linux-4.9.38/drivers/acpi/acpica/tbxface.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/acpica/tbxface.c 2017-09-20 10:58:06.101915625 -0400 @@ -136,7 +136,11 @@ rsdp_address = acpi_os_get_root_pointer(); if (!rsdp_address) { - return_ACPI_STATUS(AE_NOT_FOUND); +// NERF: there is no root table since we came straight from DxeCore +printk("%s:%d No root table found, hoping for the best\n", __func__, __LINE__); + return_ACPI_STATUS(0); + //return_ACPI_STATUS(AE_NOT_FOUND); + //rsdp_address = fake_rsdp; } /* diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/acpica/tbxfload.c linux-4.9.38/drivers/acpi/acpica/tbxfload.c --- ../clean/linux-4.9.38/drivers/acpi/acpica/tbxfload.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/acpica/tbxfload.c 2017-09-20 10:58:06.101915625 -0400 @@ -277,6 +277,7 @@ acpi_status status; u8 flags; u32 table_index; + union acpi_name_union * sig; ACPI_FUNCTION_TRACE(acpi_install_table); @@ -289,6 +290,30 @@ status = acpi_tb_install_standard_table(address, flags, FALSE, FALSE, &table_index); + if (!ACPI_SUCCESS(status)) + return_ACPI_STATUS(status); + + // NERF: the tables have been added *after* the root table + // was looked for, so we have to update the global pointers + // now that we have the actual tables. + sig = &acpi_gbl_root_table_list.tables[table_index].signature; + + if (ACPI_COMPARE_NAME(sig, ACPI_SIG_FADT)) { + printk("%s: FADT index=%d\n", __func__, table_index); + acpi_gbl_fadt_index = table_index; + acpi_tb_parse_fadt(); + } else + if (ACPI_COMPARE_NAME(sig, ACPI_SIG_FACS)) { + printk("%s: FACS index=%d\n", __func__, table_index); + acpi_gbl_facs_index = table_index; + } else + if (ACPI_COMPARE_NAME(sig, ACPI_SIG_DSDT)) { + printk("%s: DSDT index=%d\n", __func__, table_index); + acpi_gbl_dsdt_index = table_index; + } else { + // nothing special about this table + } + return_ACPI_STATUS(status); } diff -u --recursive ../clean/linux-4.9.38/drivers/acpi/tables.c linux-4.9.38/drivers/acpi/tables.c --- ../clean/linux-4.9.38/drivers/acpi/tables.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/acpi/tables.c 2017-09-20 10:58:06.101915625 -0400 @@ -475,7 +475,8 @@ ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, - ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; + ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, ACPI_SIG_FACS, + NULL }; #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) @@ -487,8 +488,18 @@ void __init acpi_table_upgrade(void) { +#if 0 void *data = (void *)initrd_start; size_t size = initrd_end - initrd_start; +#else + // NERF: The initramfs that is bundled with the kernel has + // our tables in its cpio file. There is no boot loader to + // set the initrd_start variable, so we have to use this one. +extern char __initramfs_start[]; +extern unsigned long __initramfs_size; + void *data = (void *)__initramfs_start; + size_t size = __initramfs_size; +#endif int sig, no, table_nr = 0, total_offset = 0; long offset = 0; struct acpi_table_header *table; @@ -528,7 +539,11 @@ cpio_path, file.name); continue; } - if (acpi_table_checksum(file.data, table->length)) { + + // NERF: ignore checksum errors on FACS since it doesn't have one + // but allow it to be added anyway. + if (memcmp(table->signature, ACPI_SIG_FACS, 4) != 0 + && acpi_table_checksum(file.data, table->length)) { pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n", cpio_path, file.name); continue; diff -u --recursive ../clean/linux-4.9.38/drivers/firmware/efi/vars.c linux-4.9.38/drivers/firmware/efi/vars.c --- ../clean/linux-4.9.38/drivers/firmware/efi/vars.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/drivers/firmware/efi/vars.c 2017-09-20 10:58:06.101915625 -0400 @@ -429,6 +429,12 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), void *data, bool duplicates, struct list_head *head) { + // NERF: We do not have the EfiVars protocol, so none of these + // routines will work. This avoids a possible kernel panic by + // not calling the random pointers in the runtime services. + printk("%s: not running\n", __func__); + return 0; + const struct efivar_operations *ops = __efivars->ops; unsigned long variable_name_size = 1024; efi_char16_t *variable_name; diff -u --recursive ../clean/linux-4.9.38/init/initramfs.c linux-4.9.38/init/initramfs.c --- ../clean/linux-4.9.38/init/initramfs.c 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/init/initramfs.c 2017-09-20 10:58:06.101915625 -0400 @@ -609,7 +609,7 @@ { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size); if (err) - panic("%s", err); /* Failed to decompress INTERNAL initramfs */ + panic("%s: %s", __func__, err); /* Failed to decompress INTERNAL initramfs */ if (initrd_start) { #ifdef CONFIG_BLK_DEV_RAM int fd; diff -u --recursive ../clean/linux-4.9.38/usr/Makefile linux-4.9.38/usr/Makefile --- ../clean/linux-4.9.38/usr/Makefile 2017-07-15 06:17:55.000000000 -0400 +++ linux-4.9.38/usr/Makefile 2017-09-22 15:16:19.128175394 -0400 @@ -24,6 +24,11 @@ # Gzip suffix_$(CONFIG_RD_GZIP) = .gz +# NERF doesn't support compressed initramfs, so it must disable +# the compression here. The initrd image will be compressed in +# the EFI firmware, however. +suffix_y = + AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/initramfs_data.cpio$(suffix_y)" # Generate builtin.o based on initramfs_data.o