From: Kevin O'Connor Date: Sun, 26 Jul 2009 23:16:09 +0000 (-0400) Subject: Add support for enabling ram in 0xc0000-0xf0000 area. X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=e773930ea4f37bca9334a157e86e70f14234888f;p=seabios.git Add support for enabling ram in 0xc0000-0xf0000 area. Enhance shadow ram support to enable read/write of option rom area. This enables support for option roms that modify themselves. Support copying the roms before enabling shadowing, to work around the qemu implementation of ram shadowing. Rename next_rom to RomEnd and export it. Support locking ram being used for optionroms before booting. Don't bother and'ing/or'ing 0x59 register - it's usage is well defined. --- diff --git a/src/config.h b/src/config.h index 3b4b5fe..6f19107 100644 --- a/src/config.h +++ b/src/config.h @@ -112,8 +112,11 @@ #define BUILD_STACK_ADDR 0x7c00 #define BUILD_S3RESUME_STACK_ADDR 0x1000 #define BUILD_AP_BOOT_ADDR 0x10000 +#define BUILD_ROM_START 0xc0000 #define BUILD_BIOS_ADDR 0xf0000 #define BUILD_BIOS_SIZE 0x10000 +// 32KB for shadow ram copying (works around emulator deficiencies) +#define BUILD_BIOS_TMP_ADDR 0x30000 #define BUILD_APIC_ADDR 0xfee00000 #define BUILD_IOAPIC_ADDR 0xfec00000 diff --git a/src/optionroms.c b/src/optionroms.c index 93c1959..00fa85d 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -64,15 +64,14 @@ struct pnp_data { u16 staticresource; } PACKED; -#define OPTION_ROM_START 0xc0000 #define OPTION_ROM_SIGNATURE 0xaa55 #define OPTION_ROM_ALIGN 2048 #define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0]) #define PCI_ROM_SIGNATURE 0x52494350 // PCIR #define PCIROM_CODETYPE_X86 0 -// Next available position for an option rom. -static u32 next_rom; +// The end of the last deployed rom. +u32 RomEnd; /**************************************************************** @@ -171,15 +170,15 @@ static struct rom_header * copy_rom(struct rom_header *rom) { u32 romsize = rom->size * 512; - if (next_rom + romsize > BUILD_BIOS_ADDR) { + if (RomEnd + romsize > BUILD_BIOS_ADDR) { // Option rom doesn't fit. dprintf(1, "Option rom %p doesn't fit.\n", rom); return NULL; } dprintf(4, "Copying option rom (size %d) from %p to %x\n" - , romsize, rom, next_rom); - memcpy((void*)next_rom, rom, romsize); - return (void*)next_rom; + , romsize, rom, RomEnd); + memcpy((void*)RomEnd, rom, romsize); + return (void*)RomEnd; } // Run rom init code and note rom size. @@ -193,7 +192,7 @@ init_optionrom(struct rom_header *rom, u16 bdf, int isvga) // Only init vga and PnP roms here. callrom(rom, bdf); - next_rom = (u32)rom + ALIGN(rom->size * 512, OPTION_ROM_ALIGN); + RomEnd = (u32)rom + ALIGN(rom->size * 512, OPTION_ROM_ALIGN); return 0; } @@ -215,11 +214,11 @@ lookup_hardcode(u32 vendev) && ((OPTIONROM_VENDEV_2 >> 16) | ((OPTIONROM_VENDEV_2 & 0xffff)) << 16) == vendev) return copy_rom((void*)OPTIONROM_MEM_2); - int ret = cbfs_copy_optionrom((void*)next_rom, BUILD_BIOS_ADDR - next_rom + int ret = cbfs_copy_optionrom((void*)RomEnd, BUILD_BIOS_ADDR - RomEnd , vendev); if (ret < 0) return NULL; - return (void*)next_rom; + return (void*)RomEnd; } // Run all roms in a given CBFS directory. @@ -229,10 +228,10 @@ run_cbfs_roms(const char *prefix, int isvga) struct cbfs_file *tmp = NULL; for (;;) { tmp = cbfs_copyfile_prefix( - (void*)next_rom, BUILD_BIOS_ADDR - next_rom, prefix, tmp); + (void*)RomEnd, BUILD_BIOS_ADDR - RomEnd, prefix, tmp); if (!tmp) break; - init_optionrom((void*)next_rom, 0, isvga); + init_optionrom((void*)RomEnd, 0, isvga); } } @@ -339,17 +338,17 @@ optionrom_setup() dprintf(1, "Scan for option roms\n"); - u32 post_vga = next_rom; + u32 post_vga = RomEnd; if (CONFIG_OPTIONROMS_DEPLOYED) { // Option roms are already deployed on the system. - u32 pos = next_rom; + u32 pos = RomEnd; while (pos < BUILD_BIOS_ADDR) { int ret = init_optionrom((void*)pos, 0, 0); if (ret) pos += OPTION_ROM_ALIGN; else - pos = next_rom; + pos = RomEnd; } } else { // Find and deploy PCI roms. @@ -369,7 +368,7 @@ optionrom_setup() // All option roms found and deployed - now build BEV/BCV vectors. u32 pos = post_vga; - while (pos < next_rom) { + while (pos < RomEnd) { struct rom_header *rom = (void*)pos; if (! is_valid_rom(rom)) { pos += OPTION_ROM_ALIGN; @@ -404,16 +403,17 @@ optionrom_setup() void vga_setup() { + VGAbdf = -1; + RomEnd = BUILD_ROM_START; + if (! CONFIG_OPTIONROMS) return; dprintf(1, "Scan for VGA option rom\n"); - VGAbdf = -1; - next_rom = OPTION_ROM_START; if (CONFIG_OPTIONROMS_DEPLOYED) { // Option roms are already deployed on the system. - init_optionrom((void*)OPTION_ROM_START, 0, 1); + init_optionrom((void*)BUILD_ROM_START, 0, 1); } else { // Find and deploy PCI VGA rom. int bdf = VGAbdf = pci_find_vga(); @@ -424,9 +424,9 @@ vga_setup() run_cbfs_roms("vgaroms/", 1); } - if (next_rom == OPTION_ROM_START) { + if (RomEnd == BUILD_ROM_START) { // No VGA rom found - next_rom += OPTION_ROM_ALIGN; + RomEnd += OPTION_ROM_ALIGN; return; } @@ -445,7 +445,7 @@ s3_resume_vga_init() { if (!CONFIG_S3_RESUME_VGA_INIT) return; - struct rom_header *rom = (void*)OPTION_ROM_START; + struct rom_header *rom = (void*)BUILD_ROM_START; if (! is_valid_rom(rom)) return; callrom(rom, 0); diff --git a/src/shadow.c b/src/shadow.c index 1c389f4..daa2e21 100644 --- a/src/shadow.c +++ b/src/shadow.c @@ -1,6 +1,6 @@ // Support for enabling/disabling BIOS ram shadowing. // -// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2008,2009 Kevin O'Connor // Copyright (C) 2006 Fabrice Bellard // // This file may be distributed under the terms of the GNU LGPLv3 license. @@ -23,13 +23,13 @@ // Enable shadowing and copy bios. static void -copy_bios(u16 bdf, int reg) +copy_bios(u16 bdf) { - pci_config_writeb(bdf, 0x59, reg | 0x30); + pci_config_writeb(bdf, 0x59, 0x30); memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE); } -// Make the BIOS code segment area (0xf0000) writable. +// Make the 0xc0000-0x100000 area read/writable. void make_bios_writable() { @@ -45,10 +45,33 @@ make_bios_writable() return; } + // Make ram from 0xc0000-0xf0000 writable + int clear = 0; + int i; + for (i=0; i<6; i++) { + if (CONFIG_OPTIONROMS_DEPLOYED) { + int reg = pci_config_readb(bdf, 0x5a + i); + if ((reg & 0x11) != 0x11) { + // Need to copy optionroms to work around qemu implementation + void *mem = (void*)(BUILD_ROM_START + i * 32*1024); + memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024); + pci_config_writeb(bdf, 0x5a + i, 0x33); + memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024); + clear = 1; + } else { + pci_config_writeb(bdf, 0x5a + i, 0x33); + } + } else { + pci_config_writeb(bdf, 0x5a + i, 0x33); + } + } + if (clear) + memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024); + int reg = pci_config_readb(bdf, 0x59); - if (reg & 0x30) { + if (reg & 0x10) { // Ram already present - just enable writes - pci_config_writeb(bdf, 0x59, reg | 0x30); + pci_config_writeb(bdf, 0x59, 0x30); return; } @@ -58,10 +81,10 @@ make_bios_writable() // temporary storage area so that memory does not change under // the executing code. u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BIOS_SRC_ADDR; - void (*func)(u16 bdf, int reg) = (void*)pos; - func(bdf, reg); + void (*func)(u16 bdf) = (void*)pos; + func(bdf); } else { - copy_bios(bdf, reg); + copy_bios(bdf); } } @@ -80,8 +103,21 @@ make_bios_readonly() return; } + // Flush any pending writes before locking memory. wbinvd(); - int v = pci_config_readb(bdf, 0x59); - v = (v & 0x0f) | (0x10); - pci_config_writeb(bdf, 0x59, v); + + // Write protect roms from 0xc0000-0xf0000 + int i; + for (i=0; i<6; i++) { + u32 mem = BUILD_ROM_START + i * 32*1024; + if (RomEnd <= mem + 16*1024) { + if (RomEnd > mem) + pci_config_writeb(bdf, 0x5a + i, 0x31); + break; + } + pci_config_writeb(bdf, 0x5a + i, 0x11); + } + + // Write protect 0xf0000-0x100000 + pci_config_writeb(bdf, 0x59, 0x10); } diff --git a/src/util.h b/src/util.h index b566f56..8ae54f4 100644 --- a/src/util.h +++ b/src/util.h @@ -220,6 +220,7 @@ void call_bcv(u16 seg, u16 ip); void optionrom_setup(); void vga_setup(); void s3_resume_vga_init(); +extern u32 RomEnd; // resume.c void init_dma();