mirror of https://github.com/xemu-project/xemu.git
xbox: Support MCPX ROM overlay disable
This commit is contained in:
parent
ada547c981
commit
5a353bf500
|
@ -62,6 +62,8 @@
|
|||
/* FIXME: Clean this up and propagate errors to UI */
|
||||
static void xbox_flash_init(MemoryRegion *rom_memory)
|
||||
{
|
||||
const uint32_t rom_start = 0xFF000000;
|
||||
|
||||
/* Locate BIOS ROM image */
|
||||
if (bios_name == NULL) {
|
||||
bios_name = "bios.bin";
|
||||
|
@ -69,7 +71,7 @@ static void xbox_flash_init(MemoryRegion *rom_memory)
|
|||
|
||||
int failed_to_load_bios = 1;
|
||||
char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
int bios_size = 256*1024;
|
||||
uint32_t bios_size = 256*1024;
|
||||
|
||||
if (filename != NULL) {
|
||||
int bios_file_size = get_image_size(filename);
|
||||
|
@ -93,7 +95,6 @@ static void xbox_flash_init(MemoryRegion *rom_memory)
|
|||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (failed_to_load_bios) {
|
||||
|
@ -104,6 +105,24 @@ static void xbox_flash_init(MemoryRegion *rom_memory)
|
|||
g_free(filename);
|
||||
}
|
||||
|
||||
/* Create BIOS region */
|
||||
MemoryRegion *bios;
|
||||
bios = g_malloc(sizeof(*bios));
|
||||
assert(bios != NULL);
|
||||
memory_region_init_rom(bios, NULL, "xbox.bios", bios_size, &error_fatal);
|
||||
rom_add_blob_fixed("xbox.bios", bios_data, bios_size, rom_start);
|
||||
|
||||
/* Mirror ROM from 0xff000000 - 0xffffffff */
|
||||
uint32_t map_loc;
|
||||
for (map_loc = rom_start;
|
||||
map_loc >= rom_start;
|
||||
map_loc += bios_size) {
|
||||
MemoryRegion *map_bios = g_malloc(sizeof(*map_bios));
|
||||
memory_region_init_alias(map_bios, NULL, "pci-bios", bios, 0, bios_size);
|
||||
memory_region_add_subregion(rom_memory, map_loc, map_bios);
|
||||
memory_region_set_readonly(map_bios, true);
|
||||
}
|
||||
|
||||
/* XBOX_FIXME: What follows is a big hack to overlay the MCPX ROM on the
|
||||
* top 512 bytes of the ROM region. This differs from original XQEMU
|
||||
* sources which copied it in at lpc init; new QEMU seems to be different
|
||||
|
@ -137,49 +156,25 @@ static void xbox_flash_init(MemoryRegion *rom_memory)
|
|||
/* Read in MCPX ROM over last 512 bytes of BIOS data */
|
||||
int fd = open(filename, O_RDONLY | O_BINARY);
|
||||
assert(fd >= 0);
|
||||
int rc = read(fd, &bios_data[bios_size - bootrom_size], bootrom_size);
|
||||
int rc = read(fd, bios_data + bios_size - bootrom_size, bootrom_size);
|
||||
assert(rc == bootrom_size);
|
||||
close(fd);
|
||||
g_free(filename);
|
||||
|
||||
/* This last overlay instance is special with bios and MCPX combined.
|
||||
* The overlay must be page-aligned or it will take a huge performance hit.
|
||||
* Retail 1.1+ kernels rely on cached writes here so it's not marked readonly.
|
||||
* Once the MCPX is disabled things should resort back to the readonly alias.
|
||||
*/
|
||||
|
||||
MemoryRegion *mcpx = g_malloc(sizeof(MemoryRegion));
|
||||
memory_region_init_ram(mcpx, NULL, "xbox.mcpx", bios_size, &error_fatal);
|
||||
rom_add_blob_fixed("xbox.mcpx", bios_data, bios_size, -bios_size);
|
||||
memory_region_add_subregion_overlap(rom_memory, -bios_size, mcpx, 1);
|
||||
}
|
||||
|
||||
/* XBOX_FIXME: The "memory_region_set_readonly" calls below have been
|
||||
* temporarily commented out due to MCPX 1.1-based kernels hanging
|
||||
* in the first bootloader stage when doing RSA signature verification.
|
||||
*
|
||||
* This is caused by code incorrectly using the flash memory range to
|
||||
* store the following computation; luckily real hardware's writeback
|
||||
* cache policy (verified against MTRR config) appears to allow this
|
||||
* to succeed, but qemu's emulation of such isn't capable of this yet
|
||||
* so the value is never updated in ROM unless readonly is unspecified.
|
||||
*
|
||||
* sub ds:0FFFFD52Ch, eax
|
||||
* mov eax, ds:0FFFFD52Ch
|
||||
*/
|
||||
|
||||
/* Create BIOS region */
|
||||
MemoryRegion *bios;
|
||||
bios = g_malloc(sizeof(*bios));
|
||||
assert(bios != NULL);
|
||||
memory_region_init_ram(bios, NULL, "xbox.bios", bios_size, &error_fatal);
|
||||
//memory_region_set_readonly(bios, true);
|
||||
rom_add_blob_fixed("xbox.bios", bios_data, bios_size,
|
||||
(uint32_t)(-2 * bios_size));
|
||||
|
||||
/* Assuming bios_data will be needed for duration of execution
|
||||
* so no free(bios) here.
|
||||
*/
|
||||
|
||||
/* Mirror ROM from 0xff000000 - 0xffffffff */
|
||||
uint32_t map_loc;
|
||||
for (map_loc = (uint32_t)(-bios_size);
|
||||
map_loc >= 0xff000000;
|
||||
map_loc -= bios_size) {
|
||||
MemoryRegion *map_bios = g_malloc(sizeof(*map_bios));
|
||||
memory_region_init_alias(map_bios, NULL, "pci-bios", bios, 0, bios_size);
|
||||
memory_region_add_subregion(rom_memory, map_loc, map_bios);
|
||||
//memory_region_set_readonly(map_bios, true);
|
||||
}
|
||||
// no longer needed, rom_add_blob_fixed results in a copy, not a reference
|
||||
g_free(bios_data);
|
||||
}
|
||||
|
||||
static void xbox_memory_init(PCMachineState *pcms,
|
||||
|
@ -270,7 +265,7 @@ void xbox_init_common(MachineState *machine,
|
|||
|
||||
xbox_pci_init(x86ms->gsi,
|
||||
get_system_memory(), get_system_io(),
|
||||
pci_memory, ram_memory,
|
||||
pci_memory, ram_memory, rom_memory,
|
||||
&pci_bus,
|
||||
&isa_bus,
|
||||
&smbus,
|
||||
|
|
|
@ -146,6 +146,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
MemoryRegion *address_space_io,
|
||||
MemoryRegion *pci_memory,
|
||||
MemoryRegion *ram_memory,
|
||||
MemoryRegion *rom_memory,
|
||||
PCIBus **out_host_bus,
|
||||
ISABus **out_isa_bus,
|
||||
I2CBus **out_smbus,
|
||||
|
@ -188,6 +189,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
true, "xbox-lpc");
|
||||
XBOX_LPCState *lpc_state = XBOX_LPC_DEVICE(lpc);
|
||||
lpc_state->pic = pic;
|
||||
lpc_state->rom_memory = rom_memory;
|
||||
|
||||
pci_bus_irqs(host_bus, xbox_lpc_set_irq, xbox_lpc_map_irq, lpc_state,
|
||||
XBOX_NUM_INT_IRQS + XBOX_NUM_PIRQS);
|
||||
|
@ -309,10 +311,34 @@ static void xbox_lpc_realize(PCIDevice *dev, Error **errp)
|
|||
d->isa_bus = isa_bus;
|
||||
}
|
||||
|
||||
static void xbox_lpc_enable_mcpx_rom(PCIDevice *dev, bool enable) {
|
||||
XBOX_LPCState *s = XBOX_LPC_DEVICE(dev);
|
||||
MemoryRegion *subregion;
|
||||
QTAILQ_FOREACH(subregion, &s->rom_memory->subregions, subregions_link) {
|
||||
if (subregion->name != NULL && strcmp(subregion->name, "xbox.mcpx") == 0) {
|
||||
memory_region_set_enabled(subregion, enable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void xbox_lpc_reset(DeviceState *dev)
|
||||
{
|
||||
// PCIDevice *d = PCI_DEVICE(dev);
|
||||
// XBOX_LPCState *s = XBOX_LPC_DEVICE(d);
|
||||
XBOXPCI_DPRINTF("ACTIVATING BOOT ROM\n");
|
||||
xbox_lpc_enable_mcpx_rom(PCI_DEVICE(dev), true);
|
||||
}
|
||||
|
||||
static void xbox_lpc_config_write(PCIDevice *dev,
|
||||
uint32_t addr, uint32_t val, int len)
|
||||
{
|
||||
pci_default_write_config(dev, addr, val, len);
|
||||
|
||||
if ((addr == 0x80) && (val & 2)) {
|
||||
XBOXPCI_DPRINTF("DEACTIVATING BOOT ROM\n");
|
||||
xbox_lpc_enable_mcpx_rom(dev, false);
|
||||
}
|
||||
|
||||
XBOXPCI_DPRINTF("%s: %x %x %d\n", __func__, addr, val, len);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -389,7 +415,7 @@ static void xbox_lpc_class_init(ObjectClass *klass, void *data)
|
|||
|
||||
dc->hotpluggable = false;
|
||||
k->realize = xbox_lpc_realize;
|
||||
//k->config_write = xbox_lpc_config_write;
|
||||
k->config_write = xbox_lpc_config_write;
|
||||
k->vendor_id = PCI_VENDOR_ID_NVIDIA;
|
||||
k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_LPC;
|
||||
/* FIXME - correct revision for this is 0xB2 (178) for retail 1.0 Xbox, causes known USB bug */
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef struct XBOX_LPCState {
|
|||
XBOX_PMRegs pm;
|
||||
qemu_irq *pic;
|
||||
|
||||
MemoryRegion *rom_memory;
|
||||
int bootrom_size;
|
||||
uint8_t bootrom_data[512];
|
||||
} XBOX_LPCState;
|
||||
|
@ -73,6 +74,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
MemoryRegion *address_space_io,
|
||||
MemoryRegion *pci_memory,
|
||||
MemoryRegion *ram_memory,
|
||||
MemoryRegion *rom_memory,
|
||||
PCIBus **out_host_bus,
|
||||
ISABus **out_isa_bus,
|
||||
I2CBus **out_smbus,
|
||||
|
|
Loading…
Reference in New Issue