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/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;