Move many C files from the src/ directory to the new src/fw/ directory.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
# Source files
SRCBOTH=misc.c stacks.c output.c util.c block.c hw/floppy.c hw/ata.c mouse.c \
- kbd.c hw/pci.c serial.c hw/timer.c clock.c hw/pic.c cdrom.c hw/ps2port.c smp.c resume.c \
+ kbd.c hw/pci.c serial.c hw/timer.c clock.c hw/pic.c cdrom.c hw/ps2port.c fw/smp.c resume.c \
pnpbios.c vgahooks.c hw/ramdisk.c pcibios.c hw/blockcmd.c \
hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c hw/usb-hid.c hw/usb-msc.c \
hw/virtio-ring.c hw/virtio-pci.c hw/virtio-blk.c hw/virtio-scsi.c apm.c hw/ahci.c \
hw/usb-uas.c hw/lsi-scsi.c hw/esp-scsi.c hw/megasas.c
SRC16=$(SRCBOTH) system.c disk.c font.c
-SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c pmm.c coreboot.c boot.c \
- acpi.c smm.c mptable.c pirtable.c smbios.c pciinit.c optionroms.c mtrr.c \
- lzmadecode.c bootsplash.c jpeg.c hw/usb-hub.c paravirt.c \
- biostables.c xen.c bmp.c romfile.c csm.c
+SRC32FLAT=$(SRCBOTH) post.c fw/shadow.c memmap.c pmm.c fw/coreboot.c boot.c \
+ fw/acpi.c fw/smm.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/pciinit.c optionroms.c fw/mtrr.c \
+ fw/lzmadecode.c bootsplash.c jpeg.c hw/usb-hub.c fw/paravirt.c \
+ fw/biostables.c fw/xen.c bmp.c romfile.c fw/csm.c
SRC32SEG=util.c output.c hw/pci.c pcibios.c apm.c stacks.c
-DIRS=src src/hw vgasrc
+DIRS=src src/hw src/fw vgasrc
# Default compiler flags
cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
-$(OUT)%.hex: src/%.dsl ./scripts/acpi_extract_preprocess.py ./scripts/acpi_extract.py
+$(OUT)%.hex: %.dsl ./scripts/acpi_extract_preprocess.py ./scripts/acpi_extract.py
@echo " Compiling IASL $@"
$(Q)$(CPP) $(CPPFLAGS) $< -o $(OUT)$*.dsl.i.orig
$(Q)$(PYTHON) ./scripts/acpi_extract_preprocess.py $(OUT)$*.dsl.i.orig > $(OUT)$*.dsl.i
$(Q)$(PYTHON) ./scripts/acpi_extract.py $(OUT)$*.lst > $(OUT)$*.off
$(Q)cat $(OUT)$*.off > $@
-$(OUT)src/acpi.o: $(OUT)acpi-dsdt.hex $(OUT)ssdt-proc.hex $(OUT)ssdt-pcihp.hex $(OUT)ssdt-misc.hex $(OUT)q35-acpi-dsdt.hex
+$(OUT)src/fw/acpi.o: $(OUT)src/fw/acpi-dsdt.hex $(OUT)src/fw/ssdt-proc.hex $(OUT)src/fw/ssdt-pcihp.hex $(OUT)src/fw/ssdt-misc.hex $(OUT)src/fw/q35-acpi-dsdt.hex
################ Kconfig rules
+++ /dev/null
-/** @file
- The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage
- under EFI and Legacy OS boot. This file also includes all the related
- COMPATIBILIY16 structures and defintions.
-
- Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow
- well known naming conventions.
-
- Thunk is the code that switches from 32-bit protected environment into the 16-bit real-mode
- environment. Reverse thunk is the code that does the opposite.
-
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are licensed and made available under
-the terms and conditions of the BSD License that accompanies this distribution.
-The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php.
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
- @par Revision Reference:
- This protocol is defined in Framework for EFI Compatibility Support Module spec
- Version 0.97.
-
-**/
-
-#ifndef _EFI_LEGACY_BIOS_H_
-#define _EFI_LEGACY_BIOS_H_
-
-///
-///
-///
-#pragma pack(1)
-
-typedef UINT8 SERIAL_MODE;
-typedef UINT8 PARALLEL_MODE;
-
-#define EFI_COMPATIBILITY16_TABLE_SIGNATURE SIGNATURE_32 ('I', 'F', 'E', '$')
-
-///
-/// There is a table located within the traditional BIOS in either the 0xF000:xxxx or 0xE000:xxxx
-/// physical address range. It is located on a 16-byte boundary and provides the physical address of the
-/// entry point for the Compatibility16 functions. These functions provide the platform-specific
-/// information that is required by the generic EfiCompatibility code. The functions are invoked via
-/// thunking by using EFI_LEGACY_BIOS_PROTOCOL.FarCall86() with the 32-bit physical
-/// entry point.
-///
-typedef struct {
- ///
- /// The string "$EFI" denotes the start of the EfiCompatibility table. Byte 0 is "I," byte
- /// 1 is "F," byte 2 is "E," and byte 3 is "$" and is normally accessed as a DWORD or UINT32.
- ///
- UINT32 Signature;
-
- ///
- /// The value required such that byte checksum of TableLength equals zero.
- ///
- UINT8 TableChecksum;
-
- ///
- /// The length of this table.
- ///
- UINT8 TableLength;
-
- ///
- /// The major EFI revision for which this table was generated.
- ///
- UINT8 EfiMajorRevision;
-
- ///
- /// The minor EFI revision for which this table was generated.
- ///
- UINT8 EfiMinorRevision;
-
- ///
- /// The major revision of this table.
- ///
- UINT8 TableMajorRevision;
-
- ///
- /// The minor revision of this table.
- ///
- UINT8 TableMinorRevision;
-
- ///
- /// Reserved for future usage.
- ///
- UINT16 Reserved;
-
- ///
- /// The segment of the entry point within the traditional BIOS for Compatibility16 functions.
- ///
- UINT16 Compatibility16CallSegment;
-
- ///
- /// The offset of the entry point within the traditional BIOS for Compatibility16 functions.
- ///
- UINT16 Compatibility16CallOffset;
-
- ///
- /// The segment of the entry point within the traditional BIOS for EfiCompatibility
- /// to invoke the PnP installation check.
- ///
- UINT16 PnPInstallationCheckSegment;
-
- ///
- /// The Offset of the entry point within the traditional BIOS for EfiCompatibility
- /// to invoke the PnP installation check.
- ///
- UINT16 PnPInstallationCheckOffset;
-
- ///
- /// EFI system resources table. Type EFI_SYSTEM_TABLE is defined in the IntelPlatform
- ///Innovation Framework for EFI Driver Execution Environment Core Interface Specification (DXE CIS).
- ///
- UINT32 EfiSystemTable;
-
- ///
- /// The address of an OEM-provided identifier string. The string is null terminated.
- ///
- UINT32 OemIdStringPointer;
-
- ///
- /// The 32-bit physical address where ACPI RSD PTR is stored within the traditional
- /// BIOS. The remained of the ACPI tables are located at their EFI addresses. The size
- /// reserved is the maximum for ACPI 2.0. The EfiCompatibility will fill in the ACPI
- /// RSD PTR with either the ACPI 1.0b or 2.0 values.
- ///
- UINT32 AcpiRsdPtrPointer;
-
- ///
- /// The OEM revision number. Usage is undefined but provided for OEM module usage.
- ///
- UINT16 OemRevision;
-
- ///
- /// The 32-bit physical address where INT15 E820 data is stored within the traditional
- /// BIOS. The EfiCompatibility code will fill in the E820Pointer value and copy the
- /// data to the indicated area.
- ///
- UINT32 E820Pointer;
-
- ///
- /// The length of the E820 data and is filled in by the EfiCompatibility code.
- ///
- UINT32 E820Length;
-
- ///
- /// The 32-bit physical address where the $PIR table is stored in the traditional BIOS.
- /// The EfiCompatibility code will fill in the IrqRoutingTablePointer value and
- /// copy the data to the indicated area.
- ///
- UINT32 IrqRoutingTablePointer;
-
- ///
- /// The length of the $PIR table and is filled in by the EfiCompatibility code.
- ///
- UINT32 IrqRoutingTableLength;
-
- ///
- /// The 32-bit physical address where the MP table is stored in the traditional BIOS.
- /// The EfiCompatibility code will fill in the MpTablePtr value and copy the data
- /// to the indicated area.
- ///
- UINT32 MpTablePtr;
-
- ///
- /// The length of the MP table and is filled in by the EfiCompatibility code.
- ///
- UINT32 MpTableLength;
-
- ///
- /// The segment of the OEM-specific INT table/code.
- ///
- UINT16 OemIntSegment;
-
- ///
- /// The offset of the OEM-specific INT table/code.
- ///
- UINT16 OemIntOffset;
-
- ///
- /// The segment of the OEM-specific 32-bit table/code.
- ///
- UINT16 Oem32Segment;
-
- ///
- /// The offset of the OEM-specific 32-bit table/code.
- ///
- UINT16 Oem32Offset;
-
- ///
- /// The segment of the OEM-specific 16-bit table/code.
- ///
- UINT16 Oem16Segment;
-
- ///
- /// The offset of the OEM-specific 16-bit table/code.
- ///
- UINT16 Oem16Offset;
-
- ///
- /// The segment of the TPM binary passed to 16-bit CSM.
- ///
- UINT16 TpmSegment;
-
- ///
- /// The offset of the TPM binary passed to 16-bit CSM.
- ///
- UINT16 TpmOffset;
-
- ///
- /// A pointer to a string identifying the independent BIOS vendor.
- ///
- UINT32 IbvPointer;
-
- ///
- /// This field is NULL for all systems not supporting PCI Express. This field is the base
- /// value of the start of the PCI Express memory-mapped configuration registers and
- /// must be filled in prior to EfiCompatibility code issuing the Compatibility16 function
- /// Compatibility16InitializeYourself().
- /// Compatibility16InitializeYourself() is defined in Compatability16
- /// Functions.
- ///
- UINT32 PciExpressBase;
-
- ///
- /// Maximum PCI bus number assigned.
- ///
- UINT8 LastPciBus;
-} EFI_COMPATIBILITY16_TABLE;
-
-///
-/// Functions provided by the CSM binary which communicate between the EfiCompatibility
-/// and Compatability16 code.
-///
-/// Inconsistent with the specification here:
-/// The member's name started with "Compatibility16" [defined in Intel Framework
-/// Compatibility Support Module Specification / 0.97 version]
-/// has been changed to "Legacy16" since keeping backward compatible.
-///
-typedef enum {
- ///
- /// Causes the Compatibility16 code to do any internal initialization required.
- /// Input:
- /// AX = Compatibility16InitializeYourself
- /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE
- /// Return:
- /// AX = Return Status codes
- ///
- Legacy16InitializeYourself = 0x0000,
-
- ///
- /// Causes the Compatibility16 BIOS to perform any drive number translations to match the boot sequence.
- /// Input:
- /// AX = Compatibility16UpdateBbs
- /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE
- /// Return:
- /// AX = Returned status codes
- ///
- Legacy16UpdateBbs = 0x0001,
-
- ///
- /// Allows the Compatibility16 code to perform any final actions before booting. The Compatibility16
- /// code is read/write.
- /// Input:
- /// AX = Compatibility16PrepareToBoot
- /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure
- /// Return:
- /// AX = Returned status codes
- ///
- Legacy16PrepareToBoot = 0x0002,
-
- ///
- /// Causes the Compatibility16 BIOS to boot. The Compatibility16 code is Read/Only.
- /// Input:
- /// AX = Compatibility16Boot
- /// Output:
- /// AX = Returned status codes
- ///
- Legacy16Boot = 0x0003,
-
- ///
- /// Allows the Compatibility16 code to get the last device from which a boot was attempted. This is
- /// stored in CMOS and is the priority number of the last attempted boot device.
- /// Input:
- /// AX = Compatibility16RetrieveLastBootDevice
- /// Output:
- /// AX = Returned status codes
- /// BX = Priority number of the boot device.
- ///
- Legacy16RetrieveLastBootDevice = 0x0004,
-
- ///
- /// Allows the Compatibility16 code rehook INT13, INT18, and/or INT19 after dispatching a legacy OpROM.
- /// Input:
- /// AX = Compatibility16DispatchOprom
- /// ES:BX = Pointer to EFI_DISPATCH_OPROM_TABLE
- /// Output:
- /// AX = Returned status codes
- /// BX = Number of non-BBS-compliant devices found. Equals 0 if BBS compliant.
- ///
- Legacy16DispatchOprom = 0x0005,
-
- ///
- /// Finds a free area in the 0xFxxxx or 0xExxxx region of the specified length and returns the address
- /// of that region.
- /// Input:
- /// AX = Compatibility16GetTableAddress
- /// BX = Allocation region
- /// 00 = Allocate from either 0xE0000 or 0xF0000 64 KB blocks.
- /// Bit 0 = 1 Allocate from 0xF0000 64 KB block
- /// Bit 1 = 1 Allocate from 0xE0000 64 KB block
- /// CX = Requested length in bytes.
- /// DX = Required address alignment. Bit mapped. First non-zero bit from the right is the alignment.
- /// Output:
- /// AX = Returned status codes
- /// DS:BX = Address of the region
- ///
- Legacy16GetTableAddress = 0x0006,
-
- ///
- /// Enables the EfiCompatibility module to do any nonstandard processing of keyboard LEDs or state.
- /// Input:
- /// AX = Compatibility16SetKeyboardLeds
- /// CL = LED status.
- /// Bit 0 Scroll Lock 0 = Off
- /// Bit 1 NumLock
- /// Bit 2 Caps Lock
- /// Output:
- /// AX = Returned status codes
- ///
- Legacy16SetKeyboardLeds = 0x0007,
-
- ///
- /// Enables the EfiCompatibility module to install an interrupt handler for PCI mass media devices that
- /// do not have an OpROM associated with them. An example is SATA.
- /// Input:
- /// AX = Compatibility16InstallPciHandler
- /// ES:BX = Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure
- /// Output:
- /// AX = Returned status codes
- ///
- Legacy16InstallPciHandler = 0x0008
-} EFI_COMPATIBILITY_FUNCTIONS;
-
-
-///
-/// EFI_DISPATCH_OPROM_TABLE
-///
-typedef struct {
- UINT16 PnPInstallationCheckSegment; ///< A pointer to the PnpInstallationCheck data structure.
- UINT16 PnPInstallationCheckOffset; ///< A pointer to the PnpInstallationCheck data structure.
- UINT16 OpromSegment; ///< The segment where the OpROM was placed. Offset is assumed to be 3.
- UINT8 PciBus; ///< The PCI bus.
- UINT8 PciDeviceFunction; ///< The PCI device * 0x08 | PCI function.
- UINT8 NumberBbsEntries; ///< The number of valid BBS table entries upon entry and exit. The IBV code may
- ///< increase this number, if BBS-compliant devices also hook INTs in order to force the
- ///< OpROM BIOS Setup to be executed.
- UINT32 BbsTablePointer; ///< A pointer to the BBS table.
- UINT16 RuntimeSegment; ///< The segment where the OpROM can be relocated to. If this value is 0x0000, this
- ///< means that the relocation of this run time code is not supported.
- ///< Inconsistent with specification here:
- ///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version]
- ///< has been changed to "RuntimeSegment" since keeping backward compatible.
-
-} EFI_DISPATCH_OPROM_TABLE;
-
-///
-/// EFI_TO_COMPATIBILITY16_INIT_TABLE
-///
-typedef struct {
- ///
- /// Starting address of memory under 1 MB. The ending address is assumed to be 640 KB or 0x9FFFF.
- ///
- UINT32 BiosLessThan1MB;
-
- ///
- /// The starting address of the high memory block.
- ///
- UINT32 HiPmmMemory;
-
- ///
- /// The length of high memory block.
- ///
- UINT32 HiPmmMemorySizeInBytes;
-
- ///
- /// The segment of the reverse thunk call code.
- ///
- UINT16 ReverseThunkCallSegment;
-
- ///
- /// The offset of the reverse thunk call code.
- ///
- UINT16 ReverseThunkCallOffset;
-
- ///
- /// The number of E820 entries copied to the Compatibility16 BIOS.
- ///
- UINT32 NumberE820Entries;
-
- ///
- /// The amount of usable memory above 1 MB, e.g., E820 type 1 memory.
- ///
- UINT32 OsMemoryAbove1Mb;
-
- ///
- /// The start of thunk code in main memory. Memory cannot be used by BIOS or PMM.
- ///
- UINT32 ThunkStart;
-
- ///
- /// The size of the thunk code.
- ///
- UINT32 ThunkSizeInBytes;
-
- ///
- /// Starting address of memory under 1 MB.
- ///
- UINT32 LowPmmMemory;
-
- ///
- /// The length of low Memory block.
- ///
- UINT32 LowPmmMemorySizeInBytes;
-} EFI_TO_COMPATIBILITY16_INIT_TABLE;
-
-///
-/// DEVICE_PRODUCER_SERIAL.
-///
-typedef struct {
- UINT16 Address; ///< I/O address assigned to the serial port.
- UINT8 Irq; ///< IRQ assigned to the serial port.
- SERIAL_MODE Mode; ///< Mode of serial port. Values are defined below.
-} DEVICE_PRODUCER_SERIAL;
-
-///
-/// DEVICE_PRODUCER_SERIAL's modes.
-///@{
-#define DEVICE_SERIAL_MODE_NORMAL 0x00
-#define DEVICE_SERIAL_MODE_IRDA 0x01
-#define DEVICE_SERIAL_MODE_ASK_IR 0x02
-#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00
-#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10
-///@)
-
-///
-/// DEVICE_PRODUCER_PARALLEL.
-///
-typedef struct {
- UINT16 Address; ///< I/O address assigned to the parallel port.
- UINT8 Irq; ///< IRQ assigned to the parallel port.
- UINT8 Dma; ///< DMA assigned to the parallel port.
- PARALLEL_MODE Mode; ///< Mode of the parallel port. Values are defined below.
-} DEVICE_PRODUCER_PARALLEL;
-
-///
-/// DEVICE_PRODUCER_PARALLEL's modes.
-///@{
-#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00
-#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01
-#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02
-#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03
-///@}
-
-///
-/// DEVICE_PRODUCER_FLOPPY
-///
-typedef struct {
- UINT16 Address; ///< I/O address assigned to the floppy.
- UINT8 Irq; ///< IRQ assigned to the floppy.
- UINT8 Dma; ///< DMA assigned to the floppy.
- UINT8 NumberOfFloppy; ///< Number of floppies in the system.
-} DEVICE_PRODUCER_FLOPPY;
-
-///
-/// LEGACY_DEVICE_FLAGS
-///
-typedef struct {
- UINT32 A20Kybd : 1; ///< A20 controller by keyboard controller.
- UINT32 A20Port90 : 1; ///< A20 controlled by port 0x92.
- UINT32 Reserved : 30; ///< Reserved for future usage.
-} LEGACY_DEVICE_FLAGS;
-
-///
-/// DEVICE_PRODUCER_DATA_HEADER
-///
-typedef struct {
- DEVICE_PRODUCER_SERIAL Serial[4]; ///< Data for serial port x. Type DEVICE_PRODUCER_SERIAL is defined below.
- DEVICE_PRODUCER_PARALLEL Parallel[3]; ///< Data for parallel port x. Type DEVICE_PRODUCER_PARALLEL is defined below.
- DEVICE_PRODUCER_FLOPPY Floppy; ///< Data for floppy. Type DEVICE_PRODUCER_FLOPPY is defined below.
- UINT8 MousePresent; ///< Flag to indicate if mouse is present.
- LEGACY_DEVICE_FLAGS Flags; ///< Miscellaneous Boolean state information passed to CSM.
-} DEVICE_PRODUCER_DATA_HEADER;
-
-///
-/// ATAPI_IDENTIFY
-///
-typedef struct {
- UINT16 Raw[256]; ///< Raw data from the IDE IdentifyDrive command.
-} ATAPI_IDENTIFY;
-
-///
-/// HDD_INFO
-///
-typedef struct {
- ///
- /// Status of IDE device. Values are defined below. There is one HDD_INFO structure
- /// per IDE controller. The IdentifyDrive is per drive. Index 0 is master and index
- /// 1 is slave.
- ///
- UINT16 Status;
-
- ///
- /// PCI bus of IDE controller.
- ///
- UINT32 Bus;
-
- ///
- /// PCI device of IDE controller.
- ///
- UINT32 Device;
-
- ///
- /// PCI function of IDE controller.
- ///
- UINT32 Function;
-
- ///
- /// Command ports base address.
- ///
- UINT16 CommandBaseAddress;
-
- ///
- /// Control ports base address.
- ///
- UINT16 ControlBaseAddress;
-
- ///
- /// Bus master address.
- ///
- UINT16 BusMasterAddress;
-
- UINT8 HddIrq;
-
- ///
- /// Data that identifies the drive data; one per possible attached drive.
- ///
- ATAPI_IDENTIFY IdentifyDrive[2];
-} HDD_INFO;
-
-///
-/// HDD_INFO status bits
-///
-#define HDD_PRIMARY 0x01
-#define HDD_SECONDARY 0x02
-#define HDD_MASTER_ATAPI_CDROM 0x04
-#define HDD_SLAVE_ATAPI_CDROM 0x08
-#define HDD_MASTER_IDE 0x20
-#define HDD_SLAVE_IDE 0x40
-#define HDD_MASTER_ATAPI_ZIPDISK 0x10
-#define HDD_SLAVE_ATAPI_ZIPDISK 0x80
-
-///
-/// BBS_STATUS_FLAGS;\.
-///
-typedef struct {
- UINT16 OldPosition : 4; ///< Prior priority.
- UINT16 Reserved1 : 4; ///< Reserved for future use.
- UINT16 Enabled : 1; ///< If 0, ignore this entry.
- UINT16 Failed : 1; ///< 0 = Not known if boot failure occurred.
- ///< 1 = Boot attempted failed.
-
- ///
- /// State of media present.
- /// 00 = No bootable media is present in the device.
- /// 01 = Unknown if a bootable media present.
- /// 10 = Media is present and appears bootable.
- /// 11 = Reserved.
- ///
- UINT16 MediaPresent : 2;
- UINT16 Reserved2 : 4; ///< Reserved for future use.
-} BBS_STATUS_FLAGS;
-
-///
-/// BBS_TABLE, device type values & boot priority values.
-///
-typedef struct {
- ///
- /// The boot priority for this boot device. Values are defined below.
- ///
- UINT16 BootPriority;
-
- ///
- /// The PCI bus for this boot device.
- ///
- UINT32 Bus;
-
- ///
- /// The PCI device for this boot device.
- ///
- UINT32 Device;
-
- ///
- /// The PCI function for the boot device.
- ///
- UINT32 Function;
-
- ///
- /// The PCI class for this boot device.
- ///
- UINT8 Class;
-
- ///
- /// The PCI Subclass for this boot device.
- ///
- UINT8 SubClass;
-
- ///
- /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
- ///
- UINT16 MfgStringOffset;
-
- ///
- /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
- ///
- UINT16 MfgStringSegment;
-
- ///
- /// BBS device type. BBS device types are defined below.
- ///
- UINT16 DeviceType;
-
- ///
- /// Status of this boot device. Type BBS_STATUS_FLAGS is defined below.
- ///
- BBS_STATUS_FLAGS StatusFlags;
-
- ///
- /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
- /// BCV devices.
- ///
- UINT16 BootHandlerOffset;
-
- ///
- /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
- /// BCV devices.
- ///
- UINT16 BootHandlerSegment;
-
- ///
- /// Segment:offset address of an ASCIIZ description string describing this device.
- ///
- UINT16 DescStringOffset;
-
- ///
- /// Segment:offset address of an ASCIIZ description string describing this device.
- ///
- UINT16 DescStringSegment;
-
- ///
- /// Reserved.
- ///
- UINT32 InitPerReserved;
-
- ///
- /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
- /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
- /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
- ///
- UINT32 AdditionalIrq13Handler;
-
- ///
- /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
- /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
- /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
- ///
- UINT32 AdditionalIrq18Handler;
-
- ///
- /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
- /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
- /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
- ///
- UINT32 AdditionalIrq19Handler;
-
- ///
- /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
- /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
- /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
- ///
- UINT32 AdditionalIrq40Handler;
- UINT8 AssignedDriveNumber;
- UINT32 AdditionalIrq41Handler;
- UINT32 AdditionalIrq46Handler;
- UINT32 IBV1;
- UINT32 IBV2;
-} BBS_TABLE;
-
-///
-/// BBS device type values
-///@{
-#define BBS_FLOPPY 0x01
-#define BBS_HARDDISK 0x02
-#define BBS_CDROM 0x03
-#define BBS_PCMCIA 0x04
-#define BBS_USB 0x05
-#define BBS_EMBED_NETWORK 0x06
-#define BBS_BEV_DEVICE 0x80
-#define BBS_UNKNOWN 0xff
-///@}
-
-///
-/// BBS boot priority values
-///@{
-#define BBS_DO_NOT_BOOT_FROM 0xFFFC
-#define BBS_LOWEST_PRIORITY 0xFFFD
-#define BBS_UNPRIORITIZED_ENTRY 0xFFFE
-#define BBS_IGNORE_ENTRY 0xFFFF
-///@}
-
-///
-/// SMM_ATTRIBUTES
-///
-typedef struct {
- ///
- /// Access mechanism used to generate the soft SMI. Defined types are below. The other
- /// values are reserved for future usage.
- ///
- UINT16 Type : 3;
-
- ///
- /// The size of "port" in bits. Defined values are below.
- ///
- UINT16 PortGranularity : 3;
-
- ///
- /// The size of data in bits. Defined values are below.
- ///
- UINT16 DataGranularity : 3;
-
- ///
- /// Reserved for future use.
- ///
- UINT16 Reserved : 7;
-} SMM_ATTRIBUTES;
-
-///
-/// SMM_ATTRIBUTES type values.
-///@{
-#define STANDARD_IO 0x00
-#define STANDARD_MEMORY 0x01
-///@}
-
-///
-/// SMM_ATTRIBUTES port size constants.
-///@{
-#define PORT_SIZE_8 0x00
-#define PORT_SIZE_16 0x01
-#define PORT_SIZE_32 0x02
-#define PORT_SIZE_64 0x03
-///@}
-
-///
-/// SMM_ATTRIBUTES data size constants.
-///@{
-#define DATA_SIZE_8 0x00
-#define DATA_SIZE_16 0x01
-#define DATA_SIZE_32 0x02
-#define DATA_SIZE_64 0x03
-///@}
-
-///
-/// SMM_FUNCTION & relating constants.
-///
-typedef struct {
- UINT16 Function : 15;
- UINT16 Owner : 1;
-} SMM_FUNCTION;
-
-///
-/// SMM_FUNCTION Function constants.
-///@{
-#define INT15_D042 0x0000
-#define GET_USB_BOOT_INFO 0x0001
-#define DMI_PNP_50_57 0x0002
-///@}
-
-///
-/// SMM_FUNCTION Owner constants.
-///@{
-#define STANDARD_OWNER 0x0
-#define OEM_OWNER 0x1
-///@}
-
-///
-/// This structure assumes both port and data sizes are 1. SmmAttribute must be
-/// properly to reflect that assumption.
-///
-typedef struct {
- ///
- /// Describes the access mechanism, SmmPort, and SmmData sizes. Type
- /// SMM_ATTRIBUTES is defined below.
- ///
- SMM_ATTRIBUTES SmmAttributes;
-
- ///
- /// Function Soft SMI is to perform. Type SMM_FUNCTION is defined below.
- ///
- SMM_FUNCTION SmmFunction;
-
- ///
- /// SmmPort size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
- ///
- UINT8 SmmPort;
-
- ///
- /// SmmData size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
- ///
- UINT8 SmmData;
-} SMM_ENTRY;
-
-///
-/// SMM_TABLE
-///
-typedef struct {
- UINT16 NumSmmEntries; ///< Number of entries represented by SmmEntry.
- SMM_ENTRY SmmEntry; ///< One entry per function. Type SMM_ENTRY is defined below.
-} SMM_TABLE;
-
-///
-/// UDC_ATTRIBUTES
-///
-typedef struct {
- ///
- /// This bit set indicates that the ServiceAreaData is valid.
- ///
- UINT8 DirectoryServiceValidity : 1;
-
- ///
- /// This bit set indicates to use the Reserve Area Boot Code Address (RACBA) only if
- /// DirectoryServiceValidity is 0.
- ///
- UINT8 RabcaUsedFlag : 1;
-
- ///
- /// This bit set indicates to execute hard disk diagnostics.
- ///
- UINT8 ExecuteHddDiagnosticsFlag : 1;
-
- ///
- /// Reserved for future use. Set to 0.
- ///
- UINT8 Reserved : 5;
-} UDC_ATTRIBUTES;
-
-///
-/// UD_TABLE
-///
-typedef struct {
- ///
- /// This field contains the bit-mapped attributes of the PARTIES information. Type
- /// UDC_ATTRIBUTES is defined below.
- ///
- UDC_ATTRIBUTES Attributes;
-
- ///
- /// This field contains the zero-based device on which the selected
- /// ServiceDataArea is present. It is 0 for master and 1 for the slave device.
- ///
- UINT8 DeviceNumber;
-
- ///
- /// This field contains the zero-based index into the BbsTable for the parent device.
- /// This index allows the user to reference the parent device information such as PCI
- /// bus, device function.
- ///
- UINT8 BbsTableEntryNumberForParentDevice;
-
- ///
- /// This field contains the zero-based index into the BbsTable for the boot entry.
- ///
- UINT8 BbsTableEntryNumberForBoot;
-
- ///
- /// This field contains the zero-based index into the BbsTable for the HDD diagnostics entry.
- ///
- UINT8 BbsTableEntryNumberForHddDiag;
-
- ///
- /// The raw Beer data.
- ///
- UINT8 BeerData[128];
-
- ///
- /// The raw data of selected service area.
- ///
- UINT8 ServiceAreaData[64];
-} UD_TABLE;
-
-#define EFI_TO_LEGACY_MAJOR_VERSION 0x02
-#define EFI_TO_LEGACY_MINOR_VERSION 0x00
-#define MAX_IDE_CONTROLLER 8
-
-///
-/// EFI_TO_COMPATIBILITY16_BOOT_TABLE
-///
-typedef struct {
- UINT16 MajorVersion; ///< The EfiCompatibility major version number.
- UINT16 MinorVersion; ///< The EfiCompatibility minor version number.
- UINT32 AcpiTable; ///< The location of the RSDT ACPI table. < 4G range.
- UINT32 SmbiosTable; ///< The location of the SMBIOS table in EFI memory. < 4G range.
- UINT32 SmbiosTableLength;
- //
- // Legacy SIO state
- //
- DEVICE_PRODUCER_DATA_HEADER SioData; ///< Standard traditional device information.
- UINT16 DevicePathType; ///< The default boot type.
- UINT16 PciIrqMask; ///< Mask of which IRQs have been assigned to PCI.
- UINT32 NumberE820Entries; ///< Number of E820 entries. The number can change from the
- ///< Compatibility16InitializeYourself() function.
- //
- // Controller & Drive Identify[2] per controller information
- //
- HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; ///< Hard disk drive information, including raw Identify Drive data.
- UINT32 NumberBbsEntries; ///< Number of entries in the BBS table
- UINT32 BbsTable; ///< A pointer to the BBS table. Type BBS_TABLE is defined below.
- UINT32 SmmTable; ///< A pointer to the SMM table. Type SMM_TABLE is defined below.
- UINT32 OsMemoryAbove1Mb; ///< The amount of usable memory above 1 MB, i.e. E820 type 1 memory. This value can
- ///< differ from the value in EFI_TO_COMPATIBILITY16_INIT_TABLE as more
- ///< memory may have been discovered.
- UINT32 UnconventionalDeviceTable; ///< Information to boot off an unconventional device like a PARTIES partition. Type
- ///< UD_TABLE is defined below.
-} EFI_TO_COMPATIBILITY16_BOOT_TABLE;
-
-///
-/// EFI_LEGACY_INSTALL_PCI_HANDLER
-///
-typedef struct {
- UINT8 PciBus; ///< The PCI bus of the device.
- UINT8 PciDeviceFun; ///< The PCI device in bits 7:3 and function in bits 2:0.
- UINT8 PciSegment; ///< The PCI segment of the device.
- UINT8 PciClass; ///< The PCI class code of the device.
- UINT8 PciSubclass; ///< The PCI subclass code of the device.
- UINT8 PciInterface; ///< The PCI interface code of the device.
- //
- // Primary section
- //
- UINT8 PrimaryIrq; ///< The primary device IRQ.
- UINT8 PrimaryReserved; ///< Reserved.
- UINT16 PrimaryControl; ///< The primary device control I/O base.
- UINT16 PrimaryBase; ///< The primary device I/O base.
- UINT16 PrimaryBusMaster; ///< The primary device bus master I/O base.
- //
- // Secondary Section
- //
- UINT8 SecondaryIrq; ///< The secondary device IRQ.
- UINT8 SecondaryReserved; ///< Reserved.
- UINT16 SecondaryControl; ///< The secondary device control I/O base.
- UINT16 SecondaryBase; ///< The secondary device I/O base.
- UINT16 SecondaryBusMaster; ///< The secondary device bus master I/O base.
-} EFI_LEGACY_INSTALL_PCI_HANDLER;
-
-#endif
+++ /dev/null
-/****************************************************************
- * CPU hotplug
- ****************************************************************/
-
-Scope(\_SB) {
- /* Objects filled in by run-time generated SSDT */
- External(NTFY, MethodObj)
- External(CPON, PkgObj)
-
- /* Methods called by run-time generated SSDT Processor objects */
- Method(CPMA, 1, NotSerialized) {
- // _MAT method - create an madt apic buffer
- // Arg0 = Processor ID = Local APIC ID
- // Local0 = CPON flag for this cpu
- Store(DerefOf(Index(CPON, Arg0)), Local0)
- // Local1 = Buffer (in madt apic form) to return
- Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
- // Update the processor id, lapic id, and enable/disable status
- Store(Arg0, Index(Local1, 2))
- Store(Arg0, Index(Local1, 3))
- Store(Local0, Index(Local1, 4))
- Return (Local1)
- }
- Method(CPST, 1, NotSerialized) {
- // _STA method - return ON status of cpu
- // Arg0 = Processor ID = Local APIC ID
- // Local0 = CPON flag for this cpu
- Store(DerefOf(Index(CPON, Arg0)), Local0)
- If (Local0) {
- Return (0xF)
- } Else {
- Return (0x0)
- }
- }
- Method(CPEJ, 2, NotSerialized) {
- // _EJ0 method - eject callback
- Sleep(200)
- }
-
- /* CPU hotplug notify method */
- OperationRegion(PRST, SystemIO, 0xaf00, 32)
- Field(PRST, ByteAcc, NoLock, Preserve) {
- PRS, 256
- }
- Method(PRSC, 0) {
- // Local5 = active cpu bitmap
- Store(PRS, Local5)
- // Local2 = last read byte from bitmap
- Store(Zero, Local2)
- // Local0 = Processor ID / APIC ID iterator
- Store(Zero, Local0)
- While (LLess(Local0, SizeOf(CPON))) {
- // Local1 = CPON flag for this cpu
- Store(DerefOf(Index(CPON, Local0)), Local1)
- If (And(Local0, 0x07)) {
- // Shift down previously read bitmap byte
- ShiftRight(Local2, 1, Local2)
- } Else {
- // Read next byte from cpu bitmap
- Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
- }
- // Local3 = active state for this cpu
- Store(And(Local2, 1), Local3)
-
- If (LNotEqual(Local1, Local3)) {
- // State change - update CPON with new state
- Store(Local3, Index(CPON, Local0))
- // Do CPU notify
- If (LEqual(Local3, 1)) {
- NTFY(Local0, 1)
- } Else {
- NTFY(Local0, 3)
- }
- }
- Increment(Local0)
- }
- }
-}
+++ /dev/null
-/****************************************************************
- * Debugging
- ****************************************************************/
-
-Scope(\) {
- /* Debug Output */
- OperationRegion(DBG, SystemIO, 0x0402, 0x01)
- Field(DBG, ByteAcc, NoLock, Preserve) {
- DBGB, 8,
- }
-
- /* Debug method - use this method to send output to the QEMU
- * BIOS debug port. This method handles strings, integers,
- * and buffers. For example: DBUG("abc") DBUG(0x123) */
- Method(DBUG, 1) {
- ToHexString(Arg0, Local0)
- ToBuffer(Local0, Local0)
- Subtract(SizeOf(Local0), 1, Local1)
- Store(Zero, Local2)
- While (LLess(Local2, Local1)) {
- Store(DerefOf(Index(Local0, Local2)), DBGB)
- Increment(Local2)
- }
- Store(0x0A, DBGB)
- }
-}
+++ /dev/null
-/****************************************************************
- * HPET
- ****************************************************************/
-
-Scope(\_SB) {
- Device(HPET) {
- Name(_HID, EISAID("PNP0103"))
- Name(_UID, 0)
- OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
- Field(HPTM, DWordAcc, Lock, Preserve) {
- VEND, 32,
- PRD, 32,
- }
- Method(_STA, 0, NotSerialized) {
- Store(VEND, Local0)
- Store(PRD, Local1)
- ShiftRight(Local0, 16, Local0)
- If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
- Return (0x0)
- }
- If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
- Return (0x0)
- }
- Return (0x0F)
- }
- Name(_CRS, ResourceTemplate() {
-#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
- IRQNoFlags() {2, 8}
-#endif
- Memory32Fixed(ReadOnly,
- 0xFED00000, // Address Base
- 0x00000400, // Address Length
- )
- })
- }
-}
+++ /dev/null
-/* Common legacy ISA style devices. */
-Scope(\_SB.PCI0.ISA) {
-
- Device(RTC) {
- Name(_HID, EisaId("PNP0B00"))
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
- IRQNoFlags() { 8 }
- IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
- })
- }
-
- Device(KBD) {
- Name(_HID, EisaId("PNP0303"))
- Method(_STA, 0, NotSerialized) {
- Return (0x0f)
- }
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
- IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
- IRQNoFlags() { 1 }
- })
- }
-
- Device(MOU) {
- Name(_HID, EisaId("PNP0F13"))
- Method(_STA, 0, NotSerialized) {
- Return (0x0f)
- }
- Name(_CRS, ResourceTemplate() {
- IRQNoFlags() { 12 }
- })
- }
-
- Device(FDC0) {
- Name(_HID, EisaId("PNP0700"))
- Method(_STA, 0, NotSerialized) {
- Store(FDEN, Local0)
- If (LEqual(Local0, 0)) {
- Return (0x00)
- } Else {
- Return (0x0F)
- }
- }
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
- IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
- IRQNoFlags() { 6 }
- DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
- })
- }
-
- Device(LPT) {
- Name(_HID, EisaId("PNP0400"))
- Method(_STA, 0, NotSerialized) {
- Store(LPEN, Local0)
- If (LEqual(Local0, 0)) {
- Return (0x00)
- } Else {
- Return (0x0F)
- }
- }
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
- IRQNoFlags() { 7 }
- })
- }
-
- Device(COM1) {
- Name(_HID, EisaId("PNP0501"))
- Name(_UID, 0x01)
- Method(_STA, 0, NotSerialized) {
- Store(CAEN, Local0)
- If (LEqual(Local0, 0)) {
- Return (0x00)
- } Else {
- Return (0x0F)
- }
- }
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
- IRQNoFlags() { 4 }
- })
- }
-
- Device(COM2) {
- Name(_HID, EisaId("PNP0501"))
- Name(_UID, 0x02)
- Method(_STA, 0, NotSerialized) {
- Store(CBEN, Local0)
- If (LEqual(Local0, 0)) {
- Return (0x00)
- } Else {
- Return (0x0F)
- }
- }
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
- IRQNoFlags() { 3 }
- })
- }
-}
+++ /dev/null
-/* PCI CRS (current resources) definition. */
-Scope(\_SB.PCI0) {
-
- Name(CRES, ResourceTemplate() {
- WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x00FF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0100, // Address Length
- ,, )
- IO(Decode16,
- 0x0CF8, // Address Range Minimum
- 0x0CF8, // Address Range Maximum
- 0x01, // Address Alignment
- 0x08, // Address Length
- )
- WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x0CF7, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0CF8, // Address Length
- ,, , TypeStatic)
- WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0D00, // Address Range Minimum
- 0xFFFF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0xF300, // Address Length
- ,, , TypeStatic)
- DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x000A0000, // Address Range Minimum
- 0x000BFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x00020000, // Address Length
- ,, , AddressRangeMemory, TypeStatic)
- DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0xE0000000, // Address Range Minimum
- 0xFEBFFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x1EC00000, // Address Length
- ,, PW32, AddressRangeMemory, TypeStatic)
- })
-
- Name(CR64, ResourceTemplate() {
- QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x8000000000, // Address Range Minimum
- 0xFFFFFFFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x8000000000, // Address Length
- ,, PW64, AddressRangeMemory, TypeStatic)
- })
-
- Method(_CRS, 0) {
- /* Fields provided by dynamically created ssdt */
- External(P0S, IntObj)
- External(P0E, IntObj)
- External(P1V, IntObj)
- External(P1S, BuffObj)
- External(P1E, BuffObj)
- External(P1L, BuffObj)
-
- /* fixup 32bit pci io window */
- CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
- CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
- CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
- Store(P0S, PS32)
- Store(P0E, PE32)
- Store(Add(Subtract(P0E, P0S), 1), PL32)
-
- If (LEqual(P1V, Zero)) {
- Return (CRES)
- }
-
- /* fixup 64bit pci io window */
- CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
- CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
- CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
- Store(P1S, PS64)
- Store(P1E, PE64)
- Store(P1L, PL64)
- /* add window and return result */
- ConcatenateResTemplate(CRES, CR64, Local0)
- Return (Local0)
- }
-}
+++ /dev/null
-/*
- * Bochs/QEMU ACPI DSDT ASL definition
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-ACPI_EXTRACT_ALL_CODE AmlCode
-
-DefinitionBlock (
- "acpi-dsdt.aml", // Output Filename
- "DSDT", // Signature
- 0x01, // DSDT Compliance Revision
- "BXPC", // OEMID
- "BXDSDT", // TABLE ID
- 0x1 // OEM Revision
- )
-{
-
-#include "acpi-dsdt-dbug.dsl"
-
-
-/****************************************************************
- * PCI Bus definition
- ****************************************************************/
-
- Scope(\_SB) {
- Device(PCI0) {
- Name(_HID, EisaId("PNP0A03"))
- Name(_ADR, 0x00)
- Name(_UID, 1)
- }
- }
-
-#include "acpi-dsdt-pci-crs.dsl"
-#include "acpi-dsdt-hpet.dsl"
-
-
-/****************************************************************
- * VGA
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- Device(VGA) {
- Name(_ADR, 0x00020000)
- OperationRegion(PCIC, PCI_Config, Zero, 0x4)
- Field(PCIC, DWordAcc, NoLock, Preserve) {
- VEND, 32
- }
- Method(_S1D, 0, NotSerialized) {
- Return (0x00)
- }
- Method(_S2D, 0, NotSerialized) {
- Return (0x00)
- }
- Method(_S3D, 0, NotSerialized) {
- If (LEqual(VEND, 0x1001b36)) {
- Return (0x03) // QXL
- } Else {
- Return (0x00)
- }
- }
- }
- }
-
-
-/****************************************************************
- * PIIX4 PM
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- Device(PX13) {
- Name(_ADR, 0x00010003)
- OperationRegion(P13C, PCI_Config, 0x00, 0xff)
- }
- }
-
-
-/****************************************************************
- * PIIX3 ISA bridge
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- Device(ISA) {
- Name(_ADR, 0x00010000)
-
- /* PIIX PCI to ISA irq remapping */
- OperationRegion(P40C, PCI_Config, 0x60, 0x04)
-
- /* enable bits */
- Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
- Offset(0x5f),
- , 7,
- LPEN, 1, // LPT
- Offset(0x67),
- , 3,
- CAEN, 1, // COM1
- , 3,
- CBEN, 1, // COM2
- }
- Name(FDEN, 1)
- }
- }
-
-#include "acpi-dsdt-isa.dsl"
-
-
-/****************************************************************
- * PCI hotplug
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- OperationRegion(PCST, SystemIO, 0xae00, 0x08)
- Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
- PCIU, 32,
- PCID, 32,
- }
-
- OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
- Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
- B0EJ, 32,
- }
-
- /* Methods called by bulk generated PCI devices below */
-
- /* Methods called by hotplug devices */
- Method(PCEJ, 1, NotSerialized) {
- // _EJ0 method - eject callback
- Store(ShiftLeft(1, Arg0), B0EJ)
- Return (0x0)
- }
-
- /* Hotplug notification method supplied by SSDT */
- External(\_SB.PCI0.PCNT, MethodObj)
-
- /* PCI hotplug notify method */
- Method(PCNF, 0) {
- // Local0 = iterator
- Store(Zero, Local0)
- While (LLess(Local0, 31)) {
- Increment(Local0)
- If (And(PCIU, ShiftLeft(1, Local0))) {
- PCNT(Local0, 1)
- }
- If (And(PCID, ShiftLeft(1, Local0))) {
- PCNT(Local0, 3)
- }
- }
- }
- }
-
-
-/****************************************************************
- * PCI IRQs
- ****************************************************************/
-
- Scope(\_SB) {
- Scope(PCI0) {
- Name(_PRT, Package() {
- /* PCI IRQ routing table, example from ACPI 2.0a specification,
- section 6.2.8.1 */
- /* Note: we provide the same info as the PCI routing
- table of the Bochs BIOS */
-
-#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
- Package() { nr##ffff, 0, lnk0, 0 }, \
- Package() { nr##ffff, 1, lnk1, 0 }, \
- Package() { nr##ffff, 2, lnk2, 0 }, \
- Package() { nr##ffff, 3, lnk3, 0 }
-
-#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
-#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
-#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
-#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
-
- prt_slot0(0x0000),
- /* Device 1 is power mgmt device, and can only use irq 9 */
- prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
- prt_slot2(0x0002),
- prt_slot3(0x0003),
- prt_slot0(0x0004),
- prt_slot1(0x0005),
- prt_slot2(0x0006),
- prt_slot3(0x0007),
- prt_slot0(0x0008),
- prt_slot1(0x0009),
- prt_slot2(0x000a),
- prt_slot3(0x000b),
- prt_slot0(0x000c),
- prt_slot1(0x000d),
- prt_slot2(0x000e),
- prt_slot3(0x000f),
- prt_slot0(0x0010),
- prt_slot1(0x0011),
- prt_slot2(0x0012),
- prt_slot3(0x0013),
- prt_slot0(0x0014),
- prt_slot1(0x0015),
- prt_slot2(0x0016),
- prt_slot3(0x0017),
- prt_slot0(0x0018),
- prt_slot1(0x0019),
- prt_slot2(0x001a),
- prt_slot3(0x001b),
- prt_slot0(0x001c),
- prt_slot1(0x001d),
- prt_slot2(0x001e),
- prt_slot3(0x001f),
- })
- }
-
- Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
- PRQ0, 8,
- PRQ1, 8,
- PRQ2, 8,
- PRQ3, 8
- }
-
- Method(IQST, 1, NotSerialized) {
- // _STA method - get status
- If (And(0x80, Arg0)) {
- Return (0x09)
- }
- Return (0x0B)
- }
- Method(IQCR, 1, NotSerialized) {
- // _CRS method - get current settings
- Name(PRR0, ResourceTemplate() {
- Interrupt(, Level, ActiveHigh, Shared) { 0 }
- })
- CreateDWordField(PRR0, 0x05, PRRI)
- If (LLess(Arg0, 0x80)) {
- Store(Arg0, PRRI)
- }
- Return (PRR0)
- }
-
-#define define_link(link, uid, reg) \
- Device(link) { \
- Name(_HID, EISAID("PNP0C0F")) \
- Name(_UID, uid) \
- Name(_PRS, ResourceTemplate() { \
- Interrupt(, Level, ActiveHigh, Shared) { \
- 5, 10, 11 \
- } \
- }) \
- Method(_STA, 0, NotSerialized) { \
- Return (IQST(reg)) \
- } \
- Method(_DIS, 0, NotSerialized) { \
- Or(reg, 0x80, reg) \
- } \
- Method(_CRS, 0, NotSerialized) { \
- Return (IQCR(reg)) \
- } \
- Method(_SRS, 1, NotSerialized) { \
- CreateDWordField(Arg0, 0x05, PRRI) \
- Store(PRRI, reg) \
- } \
- }
-
- define_link(LNKA, 0, PRQ0)
- define_link(LNKB, 1, PRQ1)
- define_link(LNKC, 2, PRQ2)
- define_link(LNKD, 3, PRQ3)
-
- Device(LNKS) {
- Name(_HID, EISAID("PNP0C0F"))
- Name(_UID, 4)
- Name(_PRS, ResourceTemplate() {
- Interrupt(, Level, ActiveHigh, Shared) { 9 }
- })
-
- // The SCI cannot be disabled and is always attached to GSI 9,
- // so these are no-ops. We only need this link to override the
- // polarity to active high and match the content of the MADT.
- Method(_STA, 0, NotSerialized) { Return (0x0b) }
- Method(_DIS, 0, NotSerialized) { }
- Method(_CRS, 0, NotSerialized) { Return (_PRS) }
- Method(_SRS, 1, NotSerialized) { }
- }
- }
-
-#include "acpi-dsdt-cpu-hotplug.dsl"
-
-
-/****************************************************************
- * General purpose events
- ****************************************************************/
-
- Scope(\_GPE) {
- Name(_HID, "ACPI0006")
-
- Method(_L00) {
- }
- Method(_E01) {
- // PCI hotplug event
- \_SB.PCI0.PCNF()
- }
- Method(_E02) {
- // CPU hotplug event
- \_SB.PRSC()
- }
- Method(_L03) {
- }
- Method(_L04) {
- }
- Method(_L05) {
- }
- Method(_L06) {
- }
- Method(_L07) {
- }
- Method(_L08) {
- }
- Method(_L09) {
- }
- Method(_L0A) {
- }
- Method(_L0B) {
- }
- Method(_L0C) {
- }
- Method(_L0D) {
- }
- Method(_L0E) {
- }
- Method(_L0F) {
- }
- }
-}
+++ /dev/null
-// Support for generating ACPI tables (on emulators)
-//
-// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "acpi.h" // struct rsdp_descriptor
-#include "util.h" // memcpy
-#include "byteorder.h" // cpu_to_le16
-#include "hw/pci.h" // pci_find_init_device
-#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "hw/pci_regs.h" // PCI_INTERRUPT_LINE
-#include "ioport.h" // inl
-#include "config.h" // CONFIG_*
-#include "paravirt.h" // RamSize
-#include "dev-q35.h"
-
-#include "acpi-dsdt.hex"
-
-u32 acpi_pm1a_cnt VARFSEG;
-
-static void
-build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
-{
- h->signature = cpu_to_le32(sig);
- h->length = cpu_to_le32(len);
- h->revision = rev;
- memcpy(h->oem_id, BUILD_APPNAME6, 6);
- memcpy(h->oem_table_id, BUILD_APPNAME4, 4);
- memcpy(h->oem_table_id + 4, (void*)&sig, 4);
- h->oem_revision = cpu_to_le32(1);
- memcpy(h->asl_compiler_id, BUILD_APPNAME4, 4);
- h->asl_compiler_revision = cpu_to_le32(1);
- h->checksum -= checksum(h, len);
-}
-
-#define PIIX4_ACPI_ENABLE 0xf1
-#define PIIX4_ACPI_DISABLE 0xf0
-#define PIIX4_GPE0_BLK 0xafe0
-#define PIIX4_GPE0_BLK_LEN 4
-
-#define PIIX4_PM_INTRRUPT 9 // irq 9
-
-static void piix4_fadt_setup(struct pci_device *pci, void *arg)
-{
- struct fadt_descriptor_rev1 *fadt = arg;
-
- fadt->model = 1;
- fadt->reserved1 = 0;
- fadt->sci_int = cpu_to_le16(PIIX4_PM_INTRRUPT);
- fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
- fadt->acpi_enable = PIIX4_ACPI_ENABLE;
- fadt->acpi_disable = PIIX4_ACPI_DISABLE;
- fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
- fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
- fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
- fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK);
- fadt->pm1_evt_len = 4;
- fadt->pm1_cnt_len = 2;
- fadt->pm_tmr_len = 4;
- fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN;
- fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
- fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
- /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) |
- (1 << 15));
-}
-
-/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
-void ich9_lpc_fadt_setup(struct pci_device *dev, void *arg)
-{
- struct fadt_descriptor_rev1 *fadt = arg;
-
- fadt->model = 1;
- fadt->reserved1 = 0;
- fadt->sci_int = cpu_to_le16(9);
- fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
- fadt->acpi_enable = ICH9_ACPI_ENABLE;
- fadt->acpi_disable = ICH9_ACPI_DISABLE;
- fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
- fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
- fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
- fadt->gpe0_blk = cpu_to_le32(PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS);
- fadt->pm1_evt_len = 4;
- fadt->pm1_cnt_len = 2;
- fadt->pm_tmr_len = 4;
- fadt->gpe0_blk_len = ICH9_PMIO_GPE0_BLK_LEN;
- fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
- fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
- /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) |
- (1 << 15));
-}
-
-static const struct pci_device_id fadt_init_tbl[] = {
- /* PIIX4 Power Management device (for ACPI) */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
- piix4_fadt_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
- ich9_lpc_fadt_setup),
- PCI_DEVICE_END
-};
-
-static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt)
-{
- if (fadt->dsdt) {
- free((void *)le32_to_cpu(fadt->dsdt));
- }
- fadt->dsdt = cpu_to_le32((u32)dsdt);
- fadt->checksum -= checksum(fadt, sizeof(*fadt));
- dprintf(1, "ACPI DSDT=%p\n", dsdt);
-}
-
-static void *
-build_fadt(struct pci_device *pci)
-{
- struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
- struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
-
- if (!fadt || !facs) {
- warn_noalloc();
- return NULL;
- }
-
- /* FACS */
- memset(facs, 0, sizeof(*facs));
- facs->signature = cpu_to_le32(FACS_SIGNATURE);
- facs->length = cpu_to_le32(sizeof(*facs));
-
- /* FADT */
- memset(fadt, 0, sizeof(*fadt));
- fadt->firmware_ctrl = cpu_to_le32((u32)facs);
- fadt->dsdt = 0; /* dsdt will be filled later in acpi_setup()
- by fill_dsdt() */
- pci_init_device(fadt_init_tbl, pci, fadt);
-
- build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1);
-
- return fadt;
-}
-
-static void*
-build_madt(void)
-{
- int madt_size = (sizeof(struct multiple_apic_table)
- + sizeof(struct madt_processor_apic) * MaxCountCPUs
- + sizeof(struct madt_io_apic)
- + sizeof(struct madt_intsrcovr) * 16
- + sizeof(struct madt_local_nmi));
-
- struct multiple_apic_table *madt = malloc_high(madt_size);
- if (!madt) {
- warn_noalloc();
- return NULL;
- }
- memset(madt, 0, madt_size);
- madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
- madt->flags = cpu_to_le32(1);
- struct madt_processor_apic *apic = (void*)&madt[1];
- int i;
- for (i=0; i<MaxCountCPUs; i++) {
- apic->type = APIC_PROCESSOR;
- apic->length = sizeof(*apic);
- apic->processor_id = i;
- apic->local_apic_id = i;
- if (apic_id_is_present(apic->local_apic_id))
- apic->flags = cpu_to_le32(1);
- else
- apic->flags = cpu_to_le32(0);
- apic++;
- }
- struct madt_io_apic *io_apic = (void*)apic;
- io_apic->type = APIC_IO;
- io_apic->length = sizeof(*io_apic);
- io_apic->io_apic_id = BUILD_IOAPIC_ID;
- io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
- io_apic->interrupt = cpu_to_le32(0);
-
- struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
- if (romfile_loadint("etc/irq0-override", 0)) {
- memset(intsrcovr, 0, sizeof(*intsrcovr));
- intsrcovr->type = APIC_XRUPT_OVERRIDE;
- intsrcovr->length = sizeof(*intsrcovr);
- intsrcovr->source = 0;
- intsrcovr->gsi = cpu_to_le32(2);
- intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */
- intsrcovr++;
- }
- for (i = 1; i < 16; i++) {
- if (!(BUILD_PCI_IRQS & (1 << i)))
- /* No need for a INT source override structure. */
- continue;
- memset(intsrcovr, 0, sizeof(*intsrcovr));
- intsrcovr->type = APIC_XRUPT_OVERRIDE;
- intsrcovr->length = sizeof(*intsrcovr);
- intsrcovr->source = i;
- intsrcovr->gsi = cpu_to_le32(i);
- intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
- intsrcovr++;
- }
-
- struct madt_local_nmi *local_nmi = (void*)intsrcovr;
- local_nmi->type = APIC_LOCAL_NMI;
- local_nmi->length = sizeof(*local_nmi);
- local_nmi->processor_id = 0xff; /* all processors */
- local_nmi->flags = cpu_to_le16(0);
- local_nmi->lint = 1; /* LINT1 */
- local_nmi++;
-
- build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1);
- return madt;
-}
-
-// Encode a hex value
-static inline char getHex(u32 val) {
- val &= 0x0f;
- return (val <= 9) ? ('0' + val) : ('A' + val - 10);
-}
-
-// Encode a length in an SSDT.
-static u8 *
-encodeLen(u8 *ssdt_ptr, int length, int bytes)
-{
- switch (bytes) {
- default:
- case 4: ssdt_ptr[3] = ((length >> 20) & 0xff);
- case 3: ssdt_ptr[2] = ((length >> 12) & 0xff);
- case 2: ssdt_ptr[1] = ((length >> 4) & 0xff);
- ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f);
- break;
- case 1: ssdt_ptr[0] = length & 0x3f;
- }
- return ssdt_ptr + bytes;
-}
-
-#include "ssdt-proc.hex"
-
-/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
-#define PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
-#define PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
-#define PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
-#define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
-#define PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
-
-/* 0x5B 0x82 DeviceOp PkgLength NameString */
-#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
-#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
-#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
-#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
-#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
-#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
-#define PCI_SLOTS 32
-
-#define SSDT_SIGNATURE 0x54445353 // SSDT
-#define SSDT_HEADER_LENGTH 36
-
-#include "ssdt-misc.hex"
-#include "ssdt-pcihp.hex"
-
-#define PCI_RMV_BASE 0xae0c
-
-static u8*
-build_notify(u8 *ssdt_ptr, const char *name, int skip, int count,
- const char *target, int ofs)
-{
- count -= skip;
-
- *(ssdt_ptr++) = 0x14; // MethodOp
- ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*count), 2);
- memcpy(ssdt_ptr, name, 4);
- ssdt_ptr += 4;
- *(ssdt_ptr++) = 0x02; // MethodOp
-
- int i;
- for (i = skip; count-- > 0; i++) {
- *(ssdt_ptr++) = 0xA0; // IfOp
- ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
- *(ssdt_ptr++) = 0x93; // LEqualOp
- *(ssdt_ptr++) = 0x68; // Arg0Op
- *(ssdt_ptr++) = 0x0A; // BytePrefix
- *(ssdt_ptr++) = i;
- *(ssdt_ptr++) = 0x86; // NotifyOp
- memcpy(ssdt_ptr, target, 4);
- ssdt_ptr[ofs] = getHex(i >> 4);
- ssdt_ptr[ofs + 1] = getHex(i);
- ssdt_ptr += 4;
- *(ssdt_ptr++) = 0x69; // Arg1Op
- }
- return ssdt_ptr;
-}
-
-static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject)
-{
- ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4);
- ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot);
- ssdt_ptr[PCIHP_OFFSET_ID] = slot;
- ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot;
-
- /* Runtime patching of EJ0: to disable hotplug for a slot,
- * replace the method name: _EJ0 by EJ0_. */
- /* Sanity check */
- if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) {
- warn_internalerror();
- }
- if (!eject) {
- memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4);
- }
-}
-
-static void*
-build_ssdt(void)
-{
- int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
- int length = (sizeof(ssdp_misc_aml) // _S3_ / _S4_ / _S5_
- + (1+3+4) // Scope(_SB_)
- + (acpi_cpus * PROC_SIZEOF) // procs
- + (1+2+5+(12*acpi_cpus)) // NTFY
- + (6+2+1+(1*acpi_cpus)) // CPON
- + (1+3+4) // Scope(PCI0)
- + ((PCI_SLOTS - 1) * PCIHP_SIZEOF) // slots
- + (1+2+5+(12*(PCI_SLOTS - 1)))); // PCNT
- u8 *ssdt = malloc_high(length);
- if (! ssdt) {
- warn_noalloc();
- return NULL;
- }
- u8 *ssdt_ptr = ssdt;
-
- // Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages
- int sys_state_size;
- char *sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
- if (!sys_states || sys_state_size != 6)
- sys_states = (char[]){128, 0, 0, 129, 128, 128};
-
- memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
- if (!(sys_states[3] & 128))
- ssdt_ptr[acpi_s3_name[0]] = 'X';
- if (!(sys_states[4] & 128))
- ssdt_ptr[acpi_s4_name[0]] = 'X';
- else
- ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
-
- // store pci io windows
- *(u32*)&ssdt_ptr[acpi_pci32_start[0]] = cpu_to_le32(pcimem_start);
- *(u32*)&ssdt_ptr[acpi_pci32_end[0]] = cpu_to_le32(pcimem_end - 1);
- if (pcimem64_start) {
- ssdt_ptr[acpi_pci64_valid[0]] = 1;
- *(u64*)&ssdt_ptr[acpi_pci64_start[0]] = cpu_to_le64(pcimem64_start);
- *(u64*)&ssdt_ptr[acpi_pci64_end[0]] = cpu_to_le64(pcimem64_end - 1);
- *(u64*)&ssdt_ptr[acpi_pci64_length[0]] = cpu_to_le64(
- pcimem64_end - pcimem64_start);
- } else {
- ssdt_ptr[acpi_pci64_valid[0]] = 0;
- }
-
- int pvpanic_port = romfile_loadint("etc/pvpanic-port", 0x0);
- *(u16 *)(ssdt_ptr + *ssdt_isa_pest) = pvpanic_port;
-
- ssdt_ptr += sizeof(ssdp_misc_aml);
-
- // build Scope(_SB_) header
- *(ssdt_ptr++) = 0x10; // ScopeOp
- ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
- *(ssdt_ptr++) = '_';
- *(ssdt_ptr++) = 'S';
- *(ssdt_ptr++) = 'B';
- *(ssdt_ptr++) = '_';
-
- // build Processor object for each processor
- int i;
- for (i=0; i<acpi_cpus; i++) {
- memcpy(ssdt_ptr, PROC_AML, PROC_SIZEOF);
- ssdt_ptr[PROC_OFFSET_CPUHEX] = getHex(i >> 4);
- ssdt_ptr[PROC_OFFSET_CPUHEX+1] = getHex(i);
- ssdt_ptr[PROC_OFFSET_CPUID1] = i;
- ssdt_ptr[PROC_OFFSET_CPUID2] = i;
- ssdt_ptr += PROC_SIZEOF;
- }
-
- // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
- // Arg0 = Processor ID = APIC ID
- ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2);
-
- // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
- *(ssdt_ptr++) = 0x08; // NameOp
- *(ssdt_ptr++) = 'C';
- *(ssdt_ptr++) = 'P';
- *(ssdt_ptr++) = 'O';
- *(ssdt_ptr++) = 'N';
- *(ssdt_ptr++) = 0x12; // PackageOp
- ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2);
- *(ssdt_ptr++) = acpi_cpus;
- for (i=0; i<acpi_cpus; i++)
- *(ssdt_ptr++) = (apic_id_is_present(i)) ? 0x01 : 0x00;
-
- // build Scope(PCI0) opcode
- *(ssdt_ptr++) = 0x10; // ScopeOp
- ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
- *(ssdt_ptr++) = 'P';
- *(ssdt_ptr++) = 'C';
- *(ssdt_ptr++) = 'I';
- *(ssdt_ptr++) = '0';
-
- // build Device object for each slot
- u32 rmvc_pcrm = inl(PCI_RMV_BASE);
- for (i=1; i<PCI_SLOTS; i++) {
- u32 eject = rmvc_pcrm & (0x1 << i);
- memcpy(ssdt_ptr, PCIHP_AML, PCIHP_SIZEOF);
- patch_pcihp(i, ssdt_ptr, eject != 0);
- ssdt_ptr += PCIHP_SIZEOF;
- }
-
- ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOTS, "S00_", 1);
-
- build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
-
- //hexdump(ssdt, ssdt_ptr - ssdt);
-
- return ssdt;
-}
-
-#define HPET_ID 0x000
-#define HPET_PERIOD 0x004
-
-static void*
-build_hpet(void)
-{
- struct acpi_20_hpet *hpet;
- const void *hpet_base = (void *)BUILD_HPET_ADDRESS;
- u32 hpet_vendor = readl(hpet_base + HPET_ID) >> 16;
- u32 hpet_period = readl(hpet_base + HPET_PERIOD);
-
- if (hpet_vendor == 0 || hpet_vendor == 0xffff ||
- hpet_period == 0 || hpet_period > 100000000)
- return NULL;
-
- hpet = malloc_high(sizeof(*hpet));
- if (!hpet) {
- warn_noalloc();
- return NULL;
- }
-
- memset(hpet, 0, sizeof(*hpet));
- /* Note timer_block_id value must be kept in sync with value advertised by
- * emulated hpet
- */
- hpet->timer_block_id = cpu_to_le32(0x8086a201);
- hpet->addr.address = cpu_to_le64(BUILD_HPET_ADDRESS);
- build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1);
-
- return hpet;
-}
-
-static void
-acpi_build_srat_memory(struct srat_memory_affinity *numamem,
- u64 base, u64 len, int node, int enabled)
-{
- numamem->type = SRAT_MEMORY;
- numamem->length = sizeof(*numamem);
- memset(numamem->proximity, 0, 4);
- numamem->proximity[0] = node;
- numamem->flags = cpu_to_le32(!!enabled);
- numamem->base_addr = cpu_to_le64(base);
- numamem->range_length = cpu_to_le64(len);
-}
-
-static void *
-build_srat(void)
-{
- int numadatasize, numacpusize;
- u64 *numadata = romfile_loadfile("etc/numa-nodes", &numadatasize);
- u64 *numacpumap = romfile_loadfile("etc/numa-cpu-map", &numacpusize);
- if (!numadata || !numacpumap)
- goto fail;
- int max_cpu = numacpusize / sizeof(u64);
- int nb_numa_nodes = numadatasize / sizeof(u64);
-
- struct system_resource_affinity_table *srat;
- int srat_size = sizeof(*srat) +
- sizeof(struct srat_processor_affinity) * max_cpu +
- sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
-
- srat = malloc_high(srat_size);
- if (!srat) {
- warn_noalloc();
- goto fail;
- }
-
- memset(srat, 0, srat_size);
- srat->reserved1=cpu_to_le32(1);
- struct srat_processor_affinity *core = (void*)(srat + 1);
- int i;
- u64 curnode;
-
- for (i = 0; i < max_cpu; ++i) {
- core->type = SRAT_PROCESSOR;
- core->length = sizeof(*core);
- core->local_apic_id = i;
- curnode = *numacpumap++;
- core->proximity_lo = curnode;
- memset(core->proximity_hi, 0, 3);
- core->local_sapic_eid = 0;
- if (apic_id_is_present(i))
- core->flags = cpu_to_le32(1);
- else
- core->flags = cpu_to_le32(0);
- core++;
- }
-
-
- /* the memory map is a bit tricky, it contains at least one hole
- * from 640k-1M and possibly another one from 3.5G-4G.
- */
- struct srat_memory_affinity *numamem = (void*)core;
- int slots = 0;
- u64 mem_len, mem_base, next_base = 0;
-
- acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
- next_base = 1024 * 1024;
- numamem++;
- slots++;
- for (i = 1; i < nb_numa_nodes + 1; ++i) {
- mem_base = next_base;
- mem_len = *numadata++;
- if (i == 1)
- mem_len -= 1024 * 1024;
- next_base = mem_base + mem_len;
-
- /* Cut out the PCI hole */
- if (mem_base <= RamSize && next_base > RamSize) {
- mem_len -= next_base - RamSize;
- if (mem_len > 0) {
- acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
- numamem++;
- slots++;
- }
- mem_base = 1ULL << 32;
- mem_len = next_base - RamSize;
- next_base += (1ULL << 32) - RamSize;
- }
- acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
- numamem++;
- slots++;
- }
- for (; slots < nb_numa_nodes + 2; slots++) {
- acpi_build_srat_memory(numamem, 0, 0, 0, 0);
- numamem++;
- }
-
- build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1);
-
- free(numadata);
- free(numacpumap);
- return srat;
-fail:
- free(numadata);
- free(numacpumap);
- return NULL;
-}
-
-static void *
-build_mcfg_q35(void)
-{
- struct acpi_table_mcfg *mcfg;
-
- int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
- mcfg = malloc_high(len);
- if (!mcfg) {
- warn_noalloc();
- return NULL;
- }
- memset(mcfg, 0, len);
- mcfg->allocation[0].address = cpu_to_le64(Q35_HOST_BRIDGE_PCIEXBAR_ADDR);
- mcfg->allocation[0].pci_segment = cpu_to_le16(Q35_HOST_PCIE_PCI_SEGMENT);
- mcfg->allocation[0].start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER;
- mcfg->allocation[0].end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER;
-
- build_header((void *)mcfg, MCFG_SIGNATURE, len, 1);
- return mcfg;
-}
-
-static const struct pci_device_id acpi_find_tbl[] = {
- /* PIIX4 Power Management device. */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, NULL),
- PCI_DEVICE_END,
-};
-
-struct rsdp_descriptor *RsdpAddr;
-
-#define MAX_ACPI_TABLES 20
-void
-acpi_setup(void)
-{
- if (! CONFIG_ACPI)
- return;
-
- dprintf(3, "init ACPI tables\n");
-
- // This code is hardcoded for PIIX4 Power Management device.
- struct pci_device *pci = pci_find_init_device(acpi_find_tbl, NULL);
- if (!pci)
- // Device not found
- return;
-
- // Build ACPI tables
- u32 tables[MAX_ACPI_TABLES], tbl_idx = 0;
-
-#define ACPI_INIT_TABLE(X) \
- do { \
- tables[tbl_idx] = cpu_to_le32((u32)(X)); \
- if (le32_to_cpu(tables[tbl_idx])) \
- tbl_idx++; \
- } while(0)
-
- struct fadt_descriptor_rev1 *fadt = build_fadt(pci);
- ACPI_INIT_TABLE(fadt);
- ACPI_INIT_TABLE(build_ssdt());
- ACPI_INIT_TABLE(build_madt());
- ACPI_INIT_TABLE(build_hpet());
- ACPI_INIT_TABLE(build_srat());
- if (pci->device == PCI_DEVICE_ID_INTEL_ICH9_LPC)
- ACPI_INIT_TABLE(build_mcfg_q35());
-
- struct romfile_s *file = NULL;
- for (;;) {
- file = romfile_findprefix("acpi/", file);
- if (!file)
- break;
- struct acpi_table_header *table = malloc_high(file->size);
- if (!table) {
- warn_noalloc();
- continue;
- }
- int ret = file->copy(file, table, file->size);
- if (ret <= sizeof(*table))
- continue;
- if (table->signature == DSDT_SIGNATURE) {
- if (fadt) {
- fill_dsdt(fadt, table);
- }
- } else {
- ACPI_INIT_TABLE(table);
- }
- if (tbl_idx == MAX_ACPI_TABLES) {
- warn_noalloc();
- break;
- }
- }
-
- if (CONFIG_ACPI_DSDT && fadt && !fadt->dsdt) {
- /* default DSDT */
- void *dsdt = malloc_high(sizeof(AmlCode));
- if (!dsdt) {
- warn_noalloc();
- return;
- }
- memcpy(dsdt, AmlCode, sizeof(AmlCode));
- fill_dsdt(fadt, dsdt);
- }
-
- // Build final rsdt table
- struct rsdt_descriptor_rev1 *rsdt;
- size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
- rsdt = malloc_high(rsdt_len);
- if (!rsdt) {
- warn_noalloc();
- return;
- }
- memset(rsdt, 0, rsdt_len);
- memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx);
- build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1);
-
- // Build rsdp pointer table
- struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp));
- if (!rsdp) {
- warn_noalloc();
- return;
- }
- memset(rsdp, 0, sizeof(*rsdp));
- rsdp->signature = cpu_to_le64(RSDP_SIGNATURE);
- memcpy(rsdp->oem_id, BUILD_APPNAME6, 6);
- rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt);
- rsdp->checksum -= checksum(rsdp, 20);
- RsdpAddr = rsdp;
- dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt);
-}
-
-static struct fadt_descriptor_rev1 *
-find_fadt(void)
-{
- dprintf(4, "rsdp=%p\n", RsdpAddr);
- if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
- return NULL;
- struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
- dprintf(4, "rsdt=%p\n", rsdt);
- if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
- return NULL;
- void *end = (void*)rsdt + rsdt->length;
- int i;
- for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
- struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
- if (!fadt || fadt->signature != FACP_SIGNATURE)
- continue;
- dprintf(4, "fadt=%p\n", fadt);
- return fadt;
- }
- dprintf(4, "no fadt found\n");
- return NULL;
-}
-
-u32
-find_resume_vector(void)
-{
- struct fadt_descriptor_rev1 *fadt = find_fadt();
- if (!fadt)
- return 0;
- struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
- dprintf(4, "facs=%p\n", facs);
- if (! facs || facs->signature != FACS_SIGNATURE)
- return 0;
- // Found it.
- dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
- return facs->firmware_waking_vector;
-}
-
-void
-find_acpi_features(void)
-{
- struct fadt_descriptor_rev1 *fadt = find_fadt();
- if (!fadt)
- return;
- u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk);
- u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk);
- dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
- if (pm_tmr)
- pmtimer_setup(pm_tmr);
- if (pm1a_cnt)
- acpi_pm1a_cnt = pm1a_cnt;
-
- // Theoretically we should check the 'reset_reg_sup' flag, but Windows
- // doesn't and thus nobody seems to *set* it. If the table is large enough
- // to include it, let the sanity checks in acpi_set_reset_reg() suffice.
- if (fadt->length >= 129) {
- void *p = fadt;
- acpi_set_reset_reg(p + 116, *(u8 *)(p + 128));
- }
-}
-
-static struct acpi_20_generic_address acpi_reset_reg;
-static u8 acpi_reset_val;
-
-void
-acpi_reboot(void)
-{
- // Check it passed the sanity checks in acpi_set_reset_reg() and was set
- if (acpi_reset_reg.register_bit_width != 8)
- return;
-
- u64 addr = le64_to_cpu(acpi_reset_reg.address);
-
- dprintf(1, "ACPI hard reset %d:%llx (%x)\n",
- acpi_reset_reg.address_space_id, addr, acpi_reset_val);
-
- switch (acpi_reset_reg.address_space_id) {
- case 0: // System Memory
- writeb((void *)(u32)addr, acpi_reset_val);
- break;
- case 1: // System I/O
- outb(acpi_reset_val, addr);
- break;
- case 2: // PCI config space
- pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val);
- break;
- }
-}
-
-void
-acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val)
-{
- if (!reg || reg->address_space_id > 2 ||
- reg->register_bit_width != 8 || reg->register_bit_offset)
- return;
-
- acpi_reset_reg = *reg;
- acpi_reset_val = val;
-}
+++ /dev/null
-#ifndef __ACPI_H
-#define __ACPI_H
-
-#include "types.h" // u32
-
-/*
- * ACPI 2.0 Generic Address Space definition.
- */
-struct acpi_20_generic_address {
- u8 address_space_id;
- u8 register_bit_width;
- u8 register_bit_offset;
- u8 reserved;
- u64 address;
-} PACKED;
-#define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff)
-
-void acpi_setup(void);
-u32 find_resume_vector(void);
-void find_acpi_features(void);
-void acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val);
-void acpi_reboot(void);
-
-#define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
-
-struct rsdp_descriptor { /* Root System Descriptor Pointer */
- u64 signature; /* ACPI signature, contains "RSD PTR " */
- u8 checksum; /* To make sum of struct == 0 */
- u8 oem_id [6]; /* OEM identification */
- u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */
- u32 rsdt_physical_address; /* 32-bit physical address of RSDT */
- u32 length; /* XSDT Length in bytes including hdr */
- u64 xsdt_physical_address; /* 64-bit physical address of XSDT */
- u8 extended_checksum; /* Checksum of entire table */
- u8 reserved [3]; /* Reserved field must be 0 */
-};
-
-extern struct rsdp_descriptor *RsdpAddr;
-extern u32 acpi_pm1a_cnt;
-
-/* Table structure from Linux kernel (the ACPI tables are under the
- BSD license) */
-
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
- u32 signature; /* ACPI signature (4 ASCII characters) */ \
- u32 length; /* Length of table, in bytes, including header */ \
- u8 revision; /* ACPI Specification minor version # */ \
- u8 checksum; /* To make sum of entire table == 0 */ \
- u8 oem_id [6]; /* OEM identification */ \
- u8 oem_table_id [8]; /* OEM table identification */ \
- u32 oem_revision; /* OEM revision number */ \
- u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \
- u32 asl_compiler_revision; /* ASL compiler revision number */
-
-
-/*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
- */
-#define FACP_SIGNATURE 0x50434146 // FACP
-struct fadt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 firmware_ctrl; /* Physical address of FACS */
- u32 dsdt; /* Physical address of DSDT */
- u8 model; /* System Interrupt Model */
- u8 reserved1; /* Reserved */
- u16 sci_int; /* System vector of SCI interrupt */
- u32 smi_cmd; /* Port address of SMI command port */
- u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
- u8 reserved2; /* Reserved - must be zero */
- u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
- u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
- u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
- u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
- u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
- u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
- u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
- u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
- u8 reserved3; /* Reserved */
- u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
- u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
- u16 flush_size; /* Size of area read to flush caches */
- u16 flush_stride; /* Stride used in flushing caches */
- u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */
- u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */
- u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
- u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
- u8 century; /* Index to century in RTC CMOS RAM */
- u8 reserved4; /* Reserved */
- u8 reserved4a; /* Reserved */
- u8 reserved4b; /* Reserved */
- u32 flags;
-} PACKED;
-
-struct acpi_table_header /* ACPI common table header */
-{
- ACPI_TABLE_HEADER_DEF
-} PACKED;
-
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-#define RSDT_SIGNATURE 0x54445352 // RSDT
-struct rsdt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 table_offset_entry[0]; /* Array of pointers to other */
- /* ACPI tables */
-} PACKED;
-
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-#define FACS_SIGNATURE 0x53434146 // FACS
-struct facs_descriptor_rev1
-{
- u32 signature; /* ACPI Signature */
- u32 length; /* Length of structure, in bytes */
- u32 hardware_signature; /* Hardware configuration signature */
- u32 firmware_waking_vector; /* ACPI OS waking vector */
- u32 global_lock; /* Global Lock */
- u32 flags;
- u8 resverved3 [40]; /* Reserved - must be zero */
-} PACKED;
-
-/*
- * Differentiated System Description Table (DSDT)
- */
-#define DSDT_SIGNATURE 0x54445344 // DSDT
-
-/*
- * MADT values and structures
- */
-
-/* Values for MADT PCATCompat */
-
-#define DUAL_PIC 0
-#define MULTIPLE_APIC 1
-
-/* Master MADT */
-
-#define APIC_SIGNATURE 0x43495041 // APIC
-struct multiple_apic_table
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 local_apic_address; /* Physical address of local APIC */
- u32 flags;
-} PACKED;
-
-/* Values for Type in APIC sub-headers */
-
-#define APIC_PROCESSOR 0
-#define APIC_IO 1
-#define APIC_XRUPT_OVERRIDE 2
-#define APIC_NMI 3
-#define APIC_LOCAL_NMI 4
-#define APIC_ADDRESS_OVERRIDE 5
-#define APIC_IO_SAPIC 6
-#define APIC_LOCAL_SAPIC 7
-#define APIC_XRUPT_SOURCE 8
-#define APIC_RESERVED 9 /* 9 and greater are reserved */
-
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
- u8 type; \
- u8 length;
-
-/* Sub-structures for MADT */
-
-struct madt_processor_apic
-{
- ACPI_SUB_HEADER_DEF
- u8 processor_id; /* ACPI processor id */
- u8 local_apic_id; /* Processor's local APIC id */
- u32 flags;
-} PACKED;
-
-struct madt_io_apic
-{
- ACPI_SUB_HEADER_DEF
- u8 io_apic_id; /* I/O APIC ID */
- u8 reserved; /* Reserved - must be zero */
- u32 address; /* APIC physical address */
- u32 interrupt; /* Global system interrupt where INTI
- * lines start */
-} PACKED;
-
-struct madt_intsrcovr {
- ACPI_SUB_HEADER_DEF
- u8 bus;
- u8 source;
- u32 gsi;
- u16 flags;
-} PACKED;
-
-struct madt_local_nmi {
- ACPI_SUB_HEADER_DEF
- u8 processor_id; /* ACPI processor id */
- u16 flags; /* MPS INTI flags */
- u8 lint; /* Local APIC LINT# */
-} PACKED;
-
-/*
- * HPET Description Table
- */
-#define HPET_SIGNATURE 0x54455048 // HPET
-struct acpi_20_hpet {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 timer_block_id;
- struct acpi_20_generic_address addr;
- u8 hpet_number;
- u16 min_tick;
- u8 page_protect;
-} PACKED;
-
-/*
- * SRAT (NUMA topology description) table
- */
-
-#define SRAT_SIGNATURE 0x54415253 // SRAT
-struct system_resource_affinity_table
-{
- ACPI_TABLE_HEADER_DEF
- u32 reserved1;
- u32 reserved2[2];
-} PACKED;
-
-#define SRAT_PROCESSOR 0
-#define SRAT_MEMORY 1
-
-struct srat_processor_affinity
-{
- ACPI_SUB_HEADER_DEF
- u8 proximity_lo;
- u8 local_apic_id;
- u32 flags;
- u8 local_sapic_eid;
- u8 proximity_hi[3];
- u32 reserved;
-} PACKED;
-
-struct srat_memory_affinity
-{
- ACPI_SUB_HEADER_DEF
- u8 proximity[4];
- u16 reserved1;
- u64 base_addr;
- u64 range_length;
- u32 reserved2;
- u32 flags;
- u32 reserved3[2];
-} PACKED;
-
-/* PCI fw r3.0 MCFG table. */
-/* Subtable */
-struct acpi_mcfg_allocation {
- u64 address; /* Base address, processor-relative */
- u16 pci_segment; /* PCI segment group number */
- u8 start_bus_number; /* Starting PCI Bus number */
- u8 end_bus_number; /* Final PCI Bus number */
- u32 reserved;
-} PACKED;
-
-#define MCFG_SIGNATURE 0x4746434d // MCFG
-struct acpi_table_mcfg {
- ACPI_TABLE_HEADER_DEF;
- u8 reserved[8];
- struct acpi_mcfg_allocation allocation[0];
-} PACKED;
-
-#endif // acpi.h
#include "util.h" // dprintf
#include "config.h" // CONFIG_*
#include "biosvar.h" // GET_GLOBAL
-#include "paravirt.h" // runningOnQEMU
-#include "acpi.h" // acpi_pm_ctl
+#include "fw/paravirt.h" // runningOnQEMU
+#include "fw/acpi.h" // acpi_pm_ctl
static void
out_str(const char *str_cs)
+++ /dev/null
-// Coreboot interface support.
-//
-// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h" // CONFIG_*
-#include "util.h" // dprintf
-#include "hw/pci.h" // struct pir_header
-#include "acpi.h" // struct rsdp_descriptor
-#include "mptable.h" // MPTABLE_SIGNATURE
-#include "smbios.h" // struct smbios_entry_point
-
-static void
-copy_pir(void *pos)
-{
- struct pir_header *p = pos;
- if (p->signature != PIR_SIGNATURE)
- return;
- if (PirAddr)
- return;
- if (p->size < sizeof(*p))
- return;
- if (checksum(pos, p->size) != 0)
- return;
- void *newpos = malloc_fseg(p->size);
- if (!newpos) {
- warn_noalloc();
- return;
- }
- dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
- memcpy(newpos, pos, p->size);
- PirAddr = newpos;
-}
-
-static void
-copy_mptable(void *pos)
-{
- struct mptable_floating_s *p = pos;
- if (p->signature != MPTABLE_SIGNATURE)
- return;
- if (!p->physaddr)
- return;
- if (checksum(pos, sizeof(*p)) != 0)
- return;
- u32 length = p->length * 16;
- u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
- struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
- if (!newpos) {
- warn_noalloc();
- return;
- }
- dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
- memcpy(newpos, pos, length);
- newpos->physaddr = (u32)newpos + length;
- newpos->checksum -= checksum(newpos, sizeof(*newpos));
- memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
-}
-
-static void
-copy_acpi_rsdp(void *pos)
-{
- if (RsdpAddr)
- return;
- struct rsdp_descriptor *p = pos;
- if (p->signature != RSDP_SIGNATURE)
- return;
- u32 length = 20;
- if (checksum(pos, length) != 0)
- return;
- if (p->revision > 1) {
- length = p->length;
- if (checksum(pos, length) != 0)
- return;
- }
- void *newpos = malloc_fseg(length);
- if (!newpos) {
- warn_noalloc();
- return;
- }
- dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
- memcpy(newpos, pos, length);
- RsdpAddr = newpos;
-}
-
-void
-copy_smbios(void *pos)
-{
- if (SMBiosAddr)
- return;
- struct smbios_entry_point *p = pos;
- if (memcmp(p->anchor_string, "_SM_", 4))
- return;
- if (checksum(pos, 0x10) != 0)
- return;
- if (memcmp(p->intermediate_anchor_string, "_DMI_", 5))
- return;
- if (checksum(pos+0x10, p->length-0x10) != 0)
- return;
- struct smbios_entry_point *newpos = malloc_fseg(p->length);
- if (!newpos) {
- warn_noalloc();
- return;
- }
- dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos);
- memcpy(newpos, pos, p->length);
- SMBiosAddr = newpos;
-}
-
-void
-copy_table(void *pos)
-{
- copy_pir(pos);
- copy_mptable(pos);
- copy_acpi_rsdp(pos);
- copy_smbios(pos);
-}
#include "bregs.h" // struct bregs
#include "boot.h" // func defs
#include "hw/cmos.h" // inb_cmos
-#include "paravirt.h" // qemu_cfg_show_boot_menu
+#include "fw/paravirt.h" // qemu_cfg_show_boot_menu
#include "hw/pci.h" // pci_bdf_to_*
#include "hw/usb.h" // struct usbdevice_s
-#include "csm.h" // csm_bootprio_*
+#include "fw/csm.h" // csm_bootprio_*
#include "list.h" // hlist_node
#include "jpeg.h" // splash
#include "vbe.h" // struct vbe_info
#include "bmp.h" // bmp_alloc
-#include "smbios.h" // display_uuid
+#include "fw/smbios.h" // display_uuid
/****************************************************************
+++ /dev/null
-// Coreboot interface support.
-//
-// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "memmap.h" // add_e820
-#include "util.h" // dprintf
-#include "byteorder.h" // be32_to_cpu
-#include "lzmadecode.h" // LzmaDecode
-#include "smbios.h" // smbios_init
-#include "boot.h" // boot_add_cbfs
-#include "disk.h" // MAXDESCSIZE
-#include "config.h" // CONFIG_*
-#include "acpi.h" // find_acpi_features
-#include "hw/pci.h" // pci_probe_devices
-#include "paravirt.h" // PlatformRunningOn
-
-
-/****************************************************************
- * Memory map
- ****************************************************************/
-
-struct cb_header {
- u32 signature;
- u32 header_bytes;
- u32 header_checksum;
- u32 table_bytes;
- u32 table_checksum;
- u32 table_entries;
-};
-
-#define CB_SIGNATURE 0x4f49424C // "LBIO"
-
-struct cb_memory_range {
- u64 start;
- u64 size;
- u32 type;
-};
-
-#define CB_MEM_TABLE 16
-
-struct cb_memory {
- u32 tag;
- u32 size;
- struct cb_memory_range map[0];
-};
-
-#define CB_TAG_MEMORY 0x01
-
-#define MEM_RANGE_COUNT(_rec) \
- (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0]))
-
-struct cb_mainboard {
- u32 tag;
- u32 size;
- u8 vendor_idx;
- u8 part_idx;
- char strings[0];
-};
-
-#define CB_TAG_MAINBOARD 0x0003
-
-struct cb_forward {
- u32 tag;
- u32 size;
- u64 forward;
-};
-
-#define CB_TAG_FORWARD 0x11
-
-struct cb_cbmem_ref {
- u32 tag;
- u32 size;
- u64 cbmem_addr;
-};
-
-#define CB_TAG_CBMEM_CONSOLE 0x17
-
-struct cbmem_console {
- u32 buffer_size;
- u32 buffer_cursor;
- u8 buffer_body[0];
-} PACKED;
-static struct cbmem_console *cbcon = NULL;
-
-static u16
-ipchksum(char *buf, int count)
-{
- u16 *p = (u16*)buf;
- u32 sum = 0;
- while (count > 1) {
- sum += *p++;
- count -= 2;
- }
- if (count)
- sum += *(u8*)p;
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- return ~sum;
-}
-
-// Try to locate the coreboot header in a given address range.
-static struct cb_header *
-find_cb_header(char *addr, int len)
-{
- char *end = addr + len;
- for (; addr < end; addr += 16) {
- struct cb_header *cbh = (struct cb_header *)addr;
- if (cbh->signature != CB_SIGNATURE)
- continue;
- if (! cbh->table_bytes)
- continue;
- if (ipchksum(addr, sizeof(*cbh)) != 0)
- continue;
- if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes)
- != cbh->table_checksum)
- continue;
- return cbh;
- }
- return NULL;
-}
-
-// Try to find the coreboot memory table in the given coreboot table.
-static void *
-find_cb_subtable(struct cb_header *cbh, u32 tag)
-{
- char *tbl = (char *)cbh + sizeof(*cbh);
- int i;
- for (i=0; i<cbh->table_entries; i++) {
- struct cb_memory *cbm = (struct cb_memory *)tbl;
- tbl += cbm->size;
- if (cbm->tag == tag)
- return cbm;
- }
- return NULL;
-}
-
-static struct cb_memory *CBMemTable;
-const char *CBvendor = "", *CBpart = "";
-
-// Populate max ram and e820 map info by scanning for a coreboot table.
-void
-coreboot_preinit(void)
-{
- if (!CONFIG_COREBOOT)
- return;
-
- dprintf(3, "Attempting to find coreboot table\n");
-
- // Find coreboot table.
- struct cb_header *cbh = find_cb_header(0, 0x1000);
- if (!cbh)
- goto fail;
- struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD);
- if (cbf) {
- dprintf(3, "Found coreboot table forwarder.\n");
- cbh = find_cb_header((char *)((u32)cbf->forward), 0x100);
- if (!cbh)
- goto fail;
- }
- dprintf(3, "Now attempting to find coreboot memory map\n");
- struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY);
- if (!cbm)
- goto fail;
-
- int i, count = MEM_RANGE_COUNT(cbm);
- for (i=0; i<count; i++) {
- struct cb_memory_range *m = &cbm->map[i];
- u32 type = m->type;
- if (type == CB_MEM_TABLE)
- type = E820_RESERVED;
- add_e820(m->start, m->size, type);
- }
-
- // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this
- // confuses grub. So, override it.
- add_e820(0, 16*1024, E820_RAM);
-
- struct cb_cbmem_ref *cbref = find_cb_subtable(cbh, CB_TAG_CBMEM_CONSOLE);
- if (cbref) {
- cbcon = (void*)(u32)cbref->cbmem_addr;
- dprintf(1, "----- [ seabios log starts here ] -----\n");
- dprintf(1, "Found coreboot cbmem console @ %llx\n", cbref->cbmem_addr);
- }
-
- struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD);
- if (cbmb) {
- CBvendor = &cbmb->strings[cbmb->vendor_idx];
- CBpart = &cbmb->strings[cbmb->part_idx];
- if (strcmp(CBvendor, "Emulation") == 0 &&
- memcmp(CBpart, "QEMU", 4) == 0) {
- PlatformRunningOn |= PF_QEMU;
- }
- dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart);
- }
-
- return;
-
-fail:
- // No table found.. Use 16Megs as a dummy value.
- dprintf(1, "Unable to find coreboot table!\n");
- add_e820(0, 16*1024*1024, E820_RAM);
- return;
-}
-
-void debug_cbmem(char c)
-{
- if (!CONFIG_DEBUG_COREBOOT)
- return;
- if (!cbcon)
- return;
- if (cbcon->buffer_cursor == cbcon->buffer_size)
- return;
- cbcon->buffer_body[cbcon->buffer_cursor++] = c;
-}
-
-/****************************************************************
- * BIOS table copying
- ****************************************************************/
-
-// Attempt to find (and relocate) any standard bios tables found in a
-// given address range.
-static void
-scan_tables(u32 start, u32 size)
-{
- void *p = (void*)ALIGN(start, 16);
- void *end = (void*)start + size;
- for (; p<end; p += 16)
- copy_table(p);
-}
-
-void
-coreboot_platform_setup(void)
-{
- if (!CONFIG_COREBOOT)
- return;
- pci_probe_devices();
-
- struct cb_memory *cbm = CBMemTable;
- if (!cbm)
- return;
-
- dprintf(3, "Relocating coreboot bios tables\n");
-
- // Scan CB_MEM_TABLE areas for bios tables.
- int i, count = MEM_RANGE_COUNT(cbm);
- for (i=0; i<count; i++) {
- struct cb_memory_range *m = &cbm->map[i];
- if (m->type == CB_MEM_TABLE)
- scan_tables(m->start, m->size);
- }
-
- find_acpi_features();
-}
-
-
-/****************************************************************
- * ulzma
- ****************************************************************/
-
-// Uncompress data in flash to an area of memory.
-static int
-ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
-{
- dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
- CLzmaDecoderState state;
- int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
- if (ret != LZMA_RESULT_OK) {
- dprintf(1, "LzmaDecodeProperties error - %d\n", ret);
- return -1;
- }
- u8 scratch[15980];
- int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
- if (need > sizeof(scratch)) {
- dprintf(1, "LzmaDecode need %d have %d\n", need, (unsigned int)sizeof(scratch));
- return -1;
- }
- state.Probs = (CProb *)scratch;
-
- u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE);
- if (dstlen > maxlen) {
- dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen);
- return -1;
- }
- u32 inProcessed, outProcessed;
- ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen
- , &inProcessed, dst, dstlen, &outProcessed);
- if (ret) {
- dprintf(1, "LzmaDecode returned %d\n", ret);
- return -1;
- }
- return dstlen;
-}
-
-
-/****************************************************************
- * Coreboot flash format
- ****************************************************************/
-
-#define CBFS_HEADER_MAGIC 0x4F524243
-#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
-#define CBFS_VERSION1 0x31313131
-
-struct cbfs_header {
- u32 magic;
- u32 version;
- u32 romsize;
- u32 bootblocksize;
- u32 align;
- u32 offset;
- u32 pad[2];
-} PACKED;
-
-#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE
-
-struct cbfs_file {
- u64 magic;
- u32 len;
- u32 type;
- u32 checksum;
- u32 offset;
- char filename[0];
-} PACKED;
-
-struct cbfs_romfile_s {
- struct romfile_s file;
- struct cbfs_file *fhdr;
- void *data;
- u32 rawsize, flags;
-};
-
-// Copy a file to memory (uncompressing if necessary)
-static int
-cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
-{
- if (!CONFIG_COREBOOT_FLASH)
- return -1;
-
- struct cbfs_romfile_s *cfile;
- cfile = container_of(file, struct cbfs_romfile_s, file);
- u32 size = cfile->rawsize;
- void *src = cfile->data;
- if (cfile->flags) {
- // Compressed - copy to temp ram and uncompress it.
- void *temp = malloc_tmphigh(size);
- if (!temp) {
- warn_noalloc();
- return -1;
- }
- iomemcpy(temp, src, size);
- int ret = ulzma(dst, maxlen, temp, size);
- yield();
- free(temp);
- return ret;
- }
-
- // Not compressed.
- dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
- if (size > maxlen) {
- warn_noalloc();
- return -1;
- }
- iomemcpy(dst, src, size);
- return size;
-}
-
-void
-coreboot_cbfs_init(void)
-{
- if (!CONFIG_COREBOOT_FLASH)
- return;
-
- struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR;
- if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) {
- dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n"
- , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC));
- return;
- }
- dprintf(1, "Found CBFS header at %p\n", hdr);
-
- struct cbfs_file *fhdr = (void *)(0 - be32_to_cpu(hdr->romsize)
- + be32_to_cpu(hdr->offset));
- for (;;) {
- if (fhdr < (struct cbfs_file *)(0xFFFFFFFF - be32_to_cpu(hdr->romsize)))
- break;
- u64 magic = fhdr->magic;
- if (magic != CBFS_FILE_MAGIC)
- break;
- struct cbfs_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
- if (!cfile) {
- warn_noalloc();
- break;
- }
- memset(cfile, 0, sizeof(*cfile));
- strtcpy(cfile->file.name, fhdr->filename, sizeof(cfile->file.name));
- cfile->file.size = cfile->rawsize = be32_to_cpu(fhdr->len);
- cfile->fhdr = fhdr;
- cfile->file.copy = cbfs_copyfile;
- cfile->data = (void*)fhdr + be32_to_cpu(fhdr->offset);
- int len = strlen(cfile->file.name);
- if (len > 5 && strcmp(&cfile->file.name[len-5], ".lzma") == 0) {
- // Using compression.
- cfile->flags = 1;
- cfile->file.name[len-5] = '\0';
- cfile->file.size = *(u32*)(cfile->data + LZMA_PROPERTIES_SIZE);
- }
- romfile_add(&cfile->file);
-
- fhdr = (void*)ALIGN((u32)cfile->data + cfile->rawsize
- , be32_to_cpu(hdr->align));
- }
-}
-
-struct cbfs_payload_segment {
- u32 type;
- u32 compression;
- u32 offset;
- u64 load_addr;
- u32 len;
- u32 mem_len;
-} PACKED;
-
-#define PAYLOAD_SEGMENT_BSS 0x20535342
-#define PAYLOAD_SEGMENT_ENTRY 0x52544E45
-
-#define CBFS_COMPRESS_NONE 0
-#define CBFS_COMPRESS_LZMA 1
-
-struct cbfs_payload {
- struct cbfs_payload_segment segments[1];
-};
-
-void
-cbfs_run_payload(struct cbfs_file *fhdr)
-{
- if (!CONFIG_COREBOOT_FLASH || !fhdr)
- return;
- dprintf(1, "Run %s\n", fhdr->filename);
- struct cbfs_payload *pay = (void*)fhdr + be32_to_cpu(fhdr->offset);
- struct cbfs_payload_segment *seg = pay->segments;
- for (;;) {
- void *src = (void*)pay + be32_to_cpu(seg->offset);
- void *dest = (void*)(u32)be64_to_cpu(seg->load_addr);
- u32 src_len = be32_to_cpu(seg->len);
- u32 dest_len = be32_to_cpu(seg->mem_len);
- switch (seg->type) {
- case PAYLOAD_SEGMENT_BSS:
- dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
- memset(dest, 0, dest_len);
- break;
- case PAYLOAD_SEGMENT_ENTRY: {
- dprintf(1, "Calling addr %p\n", dest);
- void (*func)() = dest;
- func();
- return;
- }
- default:
- dprintf(3, "Segment %x %d@%p -> %d@%p\n"
- , seg->type, src_len, src, dest_len, dest);
- if (seg->compression == cpu_to_be32(CBFS_COMPRESS_NONE)) {
- if (src_len > dest_len)
- src_len = dest_len;
- memcpy(dest, src, src_len);
- } else if (CONFIG_LZMA
- && seg->compression == cpu_to_be32(CBFS_COMPRESS_LZMA)) {
- int ret = ulzma(dest, dest_len, src, src_len);
- if (ret < 0)
- return;
- src_len = ret;
- } else {
- dprintf(1, "No support for compression type %x\n"
- , seg->compression);
- return;
- }
- if (dest_len > src_len)
- memset(dest + src_len, 0, dest_len - src_len);
- break;
- }
- seg++;
- }
-}
-
-// Register payloads in "img/" directory with boot system.
-void
-cbfs_payload_setup(void)
-{
- if (!CONFIG_COREBOOT_FLASH)
- return;
- struct romfile_s *file = NULL;
- for (;;) {
- file = romfile_findprefix("img/", file);
- if (!file)
- break;
- struct cbfs_romfile_s *cfile;
- cfile = container_of(file, struct cbfs_romfile_s, file);
- const char *filename = file->name;
- char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]);
- boot_add_cbfs(cfile->fhdr, desc, bootprio_find_named_rom(filename, 0));
- }
-}
+++ /dev/null
-// Compatibility Support Module (CSM) for UEFI / EDK-II
-//
-// Copyright © 2013 Intel Corporation
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h" // CONFIG_*
-#include "csm.h"
-#include "util.h" // checksum
-#include "bregs.h"
-#include "optionroms.h"
-#include "hw/pci.h"
-#include "memmap.h"
-#include "biosvar.h"
-#include "post.h"
-#include "acpi.h"
-#include "boot.h"
-#include "smbios.h"
-#include "hw/pic.h"
-
-struct rsdp_descriptor csm_rsdp VARFSEG __aligned(16);
-
-EFI_COMPATIBILITY16_TABLE csm_compat_table VARFSEG __aligned(16) = {
- .Signature = 0x24454649,
- .TableChecksum = 0 /* Filled in by checkrom.py */,
- .TableLength = sizeof(csm_compat_table),
- .Compatibility16CallSegment = SEG_BIOS,
- .Compatibility16CallOffset = 0 /* Filled in by checkrom.py */,
- .OemIdStringPointer = (u32)"SeaBIOS",
- .AcpiRsdPtrPointer = (u32)&csm_rsdp,
-};
-
-EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
-EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table;
-
-static u16 PICMask = PIC_IRQMASK_DEFAULT;
-
-extern void __csm_return(struct bregs *regs) __noreturn;
-
-static void
-csm_return(struct bregs *regs)
-{
- dprintf(3, "handle_csm returning AX=%04x\n", regs->ax);
-
- PICMask = pic_irqmask_read();
- __csm_return(regs);
-}
-
-static void
-csm_maininit(struct bregs *regs)
-{
- interface_init();
- pci_probe_devices();
-
- csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
- csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
-
- regs->ax = 0;
-
- csm_return(regs);
-}
-
-/* Legacy16InitializeYourself */
-static void
-handle_csm_0000(struct bregs *regs)
-{
- dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es,
- regs->bx);
-
- csm_init_table = MAKE_FLATPTR(regs->es, regs->bx);
-
- dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB);
- dprintf(3, "HiPmmMemory %08x\n", csm_init_table->HiPmmMemory);
- dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes);
- dprintf(3, "ReverseThunk %04x:%04x\n", csm_init_table->ReverseThunkCallSegment,
- csm_init_table->ReverseThunkCallOffset);
- dprintf(3, "NumE820Entries %08x\n", csm_init_table->NumberE820Entries);
- dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb);
- dprintf(3, "ThunkStart %08x\n", csm_init_table->ThunkStart);
- dprintf(3, "ThunkSize %08x\n", csm_init_table->ThunkSizeInBytes);
- dprintf(3, "LoPmmMemory %08x\n", csm_init_table->LowPmmMemory);
- dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes);
-
- csm_malloc_preinit(csm_init_table->LowPmmMemory,
- csm_init_table->LowPmmMemorySizeInBytes,
- csm_init_table->HiPmmMemory,
- csm_init_table->HiPmmMemorySizeInBytes);
- reloc_preinit(csm_maininit, regs);
-}
-
-/* Legacy16UpdateBbs */
-static void
-handle_csm_0001(struct bregs *regs)
-{
- if (!CONFIG_BOOT) {
- regs->ax = 1;
- return;
- }
-
- dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx);
-
- csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx);
- dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion);
- dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion);
- dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable);
- dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable);
- dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength);
-// dprintf(3, "SioData %08x\n", csm_boot_table->SioData);
- dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType);
- dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask);
- dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries);
-// dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo);
- dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries);
- dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable);
- dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable);
- dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb);
- dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable);
-
- regs->ax = 0;
-}
-
-/* PrepareToBoot */
-static void
-handle_csm_0002(struct bregs *regs)
-{
- if (!CONFIG_BOOT) {
- regs->ax = 1;
- return;
- }
-
- dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
-
- struct e820entry *p = (void *)csm_compat_table.E820Pointer;
- int i;
- for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++)
- add_e820(p[i].start, p[i].size, p[i].type);
-
- if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) {
- u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes;
- add_e820(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED);
- }
-
- // For PCIBIOS 1ab10e
- if (csm_compat_table.IrqRoutingTablePointer &&
- csm_compat_table.IrqRoutingTableLength) {
- PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer;
- dprintf(3, "CSM PIRQ table at %p\n", PirAddr);
- }
-
- // For find_resume_vector()... and find_acpi_features()
- if (csm_rsdp.signature == RSDP_SIGNATURE) {
- RsdpAddr = &csm_rsdp;
- dprintf(3, "CSM ACPI RSDP at %p\n", RsdpAddr);
-
- find_acpi_features();
- }
-
- // SMBIOS table needs to be copied into the f-seg
- // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it
- if (csm_boot_table->SmbiosTable && !SMBiosAddr)
- copy_smbios((void *)csm_boot_table->SmbiosTable);
-
- // MPTABLE is just there; we don't care where.
-
- // EFI may have reinitialised the video using its *own* driver.
- enable_vga_console();
-
- // EFI fills this in for us. Zero it for now...
- struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
- bda->hdcount = 0;
-
- mathcp_setup();
- timer_setup();
- clock_setup();
- device_hardware_setup();
- wait_threads();
- interactive_bootmenu();
-
- prepareboot();
-
- regs->ax = 0;
-}
-
-/* Boot */
-static void
-handle_csm_0003(struct bregs *regs)
-{
- if (!CONFIG_BOOT) {
- regs->ax = 1;
- return;
- }
-
- dprintf(3, "Boot\n");
-
- startBoot();
-
- regs->ax = 1;
-}
-
-/* Legacy16DispatchOprom */
-static void
-handle_csm_0005(struct bregs *regs)
-{
- EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx);
- struct rom_header *rom;
- u16 bdf;
-
- if (!CONFIG_OPTIONROMS) {
- regs->ax = 1;
- return;
- }
-
- dprintf(3, "Legacy16DispatchOprom rom %p\n", table);
-
- dprintf(3, "OpromSegment %04x\n", table->OpromSegment);
- dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
- dprintf(3, "PnPInstallationCheck %04x:%04x\n",
- table->PnPInstallationCheckSegment,
- table->PnPInstallationCheckOffset);
- dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
-
- rom = MAKE_FLATPTR(table->OpromSegment, 0);
- bdf = pci_bus_devfn_to_bdf(table->PciBus, table->PciDeviceFunction);
-
- rom_reserve(rom->size * 512);
-
- // XX PnP seg/ofs should never be other than default
- callrom(rom, bdf);
-
- rom_confirm(rom->size * 512);
-
- regs->bx = 0; // FIXME
- regs->ax = 0;
-}
-
-/* Legacy16GetTableAddress */
-static void
-handle_csm_0006(struct bregs *regs)
-{
- u16 size = regs->cx;
- u16 align = regs->dx;
- u16 region = regs->bx; // (1 for F000 seg, 2 for E000 seg, 0 for either)
- void *chunk = NULL;
-
- if (!region)
- region = 3;
-
- dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n",
- size, align, region);
-
- if (region & 2)
- chunk = pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
- if (!chunk && (region & 1))
- chunk = pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, align);
-
- dprintf(3, "Legacy16GetTableAddress size %x align %x region %d yields %p\n",
- size, align, region, chunk);
- if (chunk) {
- regs->ds = FLATPTR_TO_SEG(chunk);
- regs->bx = FLATPTR_TO_OFFSET(chunk);
- regs->ax = 0;
- } else {
- regs->ax = 1;
- }
-}
-
-void VISIBLE32INIT
-handle_csm(struct bregs *regs)
-{
- ASSERT32FLAT();
-
- if (!CONFIG_CSM)
- return;
-
- dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax);
-
- pic_irqmask_write(PICMask);
-
- switch(regs->ax) {
- case 0000: handle_csm_0000(regs); break;
- case 0001: handle_csm_0001(regs); break;
- case 0002: handle_csm_0002(regs); break;
- case 0003: handle_csm_0003(regs); break;
-// case 0004: handle_csm_0004(regs); break;
- case 0005: handle_csm_0005(regs); break;
- case 0006: handle_csm_0006(regs); break;
-// case 0007: handle_csm_0007(regs); break;
-// case 0008: hamdle_csm_0008(regs); break;
- default: regs->al = 1;
- }
-
- csm_return(regs);
-}
-
-int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave)
-{
- if (!csm_boot_table)
- return -1;
- BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
- int index = 1 + (chanid * 2) + slave;
- dprintf(3, "CSM bootprio for ATA%d,%d (index %d) is %d\n", chanid, slave,
- index, bbs[index].BootPriority);
- return bbs[index].BootPriority;
-}
-
-int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid)
-{
- if (!csm_boot_table)
- return -1;
- BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
- dprintf(3, "CSM bootprio for FDC is %d\n", bbs[0].BootPriority);
- return bbs[0].BootPriority;
-}
-
-int csm_bootprio_pci(struct pci_device *pci)
-{
- if (!csm_boot_table)
- return -1;
- BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
- int i;
-
- for (i = 5; i < csm_boot_table->NumberBbsEntries; i++) {
- if (pci->bdf == pci_to_bdf(bbs[i].Bus, bbs[i].Device, bbs[i].Function)) {
- dprintf(3, "CSM bootprio for PCI(%d,%d,%d) is %d\n", bbs[i].Bus,
- bbs[i].Device, bbs[i].Function, bbs[i].BootPriority);
- return bbs[i].BootPriority;
- }
- }
- return -1;
-}
+++ /dev/null
-#ifndef __CSM_H
-#define __CSM_H
-
-#include "types.h"
-
-#define UINT8 u8
-#define UINT16 u16
-#define UINT32 u32
-
-// csm.c
-struct pci_device;
-int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid);
-int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave);
-int csm_bootprio_pci(struct pci_device *pci);
-
-#include "LegacyBios.h"
-
-#endif // __CSM_H
+++ /dev/null
-#ifndef __DEV_Q35_H
-#define __DEV_Q35_H
-
-#include "types.h" // u16
-
-#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0
-#define Q35_HOST_BRIDGE_PAM0 0x90
-#define Q35_HOST_BRIDGE_SMRAM 0x9d
-#define Q35_HOST_BRIDGE_PCIEXBAR 0x60
-#define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024)
-#define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xb0000000
-#define Q35_HOST_BRIDGE_PCIEXBAREN ((u64)1)
-#define Q35_HOST_PCIE_PCI_SEGMENT 0
-#define Q35_HOST_PCIE_START_BUS_NUMBER 0
-#define Q35_HOST_PCIE_END_BUS_NUMBER 255
-
-#define PCI_DEVICE_ID_INTEL_ICH9_LPC 0x2918
-#define ICH9_LPC_PMBASE 0x40
-#define ICH9_LPC_PMBASE_RTE 0x1
-
-#define ICH9_LPC_ACPI_CTRL 0x44
-#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80
-#define ICH9_LPC_PIRQA_ROUT 0x60
-#define ICH9_LPC_PIRQE_ROUT 0x68
-#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80
-#define ICH9_LPC_PORT_ELCR1 0x4d0
-#define ICH9_LPC_PORT_ELCR2 0x4d1
-#define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930
-#define ICH9_SMB_SMB_BASE 0x20
-#define ICH9_SMB_HOSTC 0x40
-#define ICH9_SMB_HOSTC_HST_EN 0x01
-
-#define ICH9_ACPI_ENABLE 0x2
-#define ICH9_ACPI_DISABLE 0x3
-
-/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
-#define ICH9_PMIO_GPE0_STS 0x20
-#define ICH9_PMIO_GPE0_BLK_LEN 0x10
-#define ICH9_PMIO_SMI_EN 0x30
-#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5)
-
-/* FADT ACPI_ENABLE/ACPI_DISABLE */
-#define ICH9_APM_ACPI_ENABLE 0x2
-#define ICH9_APM_ACPI_DISABLE 0x3
-
-#endif // dev-q35.h
--- /dev/null
+/** @file
+ The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage
+ under EFI and Legacy OS boot. This file also includes all the related
+ COMPATIBILIY16 structures and defintions.
+
+ Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow
+ well known naming conventions.
+
+ Thunk is the code that switches from 32-bit protected environment into the 16-bit real-mode
+ environment. Reverse thunk is the code that does the opposite.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This protocol is defined in Framework for EFI Compatibility Support Module spec
+ Version 0.97.
+
+**/
+
+#ifndef _EFI_LEGACY_BIOS_H_
+#define _EFI_LEGACY_BIOS_H_
+
+///
+///
+///
+#pragma pack(1)
+
+typedef UINT8 SERIAL_MODE;
+typedef UINT8 PARALLEL_MODE;
+
+#define EFI_COMPATIBILITY16_TABLE_SIGNATURE SIGNATURE_32 ('I', 'F', 'E', '$')
+
+///
+/// There is a table located within the traditional BIOS in either the 0xF000:xxxx or 0xE000:xxxx
+/// physical address range. It is located on a 16-byte boundary and provides the physical address of the
+/// entry point for the Compatibility16 functions. These functions provide the platform-specific
+/// information that is required by the generic EfiCompatibility code. The functions are invoked via
+/// thunking by using EFI_LEGACY_BIOS_PROTOCOL.FarCall86() with the 32-bit physical
+/// entry point.
+///
+typedef struct {
+ ///
+ /// The string "$EFI" denotes the start of the EfiCompatibility table. Byte 0 is "I," byte
+ /// 1 is "F," byte 2 is "E," and byte 3 is "$" and is normally accessed as a DWORD or UINT32.
+ ///
+ UINT32 Signature;
+
+ ///
+ /// The value required such that byte checksum of TableLength equals zero.
+ ///
+ UINT8 TableChecksum;
+
+ ///
+ /// The length of this table.
+ ///
+ UINT8 TableLength;
+
+ ///
+ /// The major EFI revision for which this table was generated.
+ ///
+ UINT8 EfiMajorRevision;
+
+ ///
+ /// The minor EFI revision for which this table was generated.
+ ///
+ UINT8 EfiMinorRevision;
+
+ ///
+ /// The major revision of this table.
+ ///
+ UINT8 TableMajorRevision;
+
+ ///
+ /// The minor revision of this table.
+ ///
+ UINT8 TableMinorRevision;
+
+ ///
+ /// Reserved for future usage.
+ ///
+ UINT16 Reserved;
+
+ ///
+ /// The segment of the entry point within the traditional BIOS for Compatibility16 functions.
+ ///
+ UINT16 Compatibility16CallSegment;
+
+ ///
+ /// The offset of the entry point within the traditional BIOS for Compatibility16 functions.
+ ///
+ UINT16 Compatibility16CallOffset;
+
+ ///
+ /// The segment of the entry point within the traditional BIOS for EfiCompatibility
+ /// to invoke the PnP installation check.
+ ///
+ UINT16 PnPInstallationCheckSegment;
+
+ ///
+ /// The Offset of the entry point within the traditional BIOS for EfiCompatibility
+ /// to invoke the PnP installation check.
+ ///
+ UINT16 PnPInstallationCheckOffset;
+
+ ///
+ /// EFI system resources table. Type EFI_SYSTEM_TABLE is defined in the IntelPlatform
+ ///Innovation Framework for EFI Driver Execution Environment Core Interface Specification (DXE CIS).
+ ///
+ UINT32 EfiSystemTable;
+
+ ///
+ /// The address of an OEM-provided identifier string. The string is null terminated.
+ ///
+ UINT32 OemIdStringPointer;
+
+ ///
+ /// The 32-bit physical address where ACPI RSD PTR is stored within the traditional
+ /// BIOS. The remained of the ACPI tables are located at their EFI addresses. The size
+ /// reserved is the maximum for ACPI 2.0. The EfiCompatibility will fill in the ACPI
+ /// RSD PTR with either the ACPI 1.0b or 2.0 values.
+ ///
+ UINT32 AcpiRsdPtrPointer;
+
+ ///
+ /// The OEM revision number. Usage is undefined but provided for OEM module usage.
+ ///
+ UINT16 OemRevision;
+
+ ///
+ /// The 32-bit physical address where INT15 E820 data is stored within the traditional
+ /// BIOS. The EfiCompatibility code will fill in the E820Pointer value and copy the
+ /// data to the indicated area.
+ ///
+ UINT32 E820Pointer;
+
+ ///
+ /// The length of the E820 data and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 E820Length;
+
+ ///
+ /// The 32-bit physical address where the $PIR table is stored in the traditional BIOS.
+ /// The EfiCompatibility code will fill in the IrqRoutingTablePointer value and
+ /// copy the data to the indicated area.
+ ///
+ UINT32 IrqRoutingTablePointer;
+
+ ///
+ /// The length of the $PIR table and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 IrqRoutingTableLength;
+
+ ///
+ /// The 32-bit physical address where the MP table is stored in the traditional BIOS.
+ /// The EfiCompatibility code will fill in the MpTablePtr value and copy the data
+ /// to the indicated area.
+ ///
+ UINT32 MpTablePtr;
+
+ ///
+ /// The length of the MP table and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 MpTableLength;
+
+ ///
+ /// The segment of the OEM-specific INT table/code.
+ ///
+ UINT16 OemIntSegment;
+
+ ///
+ /// The offset of the OEM-specific INT table/code.
+ ///
+ UINT16 OemIntOffset;
+
+ ///
+ /// The segment of the OEM-specific 32-bit table/code.
+ ///
+ UINT16 Oem32Segment;
+
+ ///
+ /// The offset of the OEM-specific 32-bit table/code.
+ ///
+ UINT16 Oem32Offset;
+
+ ///
+ /// The segment of the OEM-specific 16-bit table/code.
+ ///
+ UINT16 Oem16Segment;
+
+ ///
+ /// The offset of the OEM-specific 16-bit table/code.
+ ///
+ UINT16 Oem16Offset;
+
+ ///
+ /// The segment of the TPM binary passed to 16-bit CSM.
+ ///
+ UINT16 TpmSegment;
+
+ ///
+ /// The offset of the TPM binary passed to 16-bit CSM.
+ ///
+ UINT16 TpmOffset;
+
+ ///
+ /// A pointer to a string identifying the independent BIOS vendor.
+ ///
+ UINT32 IbvPointer;
+
+ ///
+ /// This field is NULL for all systems not supporting PCI Express. This field is the base
+ /// value of the start of the PCI Express memory-mapped configuration registers and
+ /// must be filled in prior to EfiCompatibility code issuing the Compatibility16 function
+ /// Compatibility16InitializeYourself().
+ /// Compatibility16InitializeYourself() is defined in Compatability16
+ /// Functions.
+ ///
+ UINT32 PciExpressBase;
+
+ ///
+ /// Maximum PCI bus number assigned.
+ ///
+ UINT8 LastPciBus;
+} EFI_COMPATIBILITY16_TABLE;
+
+///
+/// Functions provided by the CSM binary which communicate between the EfiCompatibility
+/// and Compatability16 code.
+///
+/// Inconsistent with the specification here:
+/// The member's name started with "Compatibility16" [defined in Intel Framework
+/// Compatibility Support Module Specification / 0.97 version]
+/// has been changed to "Legacy16" since keeping backward compatible.
+///
+typedef enum {
+ ///
+ /// Causes the Compatibility16 code to do any internal initialization required.
+ /// Input:
+ /// AX = Compatibility16InitializeYourself
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE
+ /// Return:
+ /// AX = Return Status codes
+ ///
+ Legacy16InitializeYourself = 0x0000,
+
+ ///
+ /// Causes the Compatibility16 BIOS to perform any drive number translations to match the boot sequence.
+ /// Input:
+ /// AX = Compatibility16UpdateBbs
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE
+ /// Return:
+ /// AX = Returned status codes
+ ///
+ Legacy16UpdateBbs = 0x0001,
+
+ ///
+ /// Allows the Compatibility16 code to perform any final actions before booting. The Compatibility16
+ /// code is read/write.
+ /// Input:
+ /// AX = Compatibility16PrepareToBoot
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure
+ /// Return:
+ /// AX = Returned status codes
+ ///
+ Legacy16PrepareToBoot = 0x0002,
+
+ ///
+ /// Causes the Compatibility16 BIOS to boot. The Compatibility16 code is Read/Only.
+ /// Input:
+ /// AX = Compatibility16Boot
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16Boot = 0x0003,
+
+ ///
+ /// Allows the Compatibility16 code to get the last device from which a boot was attempted. This is
+ /// stored in CMOS and is the priority number of the last attempted boot device.
+ /// Input:
+ /// AX = Compatibility16RetrieveLastBootDevice
+ /// Output:
+ /// AX = Returned status codes
+ /// BX = Priority number of the boot device.
+ ///
+ Legacy16RetrieveLastBootDevice = 0x0004,
+
+ ///
+ /// Allows the Compatibility16 code rehook INT13, INT18, and/or INT19 after dispatching a legacy OpROM.
+ /// Input:
+ /// AX = Compatibility16DispatchOprom
+ /// ES:BX = Pointer to EFI_DISPATCH_OPROM_TABLE
+ /// Output:
+ /// AX = Returned status codes
+ /// BX = Number of non-BBS-compliant devices found. Equals 0 if BBS compliant.
+ ///
+ Legacy16DispatchOprom = 0x0005,
+
+ ///
+ /// Finds a free area in the 0xFxxxx or 0xExxxx region of the specified length and returns the address
+ /// of that region.
+ /// Input:
+ /// AX = Compatibility16GetTableAddress
+ /// BX = Allocation region
+ /// 00 = Allocate from either 0xE0000 or 0xF0000 64 KB blocks.
+ /// Bit 0 = 1 Allocate from 0xF0000 64 KB block
+ /// Bit 1 = 1 Allocate from 0xE0000 64 KB block
+ /// CX = Requested length in bytes.
+ /// DX = Required address alignment. Bit mapped. First non-zero bit from the right is the alignment.
+ /// Output:
+ /// AX = Returned status codes
+ /// DS:BX = Address of the region
+ ///
+ Legacy16GetTableAddress = 0x0006,
+
+ ///
+ /// Enables the EfiCompatibility module to do any nonstandard processing of keyboard LEDs or state.
+ /// Input:
+ /// AX = Compatibility16SetKeyboardLeds
+ /// CL = LED status.
+ /// Bit 0 Scroll Lock 0 = Off
+ /// Bit 1 NumLock
+ /// Bit 2 Caps Lock
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16SetKeyboardLeds = 0x0007,
+
+ ///
+ /// Enables the EfiCompatibility module to install an interrupt handler for PCI mass media devices that
+ /// do not have an OpROM associated with them. An example is SATA.
+ /// Input:
+ /// AX = Compatibility16InstallPciHandler
+ /// ES:BX = Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16InstallPciHandler = 0x0008
+} EFI_COMPATIBILITY_FUNCTIONS;
+
+
+///
+/// EFI_DISPATCH_OPROM_TABLE
+///
+typedef struct {
+ UINT16 PnPInstallationCheckSegment; ///< A pointer to the PnpInstallationCheck data structure.
+ UINT16 PnPInstallationCheckOffset; ///< A pointer to the PnpInstallationCheck data structure.
+ UINT16 OpromSegment; ///< The segment where the OpROM was placed. Offset is assumed to be 3.
+ UINT8 PciBus; ///< The PCI bus.
+ UINT8 PciDeviceFunction; ///< The PCI device * 0x08 | PCI function.
+ UINT8 NumberBbsEntries; ///< The number of valid BBS table entries upon entry and exit. The IBV code may
+ ///< increase this number, if BBS-compliant devices also hook INTs in order to force the
+ ///< OpROM BIOS Setup to be executed.
+ UINT32 BbsTablePointer; ///< A pointer to the BBS table.
+ UINT16 RuntimeSegment; ///< The segment where the OpROM can be relocated to. If this value is 0x0000, this
+ ///< means that the relocation of this run time code is not supported.
+ ///< Inconsistent with specification here:
+ ///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version]
+ ///< has been changed to "RuntimeSegment" since keeping backward compatible.
+
+} EFI_DISPATCH_OPROM_TABLE;
+
+///
+/// EFI_TO_COMPATIBILITY16_INIT_TABLE
+///
+typedef struct {
+ ///
+ /// Starting address of memory under 1 MB. The ending address is assumed to be 640 KB or 0x9FFFF.
+ ///
+ UINT32 BiosLessThan1MB;
+
+ ///
+ /// The starting address of the high memory block.
+ ///
+ UINT32 HiPmmMemory;
+
+ ///
+ /// The length of high memory block.
+ ///
+ UINT32 HiPmmMemorySizeInBytes;
+
+ ///
+ /// The segment of the reverse thunk call code.
+ ///
+ UINT16 ReverseThunkCallSegment;
+
+ ///
+ /// The offset of the reverse thunk call code.
+ ///
+ UINT16 ReverseThunkCallOffset;
+
+ ///
+ /// The number of E820 entries copied to the Compatibility16 BIOS.
+ ///
+ UINT32 NumberE820Entries;
+
+ ///
+ /// The amount of usable memory above 1 MB, e.g., E820 type 1 memory.
+ ///
+ UINT32 OsMemoryAbove1Mb;
+
+ ///
+ /// The start of thunk code in main memory. Memory cannot be used by BIOS or PMM.
+ ///
+ UINT32 ThunkStart;
+
+ ///
+ /// The size of the thunk code.
+ ///
+ UINT32 ThunkSizeInBytes;
+
+ ///
+ /// Starting address of memory under 1 MB.
+ ///
+ UINT32 LowPmmMemory;
+
+ ///
+ /// The length of low Memory block.
+ ///
+ UINT32 LowPmmMemorySizeInBytes;
+} EFI_TO_COMPATIBILITY16_INIT_TABLE;
+
+///
+/// DEVICE_PRODUCER_SERIAL.
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the serial port.
+ UINT8 Irq; ///< IRQ assigned to the serial port.
+ SERIAL_MODE Mode; ///< Mode of serial port. Values are defined below.
+} DEVICE_PRODUCER_SERIAL;
+
+///
+/// DEVICE_PRODUCER_SERIAL's modes.
+///@{
+#define DEVICE_SERIAL_MODE_NORMAL 0x00
+#define DEVICE_SERIAL_MODE_IRDA 0x01
+#define DEVICE_SERIAL_MODE_ASK_IR 0x02
+#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00
+#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10
+///@)
+
+///
+/// DEVICE_PRODUCER_PARALLEL.
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the parallel port.
+ UINT8 Irq; ///< IRQ assigned to the parallel port.
+ UINT8 Dma; ///< DMA assigned to the parallel port.
+ PARALLEL_MODE Mode; ///< Mode of the parallel port. Values are defined below.
+} DEVICE_PRODUCER_PARALLEL;
+
+///
+/// DEVICE_PRODUCER_PARALLEL's modes.
+///@{
+#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00
+#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01
+#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02
+#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03
+///@}
+
+///
+/// DEVICE_PRODUCER_FLOPPY
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the floppy.
+ UINT8 Irq; ///< IRQ assigned to the floppy.
+ UINT8 Dma; ///< DMA assigned to the floppy.
+ UINT8 NumberOfFloppy; ///< Number of floppies in the system.
+} DEVICE_PRODUCER_FLOPPY;
+
+///
+/// LEGACY_DEVICE_FLAGS
+///
+typedef struct {
+ UINT32 A20Kybd : 1; ///< A20 controller by keyboard controller.
+ UINT32 A20Port90 : 1; ///< A20 controlled by port 0x92.
+ UINT32 Reserved : 30; ///< Reserved for future usage.
+} LEGACY_DEVICE_FLAGS;
+
+///
+/// DEVICE_PRODUCER_DATA_HEADER
+///
+typedef struct {
+ DEVICE_PRODUCER_SERIAL Serial[4]; ///< Data for serial port x. Type DEVICE_PRODUCER_SERIAL is defined below.
+ DEVICE_PRODUCER_PARALLEL Parallel[3]; ///< Data for parallel port x. Type DEVICE_PRODUCER_PARALLEL is defined below.
+ DEVICE_PRODUCER_FLOPPY Floppy; ///< Data for floppy. Type DEVICE_PRODUCER_FLOPPY is defined below.
+ UINT8 MousePresent; ///< Flag to indicate if mouse is present.
+ LEGACY_DEVICE_FLAGS Flags; ///< Miscellaneous Boolean state information passed to CSM.
+} DEVICE_PRODUCER_DATA_HEADER;
+
+///
+/// ATAPI_IDENTIFY
+///
+typedef struct {
+ UINT16 Raw[256]; ///< Raw data from the IDE IdentifyDrive command.
+} ATAPI_IDENTIFY;
+
+///
+/// HDD_INFO
+///
+typedef struct {
+ ///
+ /// Status of IDE device. Values are defined below. There is one HDD_INFO structure
+ /// per IDE controller. The IdentifyDrive is per drive. Index 0 is master and index
+ /// 1 is slave.
+ ///
+ UINT16 Status;
+
+ ///
+ /// PCI bus of IDE controller.
+ ///
+ UINT32 Bus;
+
+ ///
+ /// PCI device of IDE controller.
+ ///
+ UINT32 Device;
+
+ ///
+ /// PCI function of IDE controller.
+ ///
+ UINT32 Function;
+
+ ///
+ /// Command ports base address.
+ ///
+ UINT16 CommandBaseAddress;
+
+ ///
+ /// Control ports base address.
+ ///
+ UINT16 ControlBaseAddress;
+
+ ///
+ /// Bus master address.
+ ///
+ UINT16 BusMasterAddress;
+
+ UINT8 HddIrq;
+
+ ///
+ /// Data that identifies the drive data; one per possible attached drive.
+ ///
+ ATAPI_IDENTIFY IdentifyDrive[2];
+} HDD_INFO;
+
+///
+/// HDD_INFO status bits
+///
+#define HDD_PRIMARY 0x01
+#define HDD_SECONDARY 0x02
+#define HDD_MASTER_ATAPI_CDROM 0x04
+#define HDD_SLAVE_ATAPI_CDROM 0x08
+#define HDD_MASTER_IDE 0x20
+#define HDD_SLAVE_IDE 0x40
+#define HDD_MASTER_ATAPI_ZIPDISK 0x10
+#define HDD_SLAVE_ATAPI_ZIPDISK 0x80
+
+///
+/// BBS_STATUS_FLAGS;\.
+///
+typedef struct {
+ UINT16 OldPosition : 4; ///< Prior priority.
+ UINT16 Reserved1 : 4; ///< Reserved for future use.
+ UINT16 Enabled : 1; ///< If 0, ignore this entry.
+ UINT16 Failed : 1; ///< 0 = Not known if boot failure occurred.
+ ///< 1 = Boot attempted failed.
+
+ ///
+ /// State of media present.
+ /// 00 = No bootable media is present in the device.
+ /// 01 = Unknown if a bootable media present.
+ /// 10 = Media is present and appears bootable.
+ /// 11 = Reserved.
+ ///
+ UINT16 MediaPresent : 2;
+ UINT16 Reserved2 : 4; ///< Reserved for future use.
+} BBS_STATUS_FLAGS;
+
+///
+/// BBS_TABLE, device type values & boot priority values.
+///
+typedef struct {
+ ///
+ /// The boot priority for this boot device. Values are defined below.
+ ///
+ UINT16 BootPriority;
+
+ ///
+ /// The PCI bus for this boot device.
+ ///
+ UINT32 Bus;
+
+ ///
+ /// The PCI device for this boot device.
+ ///
+ UINT32 Device;
+
+ ///
+ /// The PCI function for the boot device.
+ ///
+ UINT32 Function;
+
+ ///
+ /// The PCI class for this boot device.
+ ///
+ UINT8 Class;
+
+ ///
+ /// The PCI Subclass for this boot device.
+ ///
+ UINT8 SubClass;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
+ ///
+ UINT16 MfgStringOffset;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
+ ///
+ UINT16 MfgStringSegment;
+
+ ///
+ /// BBS device type. BBS device types are defined below.
+ ///
+ UINT16 DeviceType;
+
+ ///
+ /// Status of this boot device. Type BBS_STATUS_FLAGS is defined below.
+ ///
+ BBS_STATUS_FLAGS StatusFlags;
+
+ ///
+ /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
+ /// BCV devices.
+ ///
+ UINT16 BootHandlerOffset;
+
+ ///
+ /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
+ /// BCV devices.
+ ///
+ UINT16 BootHandlerSegment;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing this device.
+ ///
+ UINT16 DescStringOffset;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing this device.
+ ///
+ UINT16 DescStringSegment;
+
+ ///
+ /// Reserved.
+ ///
+ UINT32 InitPerReserved;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq13Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq18Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq19Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq40Handler;
+ UINT8 AssignedDriveNumber;
+ UINT32 AdditionalIrq41Handler;
+ UINT32 AdditionalIrq46Handler;
+ UINT32 IBV1;
+ UINT32 IBV2;
+} BBS_TABLE;
+
+///
+/// BBS device type values
+///@{
+#define BBS_FLOPPY 0x01
+#define BBS_HARDDISK 0x02
+#define BBS_CDROM 0x03
+#define BBS_PCMCIA 0x04
+#define BBS_USB 0x05
+#define BBS_EMBED_NETWORK 0x06
+#define BBS_BEV_DEVICE 0x80
+#define BBS_UNKNOWN 0xff
+///@}
+
+///
+/// BBS boot priority values
+///@{
+#define BBS_DO_NOT_BOOT_FROM 0xFFFC
+#define BBS_LOWEST_PRIORITY 0xFFFD
+#define BBS_UNPRIORITIZED_ENTRY 0xFFFE
+#define BBS_IGNORE_ENTRY 0xFFFF
+///@}
+
+///
+/// SMM_ATTRIBUTES
+///
+typedef struct {
+ ///
+ /// Access mechanism used to generate the soft SMI. Defined types are below. The other
+ /// values are reserved for future usage.
+ ///
+ UINT16 Type : 3;
+
+ ///
+ /// The size of "port" in bits. Defined values are below.
+ ///
+ UINT16 PortGranularity : 3;
+
+ ///
+ /// The size of data in bits. Defined values are below.
+ ///
+ UINT16 DataGranularity : 3;
+
+ ///
+ /// Reserved for future use.
+ ///
+ UINT16 Reserved : 7;
+} SMM_ATTRIBUTES;
+
+///
+/// SMM_ATTRIBUTES type values.
+///@{
+#define STANDARD_IO 0x00
+#define STANDARD_MEMORY 0x01
+///@}
+
+///
+/// SMM_ATTRIBUTES port size constants.
+///@{
+#define PORT_SIZE_8 0x00
+#define PORT_SIZE_16 0x01
+#define PORT_SIZE_32 0x02
+#define PORT_SIZE_64 0x03
+///@}
+
+///
+/// SMM_ATTRIBUTES data size constants.
+///@{
+#define DATA_SIZE_8 0x00
+#define DATA_SIZE_16 0x01
+#define DATA_SIZE_32 0x02
+#define DATA_SIZE_64 0x03
+///@}
+
+///
+/// SMM_FUNCTION & relating constants.
+///
+typedef struct {
+ UINT16 Function : 15;
+ UINT16 Owner : 1;
+} SMM_FUNCTION;
+
+///
+/// SMM_FUNCTION Function constants.
+///@{
+#define INT15_D042 0x0000
+#define GET_USB_BOOT_INFO 0x0001
+#define DMI_PNP_50_57 0x0002
+///@}
+
+///
+/// SMM_FUNCTION Owner constants.
+///@{
+#define STANDARD_OWNER 0x0
+#define OEM_OWNER 0x1
+///@}
+
+///
+/// This structure assumes both port and data sizes are 1. SmmAttribute must be
+/// properly to reflect that assumption.
+///
+typedef struct {
+ ///
+ /// Describes the access mechanism, SmmPort, and SmmData sizes. Type
+ /// SMM_ATTRIBUTES is defined below.
+ ///
+ SMM_ATTRIBUTES SmmAttributes;
+
+ ///
+ /// Function Soft SMI is to perform. Type SMM_FUNCTION is defined below.
+ ///
+ SMM_FUNCTION SmmFunction;
+
+ ///
+ /// SmmPort size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
+ ///
+ UINT8 SmmPort;
+
+ ///
+ /// SmmData size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
+ ///
+ UINT8 SmmData;
+} SMM_ENTRY;
+
+///
+/// SMM_TABLE
+///
+typedef struct {
+ UINT16 NumSmmEntries; ///< Number of entries represented by SmmEntry.
+ SMM_ENTRY SmmEntry; ///< One entry per function. Type SMM_ENTRY is defined below.
+} SMM_TABLE;
+
+///
+/// UDC_ATTRIBUTES
+///
+typedef struct {
+ ///
+ /// This bit set indicates that the ServiceAreaData is valid.
+ ///
+ UINT8 DirectoryServiceValidity : 1;
+
+ ///
+ /// This bit set indicates to use the Reserve Area Boot Code Address (RACBA) only if
+ /// DirectoryServiceValidity is 0.
+ ///
+ UINT8 RabcaUsedFlag : 1;
+
+ ///
+ /// This bit set indicates to execute hard disk diagnostics.
+ ///
+ UINT8 ExecuteHddDiagnosticsFlag : 1;
+
+ ///
+ /// Reserved for future use. Set to 0.
+ ///
+ UINT8 Reserved : 5;
+} UDC_ATTRIBUTES;
+
+///
+/// UD_TABLE
+///
+typedef struct {
+ ///
+ /// This field contains the bit-mapped attributes of the PARTIES information. Type
+ /// UDC_ATTRIBUTES is defined below.
+ ///
+ UDC_ATTRIBUTES Attributes;
+
+ ///
+ /// This field contains the zero-based device on which the selected
+ /// ServiceDataArea is present. It is 0 for master and 1 for the slave device.
+ ///
+ UINT8 DeviceNumber;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the parent device.
+ /// This index allows the user to reference the parent device information such as PCI
+ /// bus, device function.
+ ///
+ UINT8 BbsTableEntryNumberForParentDevice;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the boot entry.
+ ///
+ UINT8 BbsTableEntryNumberForBoot;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the HDD diagnostics entry.
+ ///
+ UINT8 BbsTableEntryNumberForHddDiag;
+
+ ///
+ /// The raw Beer data.
+ ///
+ UINT8 BeerData[128];
+
+ ///
+ /// The raw data of selected service area.
+ ///
+ UINT8 ServiceAreaData[64];
+} UD_TABLE;
+
+#define EFI_TO_LEGACY_MAJOR_VERSION 0x02
+#define EFI_TO_LEGACY_MINOR_VERSION 0x00
+#define MAX_IDE_CONTROLLER 8
+
+///
+/// EFI_TO_COMPATIBILITY16_BOOT_TABLE
+///
+typedef struct {
+ UINT16 MajorVersion; ///< The EfiCompatibility major version number.
+ UINT16 MinorVersion; ///< The EfiCompatibility minor version number.
+ UINT32 AcpiTable; ///< The location of the RSDT ACPI table. < 4G range.
+ UINT32 SmbiosTable; ///< The location of the SMBIOS table in EFI memory. < 4G range.
+ UINT32 SmbiosTableLength;
+ //
+ // Legacy SIO state
+ //
+ DEVICE_PRODUCER_DATA_HEADER SioData; ///< Standard traditional device information.
+ UINT16 DevicePathType; ///< The default boot type.
+ UINT16 PciIrqMask; ///< Mask of which IRQs have been assigned to PCI.
+ UINT32 NumberE820Entries; ///< Number of E820 entries. The number can change from the
+ ///< Compatibility16InitializeYourself() function.
+ //
+ // Controller & Drive Identify[2] per controller information
+ //
+ HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; ///< Hard disk drive information, including raw Identify Drive data.
+ UINT32 NumberBbsEntries; ///< Number of entries in the BBS table
+ UINT32 BbsTable; ///< A pointer to the BBS table. Type BBS_TABLE is defined below.
+ UINT32 SmmTable; ///< A pointer to the SMM table. Type SMM_TABLE is defined below.
+ UINT32 OsMemoryAbove1Mb; ///< The amount of usable memory above 1 MB, i.e. E820 type 1 memory. This value can
+ ///< differ from the value in EFI_TO_COMPATIBILITY16_INIT_TABLE as more
+ ///< memory may have been discovered.
+ UINT32 UnconventionalDeviceTable; ///< Information to boot off an unconventional device like a PARTIES partition. Type
+ ///< UD_TABLE is defined below.
+} EFI_TO_COMPATIBILITY16_BOOT_TABLE;
+
+///
+/// EFI_LEGACY_INSTALL_PCI_HANDLER
+///
+typedef struct {
+ UINT8 PciBus; ///< The PCI bus of the device.
+ UINT8 PciDeviceFun; ///< The PCI device in bits 7:3 and function in bits 2:0.
+ UINT8 PciSegment; ///< The PCI segment of the device.
+ UINT8 PciClass; ///< The PCI class code of the device.
+ UINT8 PciSubclass; ///< The PCI subclass code of the device.
+ UINT8 PciInterface; ///< The PCI interface code of the device.
+ //
+ // Primary section
+ //
+ UINT8 PrimaryIrq; ///< The primary device IRQ.
+ UINT8 PrimaryReserved; ///< Reserved.
+ UINT16 PrimaryControl; ///< The primary device control I/O base.
+ UINT16 PrimaryBase; ///< The primary device I/O base.
+ UINT16 PrimaryBusMaster; ///< The primary device bus master I/O base.
+ //
+ // Secondary Section
+ //
+ UINT8 SecondaryIrq; ///< The secondary device IRQ.
+ UINT8 SecondaryReserved; ///< Reserved.
+ UINT16 SecondaryControl; ///< The secondary device control I/O base.
+ UINT16 SecondaryBase; ///< The secondary device I/O base.
+ UINT16 SecondaryBusMaster; ///< The secondary device bus master I/O base.
+} EFI_LEGACY_INSTALL_PCI_HANDLER;
+
+#endif
--- /dev/null
+/****************************************************************
+ * CPU hotplug
+ ****************************************************************/
+
+Scope(\_SB) {
+ /* Objects filled in by run-time generated SSDT */
+ External(NTFY, MethodObj)
+ External(CPON, PkgObj)
+
+ /* Methods called by run-time generated SSDT Processor objects */
+ Method(CPMA, 1, NotSerialized) {
+ // _MAT method - create an madt apic buffer
+ // Arg0 = Processor ID = Local APIC ID
+ // Local0 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ // Local1 = Buffer (in madt apic form) to return
+ Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
+ // Update the processor id, lapic id, and enable/disable status
+ Store(Arg0, Index(Local1, 2))
+ Store(Arg0, Index(Local1, 3))
+ Store(Local0, Index(Local1, 4))
+ Return (Local1)
+ }
+ Method(CPST, 1, NotSerialized) {
+ // _STA method - return ON status of cpu
+ // Arg0 = Processor ID = Local APIC ID
+ // Local0 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ If (Local0) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+ Method(CPEJ, 2, NotSerialized) {
+ // _EJ0 method - eject callback
+ Sleep(200)
+ }
+
+ /* CPU hotplug notify method */
+ OperationRegion(PRST, SystemIO, 0xaf00, 32)
+ Field(PRST, ByteAcc, NoLock, Preserve) {
+ PRS, 256
+ }
+ Method(PRSC, 0) {
+ // Local5 = active cpu bitmap
+ Store(PRS, Local5)
+ // Local2 = last read byte from bitmap
+ Store(Zero, Local2)
+ // Local0 = Processor ID / APIC ID iterator
+ Store(Zero, Local0)
+ While (LLess(Local0, SizeOf(CPON))) {
+ // Local1 = CPON flag for this cpu
+ Store(DerefOf(Index(CPON, Local0)), Local1)
+ If (And(Local0, 0x07)) {
+ // Shift down previously read bitmap byte
+ ShiftRight(Local2, 1, Local2)
+ } Else {
+ // Read next byte from cpu bitmap
+ Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+ }
+ // Local3 = active state for this cpu
+ Store(And(Local2, 1), Local3)
+
+ If (LNotEqual(Local1, Local3)) {
+ // State change - update CPON with new state
+ Store(Local3, Index(CPON, Local0))
+ // Do CPU notify
+ If (LEqual(Local3, 1)) {
+ NTFY(Local0, 1)
+ } Else {
+ NTFY(Local0, 3)
+ }
+ }
+ Increment(Local0)
+ }
+ }
+}
--- /dev/null
+/****************************************************************
+ * Debugging
+ ****************************************************************/
+
+Scope(\) {
+ /* Debug Output */
+ OperationRegion(DBG, SystemIO, 0x0402, 0x01)
+ Field(DBG, ByteAcc, NoLock, Preserve) {
+ DBGB, 8,
+ }
+
+ /* Debug method - use this method to send output to the QEMU
+ * BIOS debug port. This method handles strings, integers,
+ * and buffers. For example: DBUG("abc") DBUG(0x123) */
+ Method(DBUG, 1) {
+ ToHexString(Arg0, Local0)
+ ToBuffer(Local0, Local0)
+ Subtract(SizeOf(Local0), 1, Local1)
+ Store(Zero, Local2)
+ While (LLess(Local2, Local1)) {
+ Store(DerefOf(Index(Local0, Local2)), DBGB)
+ Increment(Local2)
+ }
+ Store(0x0A, DBGB)
+ }
+}
--- /dev/null
+/****************************************************************
+ * HPET
+ ****************************************************************/
+
+Scope(\_SB) {
+ Device(HPET) {
+ Name(_HID, EISAID("PNP0103"))
+ Name(_UID, 0)
+ OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
+ Field(HPTM, DWordAcc, Lock, Preserve) {
+ VEND, 32,
+ PRD, 32,
+ }
+ Method(_STA, 0, NotSerialized) {
+ Store(VEND, Local0)
+ Store(PRD, Local1)
+ ShiftRight(Local0, 16, Local0)
+ If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
+ Return (0x0)
+ }
+ If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
+ Return (0x0)
+ }
+ Return (0x0F)
+ }
+ Name(_CRS, ResourceTemplate() {
+#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
+ IRQNoFlags() {2, 8}
+#endif
+ Memory32Fixed(ReadOnly,
+ 0xFED00000, // Address Base
+ 0x00000400, // Address Length
+ )
+ })
+ }
+}
--- /dev/null
+/* Common legacy ISA style devices. */
+Scope(\_SB.PCI0.ISA) {
+
+ Device(RTC) {
+ Name(_HID, EisaId("PNP0B00"))
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
+ IRQNoFlags() { 8 }
+ IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
+ })
+ }
+
+ Device(KBD) {
+ Name(_HID, EisaId("PNP0303"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
+ IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
+ IRQNoFlags() { 1 }
+ })
+ }
+
+ Device(MOU) {
+ Name(_HID, EisaId("PNP0F13"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IRQNoFlags() { 12 }
+ })
+ }
+
+ Device(FDC0) {
+ Name(_HID, EisaId("PNP0700"))
+ Method(_STA, 0, NotSerialized) {
+ Store(FDEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
+ IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
+ IRQNoFlags() { 6 }
+ DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
+ })
+ }
+
+ Device(LPT) {
+ Name(_HID, EisaId("PNP0400"))
+ Method(_STA, 0, NotSerialized) {
+ Store(LPEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
+ IRQNoFlags() { 7 }
+ })
+ }
+
+ Device(COM1) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x01)
+ Method(_STA, 0, NotSerialized) {
+ Store(CAEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
+ IRQNoFlags() { 4 }
+ })
+ }
+
+ Device(COM2) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x02)
+ Method(_STA, 0, NotSerialized) {
+ Store(CBEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
+ IRQNoFlags() { 3 }
+ })
+ }
+}
--- /dev/null
+/* PCI CRS (current resources) definition. */
+Scope(\_SB.PCI0) {
+
+ Name(CRES, ResourceTemplate() {
+ WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, // Address Space Granularity
+ 0x0000, // Address Range Minimum
+ 0x00FF, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0x0100, // Address Length
+ ,, )
+ IO(Decode16,
+ 0x0CF8, // Address Range Minimum
+ 0x0CF8, // Address Range Maximum
+ 0x01, // Address Alignment
+ 0x08, // Address Length
+ )
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Address Space Granularity
+ 0x0000, // Address Range Minimum
+ 0x0CF7, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0x0CF8, // Address Length
+ ,, , TypeStatic)
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Address Space Granularity
+ 0x0D00, // Address Range Minimum
+ 0xFFFF, // Address Range Maximum
+ 0x0000, // Address Translation Offset
+ 0xF300, // Address Length
+ ,, , TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x000A0000, // Address Range Minimum
+ 0x000BFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x00020000, // Address Length
+ ,, , AddressRangeMemory, TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0xE0000000, // Address Range Minimum
+ 0xFEBFFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x1EC00000, // Address Length
+ ,, PW32, AddressRangeMemory, TypeStatic)
+ })
+
+ Name(CR64, ResourceTemplate() {
+ QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x8000000000, // Address Range Minimum
+ 0xFFFFFFFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x8000000000, // Address Length
+ ,, PW64, AddressRangeMemory, TypeStatic)
+ })
+
+ Method(_CRS, 0) {
+ /* Fields provided by dynamically created ssdt */
+ External(P0S, IntObj)
+ External(P0E, IntObj)
+ External(P1V, IntObj)
+ External(P1S, BuffObj)
+ External(P1E, BuffObj)
+ External(P1L, BuffObj)
+
+ /* fixup 32bit pci io window */
+ CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
+ CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
+ CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
+ Store(P0S, PS32)
+ Store(P0E, PE32)
+ Store(Add(Subtract(P0E, P0S), 1), PL32)
+
+ If (LEqual(P1V, Zero)) {
+ Return (CRES)
+ }
+
+ /* fixup 64bit pci io window */
+ CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
+ CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
+ CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
+ Store(P1S, PS64)
+ Store(P1E, PE64)
+ Store(P1L, PL64)
+ /* add window and return result */
+ ConcatenateResTemplate(CRES, CR64, Local0)
+ Return (Local0)
+ }
+}
--- /dev/null
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ACPI_EXTRACT_ALL_CODE AmlCode
+
+DefinitionBlock (
+ "acpi-dsdt.aml", // Output Filename
+ "DSDT", // Signature
+ 0x01, // DSDT Compliance Revision
+ "BXPC", // OEMID
+ "BXDSDT", // TABLE ID
+ 0x1 // OEM Revision
+ )
+{
+
+#include "acpi-dsdt-dbug.dsl"
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+ Scope(\_SB) {
+ Device(PCI0) {
+ Name(_HID, EisaId("PNP0A03"))
+ Name(_ADR, 0x00)
+ Name(_UID, 1)
+ }
+ }
+
+#include "acpi-dsdt-pci-crs.dsl"
+#include "acpi-dsdt-hpet.dsl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(VGA) {
+ Name(_ADR, 0x00020000)
+ OperationRegion(PCIC, PCI_Config, Zero, 0x4)
+ Field(PCIC, DWordAcc, NoLock, Preserve) {
+ VEND, 32
+ }
+ Method(_S1D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S2D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S3D, 0, NotSerialized) {
+ If (LEqual(VEND, 0x1001b36)) {
+ Return (0x03) // QXL
+ } Else {
+ Return (0x00)
+ }
+ }
+ }
+ }
+
+
+/****************************************************************
+ * PIIX4 PM
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(PX13) {
+ Name(_ADR, 0x00010003)
+ OperationRegion(P13C, PCI_Config, 0x00, 0xff)
+ }
+ }
+
+
+/****************************************************************
+ * PIIX3 ISA bridge
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(ISA) {
+ Name(_ADR, 0x00010000)
+
+ /* PIIX PCI to ISA irq remapping */
+ OperationRegion(P40C, PCI_Config, 0x60, 0x04)
+
+ /* enable bits */
+ Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
+ Offset(0x5f),
+ , 7,
+ LPEN, 1, // LPT
+ Offset(0x67),
+ , 3,
+ CAEN, 1, // COM1
+ , 3,
+ CBEN, 1, // COM2
+ }
+ Name(FDEN, 1)
+ }
+ }
+
+#include "acpi-dsdt-isa.dsl"
+
+
+/****************************************************************
+ * PCI hotplug
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ OperationRegion(PCST, SystemIO, 0xae00, 0x08)
+ Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
+ PCIU, 32,
+ PCID, 32,
+ }
+
+ OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
+ Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
+ B0EJ, 32,
+ }
+
+ /* Methods called by bulk generated PCI devices below */
+
+ /* Methods called by hotplug devices */
+ Method(PCEJ, 1, NotSerialized) {
+ // _EJ0 method - eject callback
+ Store(ShiftLeft(1, Arg0), B0EJ)
+ Return (0x0)
+ }
+
+ /* Hotplug notification method supplied by SSDT */
+ External(\_SB.PCI0.PCNT, MethodObj)
+
+ /* PCI hotplug notify method */
+ Method(PCNF, 0) {
+ // Local0 = iterator
+ Store(Zero, Local0)
+ While (LLess(Local0, 31)) {
+ Increment(Local0)
+ If (And(PCIU, ShiftLeft(1, Local0))) {
+ PCNT(Local0, 1)
+ }
+ If (And(PCID, ShiftLeft(1, Local0))) {
+ PCNT(Local0, 3)
+ }
+ }
+ }
+ }
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+ Scope(\_SB) {
+ Scope(PCI0) {
+ Name(_PRT, Package() {
+ /* PCI IRQ routing table, example from ACPI 2.0a specification,
+ section 6.2.8.1 */
+ /* Note: we provide the same info as the PCI routing
+ table of the Bochs BIOS */
+
+#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
+ Package() { nr##ffff, 0, lnk0, 0 }, \
+ Package() { nr##ffff, 1, lnk1, 0 }, \
+ Package() { nr##ffff, 2, lnk2, 0 }, \
+ Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
+#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
+
+ prt_slot0(0x0000),
+ /* Device 1 is power mgmt device, and can only use irq 9 */
+ prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
+ prt_slot2(0x0002),
+ prt_slot3(0x0003),
+ prt_slot0(0x0004),
+ prt_slot1(0x0005),
+ prt_slot2(0x0006),
+ prt_slot3(0x0007),
+ prt_slot0(0x0008),
+ prt_slot1(0x0009),
+ prt_slot2(0x000a),
+ prt_slot3(0x000b),
+ prt_slot0(0x000c),
+ prt_slot1(0x000d),
+ prt_slot2(0x000e),
+ prt_slot3(0x000f),
+ prt_slot0(0x0010),
+ prt_slot1(0x0011),
+ prt_slot2(0x0012),
+ prt_slot3(0x0013),
+ prt_slot0(0x0014),
+ prt_slot1(0x0015),
+ prt_slot2(0x0016),
+ prt_slot3(0x0017),
+ prt_slot0(0x0018),
+ prt_slot1(0x0019),
+ prt_slot2(0x001a),
+ prt_slot3(0x001b),
+ prt_slot0(0x001c),
+ prt_slot1(0x001d),
+ prt_slot2(0x001e),
+ prt_slot3(0x001f),
+ })
+ }
+
+ Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
+ PRQ0, 8,
+ PRQ1, 8,
+ PRQ2, 8,
+ PRQ3, 8
+ }
+
+ Method(IQST, 1, NotSerialized) {
+ // _STA method - get status
+ If (And(0x80, Arg0)) {
+ Return (0x09)
+ }
+ Return (0x0B)
+ }
+ Method(IQCR, 1, NotSerialized) {
+ // _CRS method - get current settings
+ Name(PRR0, ResourceTemplate() {
+ Interrupt(, Level, ActiveHigh, Shared) { 0 }
+ })
+ CreateDWordField(PRR0, 0x05, PRRI)
+ If (LLess(Arg0, 0x80)) {
+ Store(Arg0, PRRI)
+ }
+ Return (PRR0)
+ }
+
+#define define_link(link, uid, reg) \
+ Device(link) { \
+ Name(_HID, EISAID("PNP0C0F")) \
+ Name(_UID, uid) \
+ Name(_PRS, ResourceTemplate() { \
+ Interrupt(, Level, ActiveHigh, Shared) { \
+ 5, 10, 11 \
+ } \
+ }) \
+ Method(_STA, 0, NotSerialized) { \
+ Return (IQST(reg)) \
+ } \
+ Method(_DIS, 0, NotSerialized) { \
+ Or(reg, 0x80, reg) \
+ } \
+ Method(_CRS, 0, NotSerialized) { \
+ Return (IQCR(reg)) \
+ } \
+ Method(_SRS, 1, NotSerialized) { \
+ CreateDWordField(Arg0, 0x05, PRRI) \
+ Store(PRRI, reg) \
+ } \
+ }
+
+ define_link(LNKA, 0, PRQ0)
+ define_link(LNKB, 1, PRQ1)
+ define_link(LNKC, 2, PRQ2)
+ define_link(LNKD, 3, PRQ3)
+
+ Device(LNKS) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 4)
+ Name(_PRS, ResourceTemplate() {
+ Interrupt(, Level, ActiveHigh, Shared) { 9 }
+ })
+
+ // The SCI cannot be disabled and is always attached to GSI 9,
+ // so these are no-ops. We only need this link to override the
+ // polarity to active high and match the content of the MADT.
+ Method(_STA, 0, NotSerialized) { Return (0x0b) }
+ Method(_DIS, 0, NotSerialized) { }
+ Method(_CRS, 0, NotSerialized) { Return (_PRS) }
+ Method(_SRS, 1, NotSerialized) { }
+ }
+ }
+
+#include "acpi-dsdt-cpu-hotplug.dsl"
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+ Scope(\_GPE) {
+ Name(_HID, "ACPI0006")
+
+ Method(_L00) {
+ }
+ Method(_E01) {
+ // PCI hotplug event
+ \_SB.PCI0.PCNF()
+ }
+ Method(_E02) {
+ // CPU hotplug event
+ \_SB.PRSC()
+ }
+ Method(_L03) {
+ }
+ Method(_L04) {
+ }
+ Method(_L05) {
+ }
+ Method(_L06) {
+ }
+ Method(_L07) {
+ }
+ Method(_L08) {
+ }
+ Method(_L09) {
+ }
+ Method(_L0A) {
+ }
+ Method(_L0B) {
+ }
+ Method(_L0C) {
+ }
+ Method(_L0D) {
+ }
+ Method(_L0E) {
+ }
+ Method(_L0F) {
+ }
+ }
+}
--- /dev/null
+// Support for generating ACPI tables (on emulators)
+//
+// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "acpi.h" // struct rsdp_descriptor
+#include "util.h" // memcpy
+#include "byteorder.h" // cpu_to_le16
+#include "hw/pci.h" // pci_find_init_device
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_INTERRUPT_LINE
+#include "ioport.h" // inl
+#include "config.h" // CONFIG_*
+#include "paravirt.h" // RamSize
+#include "dev-q35.h"
+
+#include "src/fw/acpi-dsdt.hex"
+
+u32 acpi_pm1a_cnt VARFSEG;
+
+static void
+build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
+{
+ h->signature = cpu_to_le32(sig);
+ h->length = cpu_to_le32(len);
+ h->revision = rev;
+ memcpy(h->oem_id, BUILD_APPNAME6, 6);
+ memcpy(h->oem_table_id, BUILD_APPNAME4, 4);
+ memcpy(h->oem_table_id + 4, (void*)&sig, 4);
+ h->oem_revision = cpu_to_le32(1);
+ memcpy(h->asl_compiler_id, BUILD_APPNAME4, 4);
+ h->asl_compiler_revision = cpu_to_le32(1);
+ h->checksum -= checksum(h, len);
+}
+
+#define PIIX4_ACPI_ENABLE 0xf1
+#define PIIX4_ACPI_DISABLE 0xf0
+#define PIIX4_GPE0_BLK 0xafe0
+#define PIIX4_GPE0_BLK_LEN 4
+
+#define PIIX4_PM_INTRRUPT 9 // irq 9
+
+static void piix4_fadt_setup(struct pci_device *pci, void *arg)
+{
+ struct fadt_descriptor_rev1 *fadt = arg;
+
+ fadt->model = 1;
+ fadt->reserved1 = 0;
+ fadt->sci_int = cpu_to_le16(PIIX4_PM_INTRRUPT);
+ fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
+ fadt->acpi_enable = PIIX4_ACPI_ENABLE;
+ fadt->acpi_disable = PIIX4_ACPI_DISABLE;
+ fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
+ fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
+ fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
+ fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK);
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN;
+ fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
+ fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
+ /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */
+ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) |
+ (1 << 15));
+}
+
+/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
+void ich9_lpc_fadt_setup(struct pci_device *dev, void *arg)
+{
+ struct fadt_descriptor_rev1 *fadt = arg;
+
+ fadt->model = 1;
+ fadt->reserved1 = 0;
+ fadt->sci_int = cpu_to_le16(9);
+ fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
+ fadt->acpi_enable = ICH9_ACPI_ENABLE;
+ fadt->acpi_disable = ICH9_ACPI_DISABLE;
+ fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
+ fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
+ fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
+ fadt->gpe0_blk = cpu_to_le32(PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS);
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = ICH9_PMIO_GPE0_BLK_LEN;
+ fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
+ fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
+ /* WBINVD + PROC_C1 + SLP_BUTTON + RTC_S4 + USE_PLATFORM_CLOCK */
+ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 7) |
+ (1 << 15));
+}
+
+static const struct pci_device_id fadt_init_tbl[] = {
+ /* PIIX4 Power Management device (for ACPI) */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ piix4_fadt_setup),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
+ ich9_lpc_fadt_setup),
+ PCI_DEVICE_END
+};
+
+static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt)
+{
+ if (fadt->dsdt) {
+ free((void *)le32_to_cpu(fadt->dsdt));
+ }
+ fadt->dsdt = cpu_to_le32((u32)dsdt);
+ fadt->checksum -= checksum(fadt, sizeof(*fadt));
+ dprintf(1, "ACPI DSDT=%p\n", dsdt);
+}
+
+static void *
+build_fadt(struct pci_device *pci)
+{
+ struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
+ struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
+
+ if (!fadt || !facs) {
+ warn_noalloc();
+ return NULL;
+ }
+
+ /* FACS */
+ memset(facs, 0, sizeof(*facs));
+ facs->signature = cpu_to_le32(FACS_SIGNATURE);
+ facs->length = cpu_to_le32(sizeof(*facs));
+
+ /* FADT */
+ memset(fadt, 0, sizeof(*fadt));
+ fadt->firmware_ctrl = cpu_to_le32((u32)facs);
+ fadt->dsdt = 0; /* dsdt will be filled later in acpi_setup()
+ by fill_dsdt() */
+ pci_init_device(fadt_init_tbl, pci, fadt);
+
+ build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1);
+
+ return fadt;
+}
+
+static void*
+build_madt(void)
+{
+ int madt_size = (sizeof(struct multiple_apic_table)
+ + sizeof(struct madt_processor_apic) * MaxCountCPUs
+ + sizeof(struct madt_io_apic)
+ + sizeof(struct madt_intsrcovr) * 16
+ + sizeof(struct madt_local_nmi));
+
+ struct multiple_apic_table *madt = malloc_high(madt_size);
+ if (!madt) {
+ warn_noalloc();
+ return NULL;
+ }
+ memset(madt, 0, madt_size);
+ madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
+ madt->flags = cpu_to_le32(1);
+ struct madt_processor_apic *apic = (void*)&madt[1];
+ int i;
+ for (i=0; i<MaxCountCPUs; i++) {
+ apic->type = APIC_PROCESSOR;
+ apic->length = sizeof(*apic);
+ apic->processor_id = i;
+ apic->local_apic_id = i;
+ if (apic_id_is_present(apic->local_apic_id))
+ apic->flags = cpu_to_le32(1);
+ else
+ apic->flags = cpu_to_le32(0);
+ apic++;
+ }
+ struct madt_io_apic *io_apic = (void*)apic;
+ io_apic->type = APIC_IO;
+ io_apic->length = sizeof(*io_apic);
+ io_apic->io_apic_id = BUILD_IOAPIC_ID;
+ io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
+ io_apic->interrupt = cpu_to_le32(0);
+
+ struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
+ if (romfile_loadint("etc/irq0-override", 0)) {
+ memset(intsrcovr, 0, sizeof(*intsrcovr));
+ intsrcovr->type = APIC_XRUPT_OVERRIDE;
+ intsrcovr->length = sizeof(*intsrcovr);
+ intsrcovr->source = 0;
+ intsrcovr->gsi = cpu_to_le32(2);
+ intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */
+ intsrcovr++;
+ }
+ for (i = 1; i < 16; i++) {
+ if (!(BUILD_PCI_IRQS & (1 << i)))
+ /* No need for a INT source override structure. */
+ continue;
+ memset(intsrcovr, 0, sizeof(*intsrcovr));
+ intsrcovr->type = APIC_XRUPT_OVERRIDE;
+ intsrcovr->length = sizeof(*intsrcovr);
+ intsrcovr->source = i;
+ intsrcovr->gsi = cpu_to_le32(i);
+ intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
+ intsrcovr++;
+ }
+
+ struct madt_local_nmi *local_nmi = (void*)intsrcovr;
+ local_nmi->type = APIC_LOCAL_NMI;
+ local_nmi->length = sizeof(*local_nmi);
+ local_nmi->processor_id = 0xff; /* all processors */
+ local_nmi->flags = cpu_to_le16(0);
+ local_nmi->lint = 1; /* LINT1 */
+ local_nmi++;
+
+ build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1);
+ return madt;
+}
+
+// Encode a hex value
+static inline char getHex(u32 val) {
+ val &= 0x0f;
+ return (val <= 9) ? ('0' + val) : ('A' + val - 10);
+}
+
+// Encode a length in an SSDT.
+static u8 *
+encodeLen(u8 *ssdt_ptr, int length, int bytes)
+{
+ switch (bytes) {
+ default:
+ case 4: ssdt_ptr[3] = ((length >> 20) & 0xff);
+ case 3: ssdt_ptr[2] = ((length >> 12) & 0xff);
+ case 2: ssdt_ptr[1] = ((length >> 4) & 0xff);
+ ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f);
+ break;
+ case 1: ssdt_ptr[0] = length & 0x3f;
+ }
+ return ssdt_ptr + bytes;
+}
+
+#include "src/fw/ssdt-proc.hex"
+
+/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
+#define PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
+#define PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
+#define PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
+#define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
+#define PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
+
+/* 0x5B 0x82 DeviceOp PkgLength NameString */
+#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
+#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
+#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
+#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
+#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
+#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
+#define PCI_SLOTS 32
+
+#define SSDT_SIGNATURE 0x54445353 // SSDT
+#define SSDT_HEADER_LENGTH 36
+
+#include "src/fw/ssdt-misc.hex"
+#include "src/fw/ssdt-pcihp.hex"
+
+#define PCI_RMV_BASE 0xae0c
+
+static u8*
+build_notify(u8 *ssdt_ptr, const char *name, int skip, int count,
+ const char *target, int ofs)
+{
+ count -= skip;
+
+ *(ssdt_ptr++) = 0x14; // MethodOp
+ ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*count), 2);
+ memcpy(ssdt_ptr, name, 4);
+ ssdt_ptr += 4;
+ *(ssdt_ptr++) = 0x02; // MethodOp
+
+ int i;
+ for (i = skip; count-- > 0; i++) {
+ *(ssdt_ptr++) = 0xA0; // IfOp
+ ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
+ *(ssdt_ptr++) = 0x93; // LEqualOp
+ *(ssdt_ptr++) = 0x68; // Arg0Op
+ *(ssdt_ptr++) = 0x0A; // BytePrefix
+ *(ssdt_ptr++) = i;
+ *(ssdt_ptr++) = 0x86; // NotifyOp
+ memcpy(ssdt_ptr, target, 4);
+ ssdt_ptr[ofs] = getHex(i >> 4);
+ ssdt_ptr[ofs + 1] = getHex(i);
+ ssdt_ptr += 4;
+ *(ssdt_ptr++) = 0x69; // Arg1Op
+ }
+ return ssdt_ptr;
+}
+
+static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject)
+{
+ ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4);
+ ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot);
+ ssdt_ptr[PCIHP_OFFSET_ID] = slot;
+ ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot;
+
+ /* Runtime patching of EJ0: to disable hotplug for a slot,
+ * replace the method name: _EJ0 by EJ0_. */
+ /* Sanity check */
+ if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) {
+ warn_internalerror();
+ }
+ if (!eject) {
+ memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4);
+ }
+}
+
+static void*
+build_ssdt(void)
+{
+ int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
+ int length = (sizeof(ssdp_misc_aml) // _S3_ / _S4_ / _S5_
+ + (1+3+4) // Scope(_SB_)
+ + (acpi_cpus * PROC_SIZEOF) // procs
+ + (1+2+5+(12*acpi_cpus)) // NTFY
+ + (6+2+1+(1*acpi_cpus)) // CPON
+ + (1+3+4) // Scope(PCI0)
+ + ((PCI_SLOTS - 1) * PCIHP_SIZEOF) // slots
+ + (1+2+5+(12*(PCI_SLOTS - 1)))); // PCNT
+ u8 *ssdt = malloc_high(length);
+ if (! ssdt) {
+ warn_noalloc();
+ return NULL;
+ }
+ u8 *ssdt_ptr = ssdt;
+
+ // Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages
+ int sys_state_size;
+ char *sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
+ if (!sys_states || sys_state_size != 6)
+ sys_states = (char[]){128, 0, 0, 129, 128, 128};
+
+ memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
+ if (!(sys_states[3] & 128))
+ ssdt_ptr[acpi_s3_name[0]] = 'X';
+ if (!(sys_states[4] & 128))
+ ssdt_ptr[acpi_s4_name[0]] = 'X';
+ else
+ ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
+
+ // store pci io windows
+ *(u32*)&ssdt_ptr[acpi_pci32_start[0]] = cpu_to_le32(pcimem_start);
+ *(u32*)&ssdt_ptr[acpi_pci32_end[0]] = cpu_to_le32(pcimem_end - 1);
+ if (pcimem64_start) {
+ ssdt_ptr[acpi_pci64_valid[0]] = 1;
+ *(u64*)&ssdt_ptr[acpi_pci64_start[0]] = cpu_to_le64(pcimem64_start);
+ *(u64*)&ssdt_ptr[acpi_pci64_end[0]] = cpu_to_le64(pcimem64_end - 1);
+ *(u64*)&ssdt_ptr[acpi_pci64_length[0]] = cpu_to_le64(
+ pcimem64_end - pcimem64_start);
+ } else {
+ ssdt_ptr[acpi_pci64_valid[0]] = 0;
+ }
+
+ int pvpanic_port = romfile_loadint("etc/pvpanic-port", 0x0);
+ *(u16 *)(ssdt_ptr + *ssdt_isa_pest) = pvpanic_port;
+
+ ssdt_ptr += sizeof(ssdp_misc_aml);
+
+ // build Scope(_SB_) header
+ *(ssdt_ptr++) = 0x10; // ScopeOp
+ ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
+ *(ssdt_ptr++) = '_';
+ *(ssdt_ptr++) = 'S';
+ *(ssdt_ptr++) = 'B';
+ *(ssdt_ptr++) = '_';
+
+ // build Processor object for each processor
+ int i;
+ for (i=0; i<acpi_cpus; i++) {
+ memcpy(ssdt_ptr, PROC_AML, PROC_SIZEOF);
+ ssdt_ptr[PROC_OFFSET_CPUHEX] = getHex(i >> 4);
+ ssdt_ptr[PROC_OFFSET_CPUHEX+1] = getHex(i);
+ ssdt_ptr[PROC_OFFSET_CPUID1] = i;
+ ssdt_ptr[PROC_OFFSET_CPUID2] = i;
+ ssdt_ptr += PROC_SIZEOF;
+ }
+
+ // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
+ // Arg0 = Processor ID = APIC ID
+ ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2);
+
+ // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
+ *(ssdt_ptr++) = 0x08; // NameOp
+ *(ssdt_ptr++) = 'C';
+ *(ssdt_ptr++) = 'P';
+ *(ssdt_ptr++) = 'O';
+ *(ssdt_ptr++) = 'N';
+ *(ssdt_ptr++) = 0x12; // PackageOp
+ ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2);
+ *(ssdt_ptr++) = acpi_cpus;
+ for (i=0; i<acpi_cpus; i++)
+ *(ssdt_ptr++) = (apic_id_is_present(i)) ? 0x01 : 0x00;
+
+ // build Scope(PCI0) opcode
+ *(ssdt_ptr++) = 0x10; // ScopeOp
+ ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
+ *(ssdt_ptr++) = 'P';
+ *(ssdt_ptr++) = 'C';
+ *(ssdt_ptr++) = 'I';
+ *(ssdt_ptr++) = '0';
+
+ // build Device object for each slot
+ u32 rmvc_pcrm = inl(PCI_RMV_BASE);
+ for (i=1; i<PCI_SLOTS; i++) {
+ u32 eject = rmvc_pcrm & (0x1 << i);
+ memcpy(ssdt_ptr, PCIHP_AML, PCIHP_SIZEOF);
+ patch_pcihp(i, ssdt_ptr, eject != 0);
+ ssdt_ptr += PCIHP_SIZEOF;
+ }
+
+ ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOTS, "S00_", 1);
+
+ build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
+
+ //hexdump(ssdt, ssdt_ptr - ssdt);
+
+ return ssdt;
+}
+
+#define HPET_ID 0x000
+#define HPET_PERIOD 0x004
+
+static void*
+build_hpet(void)
+{
+ struct acpi_20_hpet *hpet;
+ const void *hpet_base = (void *)BUILD_HPET_ADDRESS;
+ u32 hpet_vendor = readl(hpet_base + HPET_ID) >> 16;
+ u32 hpet_period = readl(hpet_base + HPET_PERIOD);
+
+ if (hpet_vendor == 0 || hpet_vendor == 0xffff ||
+ hpet_period == 0 || hpet_period > 100000000)
+ return NULL;
+
+ hpet = malloc_high(sizeof(*hpet));
+ if (!hpet) {
+ warn_noalloc();
+ return NULL;
+ }
+
+ memset(hpet, 0, sizeof(*hpet));
+ /* Note timer_block_id value must be kept in sync with value advertised by
+ * emulated hpet
+ */
+ hpet->timer_block_id = cpu_to_le32(0x8086a201);
+ hpet->addr.address = cpu_to_le64(BUILD_HPET_ADDRESS);
+ build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1);
+
+ return hpet;
+}
+
+static void
+acpi_build_srat_memory(struct srat_memory_affinity *numamem,
+ u64 base, u64 len, int node, int enabled)
+{
+ numamem->type = SRAT_MEMORY;
+ numamem->length = sizeof(*numamem);
+ memset(numamem->proximity, 0, 4);
+ numamem->proximity[0] = node;
+ numamem->flags = cpu_to_le32(!!enabled);
+ numamem->base_addr = cpu_to_le64(base);
+ numamem->range_length = cpu_to_le64(len);
+}
+
+static void *
+build_srat(void)
+{
+ int numadatasize, numacpusize;
+ u64 *numadata = romfile_loadfile("etc/numa-nodes", &numadatasize);
+ u64 *numacpumap = romfile_loadfile("etc/numa-cpu-map", &numacpusize);
+ if (!numadata || !numacpumap)
+ goto fail;
+ int max_cpu = numacpusize / sizeof(u64);
+ int nb_numa_nodes = numadatasize / sizeof(u64);
+
+ struct system_resource_affinity_table *srat;
+ int srat_size = sizeof(*srat) +
+ sizeof(struct srat_processor_affinity) * max_cpu +
+ sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
+
+ srat = malloc_high(srat_size);
+ if (!srat) {
+ warn_noalloc();
+ goto fail;
+ }
+
+ memset(srat, 0, srat_size);
+ srat->reserved1=cpu_to_le32(1);
+ struct srat_processor_affinity *core = (void*)(srat + 1);
+ int i;
+ u64 curnode;
+
+ for (i = 0; i < max_cpu; ++i) {
+ core->type = SRAT_PROCESSOR;
+ core->length = sizeof(*core);
+ core->local_apic_id = i;
+ curnode = *numacpumap++;
+ core->proximity_lo = curnode;
+ memset(core->proximity_hi, 0, 3);
+ core->local_sapic_eid = 0;
+ if (apic_id_is_present(i))
+ core->flags = cpu_to_le32(1);
+ else
+ core->flags = cpu_to_le32(0);
+ core++;
+ }
+
+
+ /* the memory map is a bit tricky, it contains at least one hole
+ * from 640k-1M and possibly another one from 3.5G-4G.
+ */
+ struct srat_memory_affinity *numamem = (void*)core;
+ int slots = 0;
+ u64 mem_len, mem_base, next_base = 0;
+
+ acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
+ next_base = 1024 * 1024;
+ numamem++;
+ slots++;
+ for (i = 1; i < nb_numa_nodes + 1; ++i) {
+ mem_base = next_base;
+ mem_len = *numadata++;
+ if (i == 1)
+ mem_len -= 1024 * 1024;
+ next_base = mem_base + mem_len;
+
+ /* Cut out the PCI hole */
+ if (mem_base <= RamSize && next_base > RamSize) {
+ mem_len -= next_base - RamSize;
+ if (mem_len > 0) {
+ acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
+ numamem++;
+ slots++;
+ }
+ mem_base = 1ULL << 32;
+ mem_len = next_base - RamSize;
+ next_base += (1ULL << 32) - RamSize;
+ }
+ acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
+ numamem++;
+ slots++;
+ }
+ for (; slots < nb_numa_nodes + 2; slots++) {
+ acpi_build_srat_memory(numamem, 0, 0, 0, 0);
+ numamem++;
+ }
+
+ build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1);
+
+ free(numadata);
+ free(numacpumap);
+ return srat;
+fail:
+ free(numadata);
+ free(numacpumap);
+ return NULL;
+}
+
+static void *
+build_mcfg_q35(void)
+{
+ struct acpi_table_mcfg *mcfg;
+
+ int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+ mcfg = malloc_high(len);
+ if (!mcfg) {
+ warn_noalloc();
+ return NULL;
+ }
+ memset(mcfg, 0, len);
+ mcfg->allocation[0].address = cpu_to_le64(Q35_HOST_BRIDGE_PCIEXBAR_ADDR);
+ mcfg->allocation[0].pci_segment = cpu_to_le16(Q35_HOST_PCIE_PCI_SEGMENT);
+ mcfg->allocation[0].start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER;
+ mcfg->allocation[0].end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER;
+
+ build_header((void *)mcfg, MCFG_SIGNATURE, len, 1);
+ return mcfg;
+}
+
+static const struct pci_device_id acpi_find_tbl[] = {
+ /* PIIX4 Power Management device. */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, NULL),
+ PCI_DEVICE_END,
+};
+
+struct rsdp_descriptor *RsdpAddr;
+
+#define MAX_ACPI_TABLES 20
+void
+acpi_setup(void)
+{
+ if (! CONFIG_ACPI)
+ return;
+
+ dprintf(3, "init ACPI tables\n");
+
+ // This code is hardcoded for PIIX4 Power Management device.
+ struct pci_device *pci = pci_find_init_device(acpi_find_tbl, NULL);
+ if (!pci)
+ // Device not found
+ return;
+
+ // Build ACPI tables
+ u32 tables[MAX_ACPI_TABLES], tbl_idx = 0;
+
+#define ACPI_INIT_TABLE(X) \
+ do { \
+ tables[tbl_idx] = cpu_to_le32((u32)(X)); \
+ if (le32_to_cpu(tables[tbl_idx])) \
+ tbl_idx++; \
+ } while(0)
+
+ struct fadt_descriptor_rev1 *fadt = build_fadt(pci);
+ ACPI_INIT_TABLE(fadt);
+ ACPI_INIT_TABLE(build_ssdt());
+ ACPI_INIT_TABLE(build_madt());
+ ACPI_INIT_TABLE(build_hpet());
+ ACPI_INIT_TABLE(build_srat());
+ if (pci->device == PCI_DEVICE_ID_INTEL_ICH9_LPC)
+ ACPI_INIT_TABLE(build_mcfg_q35());
+
+ struct romfile_s *file = NULL;
+ for (;;) {
+ file = romfile_findprefix("acpi/", file);
+ if (!file)
+ break;
+ struct acpi_table_header *table = malloc_high(file->size);
+ if (!table) {
+ warn_noalloc();
+ continue;
+ }
+ int ret = file->copy(file, table, file->size);
+ if (ret <= sizeof(*table))
+ continue;
+ if (table->signature == DSDT_SIGNATURE) {
+ if (fadt) {
+ fill_dsdt(fadt, table);
+ }
+ } else {
+ ACPI_INIT_TABLE(table);
+ }
+ if (tbl_idx == MAX_ACPI_TABLES) {
+ warn_noalloc();
+ break;
+ }
+ }
+
+ if (CONFIG_ACPI_DSDT && fadt && !fadt->dsdt) {
+ /* default DSDT */
+ void *dsdt = malloc_high(sizeof(AmlCode));
+ if (!dsdt) {
+ warn_noalloc();
+ return;
+ }
+ memcpy(dsdt, AmlCode, sizeof(AmlCode));
+ fill_dsdt(fadt, dsdt);
+ }
+
+ // Build final rsdt table
+ struct rsdt_descriptor_rev1 *rsdt;
+ size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
+ rsdt = malloc_high(rsdt_len);
+ if (!rsdt) {
+ warn_noalloc();
+ return;
+ }
+ memset(rsdt, 0, rsdt_len);
+ memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx);
+ build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1);
+
+ // Build rsdp pointer table
+ struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp));
+ if (!rsdp) {
+ warn_noalloc();
+ return;
+ }
+ memset(rsdp, 0, sizeof(*rsdp));
+ rsdp->signature = cpu_to_le64(RSDP_SIGNATURE);
+ memcpy(rsdp->oem_id, BUILD_APPNAME6, 6);
+ rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt);
+ rsdp->checksum -= checksum(rsdp, 20);
+ RsdpAddr = rsdp;
+ dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt);
+}
+
+static struct fadt_descriptor_rev1 *
+find_fadt(void)
+{
+ dprintf(4, "rsdp=%p\n", RsdpAddr);
+ if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
+ return NULL;
+ struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
+ dprintf(4, "rsdt=%p\n", rsdt);
+ if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
+ return NULL;
+ void *end = (void*)rsdt + rsdt->length;
+ int i;
+ for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
+ struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
+ if (!fadt || fadt->signature != FACP_SIGNATURE)
+ continue;
+ dprintf(4, "fadt=%p\n", fadt);
+ return fadt;
+ }
+ dprintf(4, "no fadt found\n");
+ return NULL;
+}
+
+u32
+find_resume_vector(void)
+{
+ struct fadt_descriptor_rev1 *fadt = find_fadt();
+ if (!fadt)
+ return 0;
+ struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
+ dprintf(4, "facs=%p\n", facs);
+ if (! facs || facs->signature != FACS_SIGNATURE)
+ return 0;
+ // Found it.
+ dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
+ return facs->firmware_waking_vector;
+}
+
+void
+find_acpi_features(void)
+{
+ struct fadt_descriptor_rev1 *fadt = find_fadt();
+ if (!fadt)
+ return;
+ u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk);
+ u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk);
+ dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
+ if (pm_tmr)
+ pmtimer_setup(pm_tmr);
+ if (pm1a_cnt)
+ acpi_pm1a_cnt = pm1a_cnt;
+
+ // Theoretically we should check the 'reset_reg_sup' flag, but Windows
+ // doesn't and thus nobody seems to *set* it. If the table is large enough
+ // to include it, let the sanity checks in acpi_set_reset_reg() suffice.
+ if (fadt->length >= 129) {
+ void *p = fadt;
+ acpi_set_reset_reg(p + 116, *(u8 *)(p + 128));
+ }
+}
+
+static struct acpi_20_generic_address acpi_reset_reg;
+static u8 acpi_reset_val;
+
+void
+acpi_reboot(void)
+{
+ // Check it passed the sanity checks in acpi_set_reset_reg() and was set
+ if (acpi_reset_reg.register_bit_width != 8)
+ return;
+
+ u64 addr = le64_to_cpu(acpi_reset_reg.address);
+
+ dprintf(1, "ACPI hard reset %d:%llx (%x)\n",
+ acpi_reset_reg.address_space_id, addr, acpi_reset_val);
+
+ switch (acpi_reset_reg.address_space_id) {
+ case 0: // System Memory
+ writeb((void *)(u32)addr, acpi_reset_val);
+ break;
+ case 1: // System I/O
+ outb(acpi_reset_val, addr);
+ break;
+ case 2: // PCI config space
+ pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val);
+ break;
+ }
+}
+
+void
+acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val)
+{
+ if (!reg || reg->address_space_id > 2 ||
+ reg->register_bit_width != 8 || reg->register_bit_offset)
+ return;
+
+ acpi_reset_reg = *reg;
+ acpi_reset_val = val;
+}
--- /dev/null
+#ifndef __ACPI_H
+#define __ACPI_H
+
+#include "types.h" // u32
+
+/*
+ * ACPI 2.0 Generic Address Space definition.
+ */
+struct acpi_20_generic_address {
+ u8 address_space_id;
+ u8 register_bit_width;
+ u8 register_bit_offset;
+ u8 reserved;
+ u64 address;
+} PACKED;
+#define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff)
+
+void acpi_setup(void);
+u32 find_resume_vector(void);
+void find_acpi_features(void);
+void acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val);
+void acpi_reboot(void);
+
+#define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
+
+struct rsdp_descriptor { /* Root System Descriptor Pointer */
+ u64 signature; /* ACPI signature, contains "RSD PTR " */
+ u8 checksum; /* To make sum of struct == 0 */
+ u8 oem_id [6]; /* OEM identification */
+ u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */
+ u32 rsdt_physical_address; /* 32-bit physical address of RSDT */
+ u32 length; /* XSDT Length in bytes including hdr */
+ u64 xsdt_physical_address; /* 64-bit physical address of XSDT */
+ u8 extended_checksum; /* Checksum of entire table */
+ u8 reserved [3]; /* Reserved field must be 0 */
+};
+
+extern struct rsdp_descriptor *RsdpAddr;
+extern u32 acpi_pm1a_cnt;
+
+/* Table structure from Linux kernel (the ACPI tables are under the
+ BSD license) */
+
+#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
+ u32 signature; /* ACPI signature (4 ASCII characters) */ \
+ u32 length; /* Length of table, in bytes, including header */ \
+ u8 revision; /* ACPI Specification minor version # */ \
+ u8 checksum; /* To make sum of entire table == 0 */ \
+ u8 oem_id [6]; /* OEM identification */ \
+ u8 oem_table_id [8]; /* OEM table identification */ \
+ u32 oem_revision; /* OEM revision number */ \
+ u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \
+ u32 asl_compiler_revision; /* ASL compiler revision number */
+
+
+/*
+ * ACPI 1.0 Fixed ACPI Description Table (FADT)
+ */
+#define FACP_SIGNATURE 0x50434146 // FACP
+struct fadt_descriptor_rev1
+{
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 firmware_ctrl; /* Physical address of FACS */
+ u32 dsdt; /* Physical address of DSDT */
+ u8 model; /* System Interrupt Model */
+ u8 reserved1; /* Reserved */
+ u16 sci_int; /* System vector of SCI interrupt */
+ u32 smi_cmd; /* Port address of SMI command port */
+ u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
+ u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
+ u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
+ u8 reserved2; /* Reserved - must be zero */
+ u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
+ u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
+ u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
+ u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
+ u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
+ u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
+ u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
+ u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
+ u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
+ u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
+ u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
+ u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
+ u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
+ u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
+ u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
+ u8 reserved3; /* Reserved */
+ u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
+ u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
+ u16 flush_size; /* Size of area read to flush caches */
+ u16 flush_stride; /* Stride used in flushing caches */
+ u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */
+ u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */
+ u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
+ u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
+ u8 century; /* Index to century in RTC CMOS RAM */
+ u8 reserved4; /* Reserved */
+ u8 reserved4a; /* Reserved */
+ u8 reserved4b; /* Reserved */
+ u32 flags;
+} PACKED;
+
+struct acpi_table_header /* ACPI common table header */
+{
+ ACPI_TABLE_HEADER_DEF
+} PACKED;
+
+/*
+ * ACPI 1.0 Root System Description Table (RSDT)
+ */
+#define RSDT_SIGNATURE 0x54445352 // RSDT
+struct rsdt_descriptor_rev1
+{
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 table_offset_entry[0]; /* Array of pointers to other */
+ /* ACPI tables */
+} PACKED;
+
+/*
+ * ACPI 1.0 Firmware ACPI Control Structure (FACS)
+ */
+#define FACS_SIGNATURE 0x53434146 // FACS
+struct facs_descriptor_rev1
+{
+ u32 signature; /* ACPI Signature */
+ u32 length; /* Length of structure, in bytes */
+ u32 hardware_signature; /* Hardware configuration signature */
+ u32 firmware_waking_vector; /* ACPI OS waking vector */
+ u32 global_lock; /* Global Lock */
+ u32 flags;
+ u8 resverved3 [40]; /* Reserved - must be zero */
+} PACKED;
+
+/*
+ * Differentiated System Description Table (DSDT)
+ */
+#define DSDT_SIGNATURE 0x54445344 // DSDT
+
+/*
+ * MADT values and structures
+ */
+
+/* Values for MADT PCATCompat */
+
+#define DUAL_PIC 0
+#define MULTIPLE_APIC 1
+
+/* Master MADT */
+
+#define APIC_SIGNATURE 0x43495041 // APIC
+struct multiple_apic_table
+{
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 local_apic_address; /* Physical address of local APIC */
+ u32 flags;
+} PACKED;
+
+/* Values for Type in APIC sub-headers */
+
+#define APIC_PROCESSOR 0
+#define APIC_IO 1
+#define APIC_XRUPT_OVERRIDE 2
+#define APIC_NMI 3
+#define APIC_LOCAL_NMI 4
+#define APIC_ADDRESS_OVERRIDE 5
+#define APIC_IO_SAPIC 6
+#define APIC_LOCAL_SAPIC 7
+#define APIC_XRUPT_SOURCE 8
+#define APIC_RESERVED 9 /* 9 and greater are reserved */
+
+/*
+ * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
+ */
+#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
+ u8 type; \
+ u8 length;
+
+/* Sub-structures for MADT */
+
+struct madt_processor_apic
+{
+ ACPI_SUB_HEADER_DEF
+ u8 processor_id; /* ACPI processor id */
+ u8 local_apic_id; /* Processor's local APIC id */
+ u32 flags;
+} PACKED;
+
+struct madt_io_apic
+{
+ ACPI_SUB_HEADER_DEF
+ u8 io_apic_id; /* I/O APIC ID */
+ u8 reserved; /* Reserved - must be zero */
+ u32 address; /* APIC physical address */
+ u32 interrupt; /* Global system interrupt where INTI
+ * lines start */
+} PACKED;
+
+struct madt_intsrcovr {
+ ACPI_SUB_HEADER_DEF
+ u8 bus;
+ u8 source;
+ u32 gsi;
+ u16 flags;
+} PACKED;
+
+struct madt_local_nmi {
+ ACPI_SUB_HEADER_DEF
+ u8 processor_id; /* ACPI processor id */
+ u16 flags; /* MPS INTI flags */
+ u8 lint; /* Local APIC LINT# */
+} PACKED;
+
+/*
+ * HPET Description Table
+ */
+#define HPET_SIGNATURE 0x54455048 // HPET
+struct acpi_20_hpet {
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 timer_block_id;
+ struct acpi_20_generic_address addr;
+ u8 hpet_number;
+ u16 min_tick;
+ u8 page_protect;
+} PACKED;
+
+/*
+ * SRAT (NUMA topology description) table
+ */
+
+#define SRAT_SIGNATURE 0x54415253 // SRAT
+struct system_resource_affinity_table
+{
+ ACPI_TABLE_HEADER_DEF
+ u32 reserved1;
+ u32 reserved2[2];
+} PACKED;
+
+#define SRAT_PROCESSOR 0
+#define SRAT_MEMORY 1
+
+struct srat_processor_affinity
+{
+ ACPI_SUB_HEADER_DEF
+ u8 proximity_lo;
+ u8 local_apic_id;
+ u32 flags;
+ u8 local_sapic_eid;
+ u8 proximity_hi[3];
+ u32 reserved;
+} PACKED;
+
+struct srat_memory_affinity
+{
+ ACPI_SUB_HEADER_DEF
+ u8 proximity[4];
+ u16 reserved1;
+ u64 base_addr;
+ u64 range_length;
+ u32 reserved2;
+ u32 flags;
+ u32 reserved3[2];
+} PACKED;
+
+/* PCI fw r3.0 MCFG table. */
+/* Subtable */
+struct acpi_mcfg_allocation {
+ u64 address; /* Base address, processor-relative */
+ u16 pci_segment; /* PCI segment group number */
+ u8 start_bus_number; /* Starting PCI Bus number */
+ u8 end_bus_number; /* Final PCI Bus number */
+ u32 reserved;
+} PACKED;
+
+#define MCFG_SIGNATURE 0x4746434d // MCFG
+struct acpi_table_mcfg {
+ ACPI_TABLE_HEADER_DEF;
+ u8 reserved[8];
+ struct acpi_mcfg_allocation allocation[0];
+} PACKED;
+
+#endif // acpi.h
--- /dev/null
+// Coreboot interface support.
+//
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h" // CONFIG_*
+#include "util.h" // dprintf
+#include "hw/pci.h" // struct pir_header
+#include "acpi.h" // struct rsdp_descriptor
+#include "mptable.h" // MPTABLE_SIGNATURE
+#include "smbios.h" // struct smbios_entry_point
+
+static void
+copy_pir(void *pos)
+{
+ struct pir_header *p = pos;
+ if (p->signature != PIR_SIGNATURE)
+ return;
+ if (PirAddr)
+ return;
+ if (p->size < sizeof(*p))
+ return;
+ if (checksum(pos, p->size) != 0)
+ return;
+ void *newpos = malloc_fseg(p->size);
+ if (!newpos) {
+ warn_noalloc();
+ return;
+ }
+ dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
+ memcpy(newpos, pos, p->size);
+ PirAddr = newpos;
+}
+
+static void
+copy_mptable(void *pos)
+{
+ struct mptable_floating_s *p = pos;
+ if (p->signature != MPTABLE_SIGNATURE)
+ return;
+ if (!p->physaddr)
+ return;
+ if (checksum(pos, sizeof(*p)) != 0)
+ return;
+ u32 length = p->length * 16;
+ u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
+ struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
+ if (!newpos) {
+ warn_noalloc();
+ return;
+ }
+ dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
+ memcpy(newpos, pos, length);
+ newpos->physaddr = (u32)newpos + length;
+ newpos->checksum -= checksum(newpos, sizeof(*newpos));
+ memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
+}
+
+static void
+copy_acpi_rsdp(void *pos)
+{
+ if (RsdpAddr)
+ return;
+ struct rsdp_descriptor *p = pos;
+ if (p->signature != RSDP_SIGNATURE)
+ return;
+ u32 length = 20;
+ if (checksum(pos, length) != 0)
+ return;
+ if (p->revision > 1) {
+ length = p->length;
+ if (checksum(pos, length) != 0)
+ return;
+ }
+ void *newpos = malloc_fseg(length);
+ if (!newpos) {
+ warn_noalloc();
+ return;
+ }
+ dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
+ memcpy(newpos, pos, length);
+ RsdpAddr = newpos;
+}
+
+void
+copy_smbios(void *pos)
+{
+ if (SMBiosAddr)
+ return;
+ struct smbios_entry_point *p = pos;
+ if (memcmp(p->anchor_string, "_SM_", 4))
+ return;
+ if (checksum(pos, 0x10) != 0)
+ return;
+ if (memcmp(p->intermediate_anchor_string, "_DMI_", 5))
+ return;
+ if (checksum(pos+0x10, p->length-0x10) != 0)
+ return;
+ struct smbios_entry_point *newpos = malloc_fseg(p->length);
+ if (!newpos) {
+ warn_noalloc();
+ return;
+ }
+ dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos);
+ memcpy(newpos, pos, p->length);
+ SMBiosAddr = newpos;
+}
+
+void
+copy_table(void *pos)
+{
+ copy_pir(pos);
+ copy_mptable(pos);
+ copy_acpi_rsdp(pos);
+ copy_smbios(pos);
+}
--- /dev/null
+// Coreboot interface support.
+//
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "memmap.h" // add_e820
+#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
+#include "lzmadecode.h" // LzmaDecode
+#include "smbios.h" // smbios_init
+#include "boot.h" // boot_add_cbfs
+#include "disk.h" // MAXDESCSIZE
+#include "config.h" // CONFIG_*
+#include "acpi.h" // find_acpi_features
+#include "hw/pci.h" // pci_probe_devices
+#include "paravirt.h" // PlatformRunningOn
+
+
+/****************************************************************
+ * Memory map
+ ****************************************************************/
+
+struct cb_header {
+ u32 signature;
+ u32 header_bytes;
+ u32 header_checksum;
+ u32 table_bytes;
+ u32 table_checksum;
+ u32 table_entries;
+};
+
+#define CB_SIGNATURE 0x4f49424C // "LBIO"
+
+struct cb_memory_range {
+ u64 start;
+ u64 size;
+ u32 type;
+};
+
+#define CB_MEM_TABLE 16
+
+struct cb_memory {
+ u32 tag;
+ u32 size;
+ struct cb_memory_range map[0];
+};
+
+#define CB_TAG_MEMORY 0x01
+
+#define MEM_RANGE_COUNT(_rec) \
+ (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0]))
+
+struct cb_mainboard {
+ u32 tag;
+ u32 size;
+ u8 vendor_idx;
+ u8 part_idx;
+ char strings[0];
+};
+
+#define CB_TAG_MAINBOARD 0x0003
+
+struct cb_forward {
+ u32 tag;
+ u32 size;
+ u64 forward;
+};
+
+#define CB_TAG_FORWARD 0x11
+
+struct cb_cbmem_ref {
+ u32 tag;
+ u32 size;
+ u64 cbmem_addr;
+};
+
+#define CB_TAG_CBMEM_CONSOLE 0x17
+
+struct cbmem_console {
+ u32 buffer_size;
+ u32 buffer_cursor;
+ u8 buffer_body[0];
+} PACKED;
+static struct cbmem_console *cbcon = NULL;
+
+static u16
+ipchksum(char *buf, int count)
+{
+ u16 *p = (u16*)buf;
+ u32 sum = 0;
+ while (count > 1) {
+ sum += *p++;
+ count -= 2;
+ }
+ if (count)
+ sum += *(u8*)p;
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ return ~sum;
+}
+
+// Try to locate the coreboot header in a given address range.
+static struct cb_header *
+find_cb_header(char *addr, int len)
+{
+ char *end = addr + len;
+ for (; addr < end; addr += 16) {
+ struct cb_header *cbh = (struct cb_header *)addr;
+ if (cbh->signature != CB_SIGNATURE)
+ continue;
+ if (! cbh->table_bytes)
+ continue;
+ if (ipchksum(addr, sizeof(*cbh)) != 0)
+ continue;
+ if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes)
+ != cbh->table_checksum)
+ continue;
+ return cbh;
+ }
+ return NULL;
+}
+
+// Try to find the coreboot memory table in the given coreboot table.
+static void *
+find_cb_subtable(struct cb_header *cbh, u32 tag)
+{
+ char *tbl = (char *)cbh + sizeof(*cbh);
+ int i;
+ for (i=0; i<cbh->table_entries; i++) {
+ struct cb_memory *cbm = (struct cb_memory *)tbl;
+ tbl += cbm->size;
+ if (cbm->tag == tag)
+ return cbm;
+ }
+ return NULL;
+}
+
+static struct cb_memory *CBMemTable;
+const char *CBvendor = "", *CBpart = "";
+
+// Populate max ram and e820 map info by scanning for a coreboot table.
+void
+coreboot_preinit(void)
+{
+ if (!CONFIG_COREBOOT)
+ return;
+
+ dprintf(3, "Attempting to find coreboot table\n");
+
+ // Find coreboot table.
+ struct cb_header *cbh = find_cb_header(0, 0x1000);
+ if (!cbh)
+ goto fail;
+ struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD);
+ if (cbf) {
+ dprintf(3, "Found coreboot table forwarder.\n");
+ cbh = find_cb_header((char *)((u32)cbf->forward), 0x100);
+ if (!cbh)
+ goto fail;
+ }
+ dprintf(3, "Now attempting to find coreboot memory map\n");
+ struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY);
+ if (!cbm)
+ goto fail;
+
+ int i, count = MEM_RANGE_COUNT(cbm);
+ for (i=0; i<count; i++) {
+ struct cb_memory_range *m = &cbm->map[i];
+ u32 type = m->type;
+ if (type == CB_MEM_TABLE)
+ type = E820_RESERVED;
+ add_e820(m->start, m->size, type);
+ }
+
+ // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this
+ // confuses grub. So, override it.
+ add_e820(0, 16*1024, E820_RAM);
+
+ struct cb_cbmem_ref *cbref = find_cb_subtable(cbh, CB_TAG_CBMEM_CONSOLE);
+ if (cbref) {
+ cbcon = (void*)(u32)cbref->cbmem_addr;
+ dprintf(1, "----- [ seabios log starts here ] -----\n");
+ dprintf(1, "Found coreboot cbmem console @ %llx\n", cbref->cbmem_addr);
+ }
+
+ struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD);
+ if (cbmb) {
+ CBvendor = &cbmb->strings[cbmb->vendor_idx];
+ CBpart = &cbmb->strings[cbmb->part_idx];
+ if (strcmp(CBvendor, "Emulation") == 0 &&
+ memcmp(CBpart, "QEMU", 4) == 0) {
+ PlatformRunningOn |= PF_QEMU;
+ }
+ dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart);
+ }
+
+ return;
+
+fail:
+ // No table found.. Use 16Megs as a dummy value.
+ dprintf(1, "Unable to find coreboot table!\n");
+ add_e820(0, 16*1024*1024, E820_RAM);
+ return;
+}
+
+void debug_cbmem(char c)
+{
+ if (!CONFIG_DEBUG_COREBOOT)
+ return;
+ if (!cbcon)
+ return;
+ if (cbcon->buffer_cursor == cbcon->buffer_size)
+ return;
+ cbcon->buffer_body[cbcon->buffer_cursor++] = c;
+}
+
+/****************************************************************
+ * BIOS table copying
+ ****************************************************************/
+
+// Attempt to find (and relocate) any standard bios tables found in a
+// given address range.
+static void
+scan_tables(u32 start, u32 size)
+{
+ void *p = (void*)ALIGN(start, 16);
+ void *end = (void*)start + size;
+ for (; p<end; p += 16)
+ copy_table(p);
+}
+
+void
+coreboot_platform_setup(void)
+{
+ if (!CONFIG_COREBOOT)
+ return;
+ pci_probe_devices();
+
+ struct cb_memory *cbm = CBMemTable;
+ if (!cbm)
+ return;
+
+ dprintf(3, "Relocating coreboot bios tables\n");
+
+ // Scan CB_MEM_TABLE areas for bios tables.
+ int i, count = MEM_RANGE_COUNT(cbm);
+ for (i=0; i<count; i++) {
+ struct cb_memory_range *m = &cbm->map[i];
+ if (m->type == CB_MEM_TABLE)
+ scan_tables(m->start, m->size);
+ }
+
+ find_acpi_features();
+}
+
+
+/****************************************************************
+ * ulzma
+ ****************************************************************/
+
+// Uncompress data in flash to an area of memory.
+static int
+ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
+{
+ dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
+ CLzmaDecoderState state;
+ int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
+ if (ret != LZMA_RESULT_OK) {
+ dprintf(1, "LzmaDecodeProperties error - %d\n", ret);
+ return -1;
+ }
+ u8 scratch[15980];
+ int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (need > sizeof(scratch)) {
+ dprintf(1, "LzmaDecode need %d have %d\n", need, (unsigned int)sizeof(scratch));
+ return -1;
+ }
+ state.Probs = (CProb *)scratch;
+
+ u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE);
+ if (dstlen > maxlen) {
+ dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen);
+ return -1;
+ }
+ u32 inProcessed, outProcessed;
+ ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen
+ , &inProcessed, dst, dstlen, &outProcessed);
+ if (ret) {
+ dprintf(1, "LzmaDecode returned %d\n", ret);
+ return -1;
+ }
+ return dstlen;
+}
+
+
+/****************************************************************
+ * Coreboot flash format
+ ****************************************************************/
+
+#define CBFS_HEADER_MAGIC 0x4F524243
+#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
+#define CBFS_VERSION1 0x31313131
+
+struct cbfs_header {
+ u32 magic;
+ u32 version;
+ u32 romsize;
+ u32 bootblocksize;
+ u32 align;
+ u32 offset;
+ u32 pad[2];
+} PACKED;
+
+#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE
+
+struct cbfs_file {
+ u64 magic;
+ u32 len;
+ u32 type;
+ u32 checksum;
+ u32 offset;
+ char filename[0];
+} PACKED;
+
+struct cbfs_romfile_s {
+ struct romfile_s file;
+ struct cbfs_file *fhdr;
+ void *data;
+ u32 rawsize, flags;
+};
+
+// Copy a file to memory (uncompressing if necessary)
+static int
+cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
+{
+ if (!CONFIG_COREBOOT_FLASH)
+ return -1;
+
+ struct cbfs_romfile_s *cfile;
+ cfile = container_of(file, struct cbfs_romfile_s, file);
+ u32 size = cfile->rawsize;
+ void *src = cfile->data;
+ if (cfile->flags) {
+ // Compressed - copy to temp ram and uncompress it.
+ void *temp = malloc_tmphigh(size);
+ if (!temp) {
+ warn_noalloc();
+ return -1;
+ }
+ iomemcpy(temp, src, size);
+ int ret = ulzma(dst, maxlen, temp, size);
+ yield();
+ free(temp);
+ return ret;
+ }
+
+ // Not compressed.
+ dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
+ if (size > maxlen) {
+ warn_noalloc();
+ return -1;
+ }
+ iomemcpy(dst, src, size);
+ return size;
+}
+
+void
+coreboot_cbfs_init(void)
+{
+ if (!CONFIG_COREBOOT_FLASH)
+ return;
+
+ struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR;
+ if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) {
+ dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n"
+ , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC));
+ return;
+ }
+ dprintf(1, "Found CBFS header at %p\n", hdr);
+
+ struct cbfs_file *fhdr = (void *)(0 - be32_to_cpu(hdr->romsize)
+ + be32_to_cpu(hdr->offset));
+ for (;;) {
+ if (fhdr < (struct cbfs_file *)(0xFFFFFFFF - be32_to_cpu(hdr->romsize)))
+ break;
+ u64 magic = fhdr->magic;
+ if (magic != CBFS_FILE_MAGIC)
+ break;
+ struct cbfs_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
+ if (!cfile) {
+ warn_noalloc();
+ break;
+ }
+ memset(cfile, 0, sizeof(*cfile));
+ strtcpy(cfile->file.name, fhdr->filename, sizeof(cfile->file.name));
+ cfile->file.size = cfile->rawsize = be32_to_cpu(fhdr->len);
+ cfile->fhdr = fhdr;
+ cfile->file.copy = cbfs_copyfile;
+ cfile->data = (void*)fhdr + be32_to_cpu(fhdr->offset);
+ int len = strlen(cfile->file.name);
+ if (len > 5 && strcmp(&cfile->file.name[len-5], ".lzma") == 0) {
+ // Using compression.
+ cfile->flags = 1;
+ cfile->file.name[len-5] = '\0';
+ cfile->file.size = *(u32*)(cfile->data + LZMA_PROPERTIES_SIZE);
+ }
+ romfile_add(&cfile->file);
+
+ fhdr = (void*)ALIGN((u32)cfile->data + cfile->rawsize
+ , be32_to_cpu(hdr->align));
+ }
+}
+
+struct cbfs_payload_segment {
+ u32 type;
+ u32 compression;
+ u32 offset;
+ u64 load_addr;
+ u32 len;
+ u32 mem_len;
+} PACKED;
+
+#define PAYLOAD_SEGMENT_BSS 0x20535342
+#define PAYLOAD_SEGMENT_ENTRY 0x52544E45
+
+#define CBFS_COMPRESS_NONE 0
+#define CBFS_COMPRESS_LZMA 1
+
+struct cbfs_payload {
+ struct cbfs_payload_segment segments[1];
+};
+
+void
+cbfs_run_payload(struct cbfs_file *fhdr)
+{
+ if (!CONFIG_COREBOOT_FLASH || !fhdr)
+ return;
+ dprintf(1, "Run %s\n", fhdr->filename);
+ struct cbfs_payload *pay = (void*)fhdr + be32_to_cpu(fhdr->offset);
+ struct cbfs_payload_segment *seg = pay->segments;
+ for (;;) {
+ void *src = (void*)pay + be32_to_cpu(seg->offset);
+ void *dest = (void*)(u32)be64_to_cpu(seg->load_addr);
+ u32 src_len = be32_to_cpu(seg->len);
+ u32 dest_len = be32_to_cpu(seg->mem_len);
+ switch (seg->type) {
+ case PAYLOAD_SEGMENT_BSS:
+ dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
+ memset(dest, 0, dest_len);
+ break;
+ case PAYLOAD_SEGMENT_ENTRY: {
+ dprintf(1, "Calling addr %p\n", dest);
+ void (*func)() = dest;
+ func();
+ return;
+ }
+ default:
+ dprintf(3, "Segment %x %d@%p -> %d@%p\n"
+ , seg->type, src_len, src, dest_len, dest);
+ if (seg->compression == cpu_to_be32(CBFS_COMPRESS_NONE)) {
+ if (src_len > dest_len)
+ src_len = dest_len;
+ memcpy(dest, src, src_len);
+ } else if (CONFIG_LZMA
+ && seg->compression == cpu_to_be32(CBFS_COMPRESS_LZMA)) {
+ int ret = ulzma(dest, dest_len, src, src_len);
+ if (ret < 0)
+ return;
+ src_len = ret;
+ } else {
+ dprintf(1, "No support for compression type %x\n"
+ , seg->compression);
+ return;
+ }
+ if (dest_len > src_len)
+ memset(dest + src_len, 0, dest_len - src_len);
+ break;
+ }
+ seg++;
+ }
+}
+
+// Register payloads in "img/" directory with boot system.
+void
+cbfs_payload_setup(void)
+{
+ if (!CONFIG_COREBOOT_FLASH)
+ return;
+ struct romfile_s *file = NULL;
+ for (;;) {
+ file = romfile_findprefix("img/", file);
+ if (!file)
+ break;
+ struct cbfs_romfile_s *cfile;
+ cfile = container_of(file, struct cbfs_romfile_s, file);
+ const char *filename = file->name;
+ char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]);
+ boot_add_cbfs(cfile->fhdr, desc, bootprio_find_named_rom(filename, 0));
+ }
+}
--- /dev/null
+// Compatibility Support Module (CSM) for UEFI / EDK-II
+//
+// Copyright © 2013 Intel Corporation
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h" // CONFIG_*
+#include "csm.h"
+#include "util.h" // checksum
+#include "bregs.h"
+#include "optionroms.h"
+#include "hw/pci.h"
+#include "memmap.h"
+#include "biosvar.h"
+#include "post.h"
+#include "acpi.h"
+#include "boot.h"
+#include "smbios.h"
+#include "hw/pic.h"
+
+struct rsdp_descriptor csm_rsdp VARFSEG __aligned(16);
+
+EFI_COMPATIBILITY16_TABLE csm_compat_table VARFSEG __aligned(16) = {
+ .Signature = 0x24454649,
+ .TableChecksum = 0 /* Filled in by checkrom.py */,
+ .TableLength = sizeof(csm_compat_table),
+ .Compatibility16CallSegment = SEG_BIOS,
+ .Compatibility16CallOffset = 0 /* Filled in by checkrom.py */,
+ .OemIdStringPointer = (u32)"SeaBIOS",
+ .AcpiRsdPtrPointer = (u32)&csm_rsdp,
+};
+
+EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
+EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table;
+
+static u16 PICMask = PIC_IRQMASK_DEFAULT;
+
+extern void __csm_return(struct bregs *regs) __noreturn;
+
+static void
+csm_return(struct bregs *regs)
+{
+ dprintf(3, "handle_csm returning AX=%04x\n", regs->ax);
+
+ PICMask = pic_irqmask_read();
+ __csm_return(regs);
+}
+
+static void
+csm_maininit(struct bregs *regs)
+{
+ interface_init();
+ pci_probe_devices();
+
+ csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
+ csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
+
+ regs->ax = 0;
+
+ csm_return(regs);
+}
+
+/* Legacy16InitializeYourself */
+static void
+handle_csm_0000(struct bregs *regs)
+{
+ dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es,
+ regs->bx);
+
+ csm_init_table = MAKE_FLATPTR(regs->es, regs->bx);
+
+ dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB);
+ dprintf(3, "HiPmmMemory %08x\n", csm_init_table->HiPmmMemory);
+ dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes);
+ dprintf(3, "ReverseThunk %04x:%04x\n", csm_init_table->ReverseThunkCallSegment,
+ csm_init_table->ReverseThunkCallOffset);
+ dprintf(3, "NumE820Entries %08x\n", csm_init_table->NumberE820Entries);
+ dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb);
+ dprintf(3, "ThunkStart %08x\n", csm_init_table->ThunkStart);
+ dprintf(3, "ThunkSize %08x\n", csm_init_table->ThunkSizeInBytes);
+ dprintf(3, "LoPmmMemory %08x\n", csm_init_table->LowPmmMemory);
+ dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes);
+
+ csm_malloc_preinit(csm_init_table->LowPmmMemory,
+ csm_init_table->LowPmmMemorySizeInBytes,
+ csm_init_table->HiPmmMemory,
+ csm_init_table->HiPmmMemorySizeInBytes);
+ reloc_preinit(csm_maininit, regs);
+}
+
+/* Legacy16UpdateBbs */
+static void
+handle_csm_0001(struct bregs *regs)
+{
+ if (!CONFIG_BOOT) {
+ regs->ax = 1;
+ return;
+ }
+
+ dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx);
+
+ csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx);
+ dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion);
+ dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion);
+ dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable);
+ dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable);
+ dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength);
+// dprintf(3, "SioData %08x\n", csm_boot_table->SioData);
+ dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType);
+ dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask);
+ dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries);
+// dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo);
+ dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries);
+ dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable);
+ dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable);
+ dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb);
+ dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable);
+
+ regs->ax = 0;
+}
+
+/* PrepareToBoot */
+static void
+handle_csm_0002(struct bregs *regs)
+{
+ if (!CONFIG_BOOT) {
+ regs->ax = 1;
+ return;
+ }
+
+ dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
+
+ struct e820entry *p = (void *)csm_compat_table.E820Pointer;
+ int i;
+ for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++)
+ add_e820(p[i].start, p[i].size, p[i].type);
+
+ if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) {
+ u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes;
+ add_e820(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED);
+ }
+
+ // For PCIBIOS 1ab10e
+ if (csm_compat_table.IrqRoutingTablePointer &&
+ csm_compat_table.IrqRoutingTableLength) {
+ PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer;
+ dprintf(3, "CSM PIRQ table at %p\n", PirAddr);
+ }
+
+ // For find_resume_vector()... and find_acpi_features()
+ if (csm_rsdp.signature == RSDP_SIGNATURE) {
+ RsdpAddr = &csm_rsdp;
+ dprintf(3, "CSM ACPI RSDP at %p\n", RsdpAddr);
+
+ find_acpi_features();
+ }
+
+ // SMBIOS table needs to be copied into the f-seg
+ // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it
+ if (csm_boot_table->SmbiosTable && !SMBiosAddr)
+ copy_smbios((void *)csm_boot_table->SmbiosTable);
+
+ // MPTABLE is just there; we don't care where.
+
+ // EFI may have reinitialised the video using its *own* driver.
+ enable_vga_console();
+
+ // EFI fills this in for us. Zero it for now...
+ struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
+ bda->hdcount = 0;
+
+ mathcp_setup();
+ timer_setup();
+ clock_setup();
+ device_hardware_setup();
+ wait_threads();
+ interactive_bootmenu();
+
+ prepareboot();
+
+ regs->ax = 0;
+}
+
+/* Boot */
+static void
+handle_csm_0003(struct bregs *regs)
+{
+ if (!CONFIG_BOOT) {
+ regs->ax = 1;
+ return;
+ }
+
+ dprintf(3, "Boot\n");
+
+ startBoot();
+
+ regs->ax = 1;
+}
+
+/* Legacy16DispatchOprom */
+static void
+handle_csm_0005(struct bregs *regs)
+{
+ EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx);
+ struct rom_header *rom;
+ u16 bdf;
+
+ if (!CONFIG_OPTIONROMS) {
+ regs->ax = 1;
+ return;
+ }
+
+ dprintf(3, "Legacy16DispatchOprom rom %p\n", table);
+
+ dprintf(3, "OpromSegment %04x\n", table->OpromSegment);
+ dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
+ dprintf(3, "PnPInstallationCheck %04x:%04x\n",
+ table->PnPInstallationCheckSegment,
+ table->PnPInstallationCheckOffset);
+ dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
+
+ rom = MAKE_FLATPTR(table->OpromSegment, 0);
+ bdf = pci_bus_devfn_to_bdf(table->PciBus, table->PciDeviceFunction);
+
+ rom_reserve(rom->size * 512);
+
+ // XX PnP seg/ofs should never be other than default
+ callrom(rom, bdf);
+
+ rom_confirm(rom->size * 512);
+
+ regs->bx = 0; // FIXME
+ regs->ax = 0;
+}
+
+/* Legacy16GetTableAddress */
+static void
+handle_csm_0006(struct bregs *regs)
+{
+ u16 size = regs->cx;
+ u16 align = regs->dx;
+ u16 region = regs->bx; // (1 for F000 seg, 2 for E000 seg, 0 for either)
+ void *chunk = NULL;
+
+ if (!region)
+ region = 3;
+
+ dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n",
+ size, align, region);
+
+ if (region & 2)
+ chunk = pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
+ if (!chunk && (region & 1))
+ chunk = pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, align);
+
+ dprintf(3, "Legacy16GetTableAddress size %x align %x region %d yields %p\n",
+ size, align, region, chunk);
+ if (chunk) {
+ regs->ds = FLATPTR_TO_SEG(chunk);
+ regs->bx = FLATPTR_TO_OFFSET(chunk);
+ regs->ax = 0;
+ } else {
+ regs->ax = 1;
+ }
+}
+
+void VISIBLE32INIT
+handle_csm(struct bregs *regs)
+{
+ ASSERT32FLAT();
+
+ if (!CONFIG_CSM)
+ return;
+
+ dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax);
+
+ pic_irqmask_write(PICMask);
+
+ switch(regs->ax) {
+ case 0000: handle_csm_0000(regs); break;
+ case 0001: handle_csm_0001(regs); break;
+ case 0002: handle_csm_0002(regs); break;
+ case 0003: handle_csm_0003(regs); break;
+// case 0004: handle_csm_0004(regs); break;
+ case 0005: handle_csm_0005(regs); break;
+ case 0006: handle_csm_0006(regs); break;
+// case 0007: handle_csm_0007(regs); break;
+// case 0008: hamdle_csm_0008(regs); break;
+ default: regs->al = 1;
+ }
+
+ csm_return(regs);
+}
+
+int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave)
+{
+ if (!csm_boot_table)
+ return -1;
+ BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+ int index = 1 + (chanid * 2) + slave;
+ dprintf(3, "CSM bootprio for ATA%d,%d (index %d) is %d\n", chanid, slave,
+ index, bbs[index].BootPriority);
+ return bbs[index].BootPriority;
+}
+
+int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid)
+{
+ if (!csm_boot_table)
+ return -1;
+ BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+ dprintf(3, "CSM bootprio for FDC is %d\n", bbs[0].BootPriority);
+ return bbs[0].BootPriority;
+}
+
+int csm_bootprio_pci(struct pci_device *pci)
+{
+ if (!csm_boot_table)
+ return -1;
+ BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+ int i;
+
+ for (i = 5; i < csm_boot_table->NumberBbsEntries; i++) {
+ if (pci->bdf == pci_to_bdf(bbs[i].Bus, bbs[i].Device, bbs[i].Function)) {
+ dprintf(3, "CSM bootprio for PCI(%d,%d,%d) is %d\n", bbs[i].Bus,
+ bbs[i].Device, bbs[i].Function, bbs[i].BootPriority);
+ return bbs[i].BootPriority;
+ }
+ }
+ return -1;
+}
--- /dev/null
+#ifndef __CSM_H
+#define __CSM_H
+
+#include "types.h"
+
+#define UINT8 u8
+#define UINT16 u16
+#define UINT32 u32
+
+// csm.c
+struct pci_device;
+int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid);
+int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave);
+int csm_bootprio_pci(struct pci_device *pci);
+
+#include "LegacyBios.h"
+
+#endif // __CSM_H
--- /dev/null
+#ifndef __DEV_Q35_H
+#define __DEV_Q35_H
+
+#include "types.h" // u16
+
+#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0
+#define Q35_HOST_BRIDGE_PAM0 0x90
+#define Q35_HOST_BRIDGE_SMRAM 0x9d
+#define Q35_HOST_BRIDGE_PCIEXBAR 0x60
+#define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024)
+#define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xb0000000
+#define Q35_HOST_BRIDGE_PCIEXBAREN ((u64)1)
+#define Q35_HOST_PCIE_PCI_SEGMENT 0
+#define Q35_HOST_PCIE_START_BUS_NUMBER 0
+#define Q35_HOST_PCIE_END_BUS_NUMBER 255
+
+#define PCI_DEVICE_ID_INTEL_ICH9_LPC 0x2918
+#define ICH9_LPC_PMBASE 0x40
+#define ICH9_LPC_PMBASE_RTE 0x1
+
+#define ICH9_LPC_ACPI_CTRL 0x44
+#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80
+#define ICH9_LPC_PIRQA_ROUT 0x60
+#define ICH9_LPC_PIRQE_ROUT 0x68
+#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80
+#define ICH9_LPC_PORT_ELCR1 0x4d0
+#define ICH9_LPC_PORT_ELCR2 0x4d1
+#define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930
+#define ICH9_SMB_SMB_BASE 0x20
+#define ICH9_SMB_HOSTC 0x40
+#define ICH9_SMB_HOSTC_HST_EN 0x01
+
+#define ICH9_ACPI_ENABLE 0x2
+#define ICH9_ACPI_DISABLE 0x3
+
+/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
+#define ICH9_PMIO_GPE0_STS 0x20
+#define ICH9_PMIO_GPE0_BLK_LEN 0x10
+#define ICH9_PMIO_SMI_EN 0x30
+#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5)
+
+/* FADT ACPI_ENABLE/ACPI_DISABLE */
+#define ICH9_APM_ACPI_ENABLE 0x2
+#define ICH9_APM_ACPI_DISABLE 0x3
+
+#endif // dev-q35.h
--- /dev/null
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "lzmadecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ *inSizeProcessed = 0;
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ RC_INIT(inStream, inSize);
+
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ matchByte = outStream[nowPos - rep0];
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+
+ if (nowPos == 0)
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ previousByte = outStream[nowPos - rep0];
+ outStream[nowPos++] = previousByte;
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > nowPos)
+ return LZMA_RESULT_DATA_ERROR;
+
+
+ do
+ {
+ previousByte = outStream[nowPos - rep0];
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
--- /dev/null
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+typedef unsigned char Byte;
+typedef unsigned short UInt16;
+typedef unsigned int UInt32;
+typedef UInt32 SizeT;
+
+#define CProb UInt16
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+
+} CLzmaDecoderState;
+
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
--- /dev/null
+// MPTable generation (on emulators)
+//
+// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "mptable.h" // MPTABLE_SIGNATURE
+#include "hw/pci.h"
+#include "hw/pci_regs.h"
+
+void
+mptable_setup(void)
+{
+ if (! CONFIG_MPTABLE)
+ return;
+
+ dprintf(3, "init MPTable\n");
+
+ // Config structure in temp area.
+ struct mptable_config_s *config = malloc_tmp(32*1024);
+ if (!config) {
+ warn_noalloc();
+ return;
+ }
+ memset(config, 0, sizeof(*config));
+ config->signature = MPCONFIG_SIGNATURE;
+ config->spec = 4;
+ memcpy(config->oemid, BUILD_CPUNAME8, sizeof(config->oemid));
+ memcpy(config->productid, "0.1 ", sizeof(config->productid));
+ config->lapic = BUILD_APIC_ADDR;
+
+ // Detect cpu info
+ u32 cpuid_signature, ebx, ecx, cpuid_features;
+ cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
+ if (! cpuid_signature) {
+ // Use default values.
+ cpuid_signature = 0x600;
+ cpuid_features = 0x201;
+ }
+ int pkgcpus = 1;
+ if (cpuid_features & (1 << 28)) {
+ /* Only populate the MPS tables with the first logical CPU in
+ each package */
+ pkgcpus = (ebx >> 16) & 0xff;
+ pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */
+ }
+ u8 apic_version = readl((u8*)BUILD_APIC_ADDR + 0x30) & 0xff;
+
+ // CPU definitions.
+ struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus;
+ int i;
+ for (i = 0; i < MaxCountCPUs; i+=pkgcpus) {
+ memset(cpu, 0, sizeof(*cpu));
+ cpu->type = MPT_TYPE_CPU;
+ cpu->apicid = i;
+ cpu->apicver = apic_version;
+ /* cpu flags: enabled, bootstrap cpu */
+ cpu->cpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00);
+ cpu->cpusignature = cpuid_signature;
+ cpu->featureflag = cpuid_features;
+ cpu++;
+ }
+ int entrycount = cpu - cpus;
+
+ // PCI bus
+ struct mpt_bus *buses = (void*)cpu, *bus = buses;
+ if (!hlist_empty(&PCIDevices)) {
+ memset(bus, 0, sizeof(*bus));
+ bus->type = MPT_TYPE_BUS;
+ bus->busid = 0;
+ memcpy(bus->bustype, "PCI ", sizeof(bus->bustype));
+ bus++;
+ entrycount++;
+ }
+
+ /* isa bus */
+ int isabusid = bus - buses;
+ memset(bus, 0, sizeof(*bus));
+ bus->type = MPT_TYPE_BUS;
+ bus->busid = isabusid;
+ memcpy(bus->bustype, "ISA ", sizeof(bus->bustype));
+ bus++;
+ entrycount++;
+
+ /* ioapic */
+ u8 ioapic_id = BUILD_IOAPIC_ID;
+ struct mpt_ioapic *ioapic = (void*)bus;
+ memset(ioapic, 0, sizeof(*ioapic));
+ ioapic->type = MPT_TYPE_IOAPIC;
+ ioapic->apicid = ioapic_id;
+ ioapic->apicver = 0x11;
+ ioapic->flags = 1; // enable
+ ioapic->apicaddr = BUILD_IOAPIC_ADDR;
+ entrycount++;
+
+ /* irqs */
+ struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs;
+ int dev = -1;
+ unsigned short pinmask = 0;
+
+ struct pci_device *pci;
+ foreachpci(pci) {
+ u16 bdf = pci->bdf;
+ if (pci_bdf_to_bus(bdf) != 0)
+ break;
+ int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
+ int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
+ if (pin == 0)
+ continue;
+ if (dev != pci_bdf_to_busdev(bdf)) {
+ dev = pci_bdf_to_busdev(bdf);
+ pinmask = 0;
+ }
+ if (pinmask & (1 << pin)) /* pin was seen already */
+ continue;
+ pinmask |= (1 << pin);
+ memset(intsrc, 0, sizeof(*intsrc));
+ intsrc->type = MPT_TYPE_INTSRC;
+ intsrc->irqtype = 0; /* INT */
+ intsrc->irqflag = 1; /* active high */
+ intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */
+ intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1);
+ intsrc->dstapic = ioapic_id;
+ intsrc->dstirq = irq;
+ intsrc++;
+ }
+
+ int irq0_override = romfile_loadint("etc/irq0-override", 0);
+ for (i = 0; i < 16; i++) {
+ memset(intsrc, 0, sizeof(*intsrc));
+ if (BUILD_PCI_IRQS & (1 << i))
+ continue;
+ intsrc->type = MPT_TYPE_INTSRC;
+ intsrc->irqtype = 0; /* INT */
+ intsrc->irqflag = 0; /* conform to bus spec */
+ intsrc->srcbus = isabusid; /* ISA bus */
+ intsrc->srcbusirq = i;
+ intsrc->dstapic = ioapic_id;
+ intsrc->dstirq = i;
+ if (irq0_override) {
+ /* Destination 2 is covered by irq0->inti2 override (i ==
+ 0). Source IRQ 2 is unused */
+ if (i == 0)
+ intsrc->dstirq = 2;
+ else if (i == 2)
+ intsrc--;
+ }
+ intsrc++;
+ }
+
+ /* Local interrupt assignment */
+ intsrc->type = MPT_TYPE_LOCAL_INT;
+ intsrc->irqtype = 3; /* ExtINT */
+ intsrc->irqflag = 0; /* PO, EL default */
+ intsrc->srcbus = isabusid; /* ISA */
+ intsrc->srcbusirq = 0;
+ intsrc->dstapic = 0; /* BSP == APIC #0 */
+ intsrc->dstirq = 0; /* LINTIN0 */
+ intsrc++;
+
+ intsrc->type = MPT_TYPE_LOCAL_INT;
+ intsrc->irqtype = 1; /* NMI */
+ intsrc->irqflag = 0; /* PO, EL default */
+ intsrc->srcbus = isabusid; /* ISA */
+ intsrc->srcbusirq = 0;
+ intsrc->dstapic = 0xff; /* to all local APICs */
+ intsrc->dstirq = 1; /* LINTIN1 */
+ intsrc++;
+ entrycount += intsrc - intsrcs;
+
+ // Finalize config structure.
+ int length = (void*)intsrc - (void*)config;
+ config->entrycount = entrycount;
+ config->length = length;
+ config->checksum -= checksum(config, length);
+
+ // Allocate final memory locations. (In theory the config
+ // structure can go in high memory, but Linux kernels before
+ // v2.6.30 crash with that.)
+ struct mptable_config_s *finalconfig = malloc_fseg(length);
+ struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
+ if (!finalconfig || !floating) {
+ warn_noalloc();
+ free(config);
+ free(finalconfig);
+ free(floating);
+ return;
+ }
+ memcpy(finalconfig, config, length);
+ free(config);
+
+ /* floating pointer structure */
+ memset(floating, 0, sizeof(*floating));
+ floating->signature = MPTABLE_SIGNATURE;
+ floating->physaddr = (u32)finalconfig;
+ floating->length = 1;
+ floating->spec_rev = 4;
+ floating->checksum -= checksum(floating, sizeof(*floating));
+
+ dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
+ floating, finalconfig, length);
+}
--- /dev/null
+#ifndef __MPTABLE_H
+#define __MPTABLE_H
+
+#include "types.h" // u32
+
+#define MPTABLE_SIGNATURE 0x5f504d5f // "_MP_"
+
+struct mptable_floating_s {
+ u32 signature;
+ u32 physaddr;
+ u8 length;
+ u8 spec_rev;
+ u8 checksum;
+ u8 feature1;
+ u8 feature2;
+ u8 reserved[3];
+};
+
+#define MPCONFIG_SIGNATURE 0x504d4350 // "PCMP"
+
+struct mptable_config_s {
+ u32 signature;
+ u16 length;
+ u8 spec;
+ u8 checksum;
+ char oemid[8];
+ char productid[12];
+ u32 oemptr;
+ u16 oemsize;
+ u16 entrycount;
+ u32 lapic;
+ u16 exttable_length;
+ u8 exttable_checksum;
+ u8 reserved;
+} PACKED;
+
+#define MPT_TYPE_CPU 0
+#define MPT_TYPE_BUS 1
+#define MPT_TYPE_IOAPIC 2
+#define MPT_TYPE_INTSRC 3
+#define MPT_TYPE_LOCAL_INT 4
+
+struct mpt_cpu {
+ u8 type;
+ u8 apicid;
+ u8 apicver;
+ u8 cpuflag;
+ u32 cpusignature;
+ u32 featureflag;
+ u32 reserved[2];
+} PACKED;
+
+struct mpt_bus {
+ u8 type;
+ u8 busid;
+ char bustype[6];
+} PACKED;
+
+struct mpt_ioapic {
+ u8 type;
+ u8 apicid;
+ u8 apicver;
+ u8 flags;
+ u32 apicaddr;
+} PACKED;
+
+struct mpt_intsrc {
+ u8 type;
+ u8 irqtype;
+ u16 irqflag;
+ u8 srcbus;
+ u8 srcbusirq;
+ u8 dstapic;
+ u8 dstirq;
+} PACKED;
+
+// mptable.c
+void mptable_setup(void);
+
+#endif // mptable.h
--- /dev/null
+// Initialize MTRRs - mostly useful on KVM.
+//
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "hw/pci.h" // pcimem_start
+#include "paravirt.h" // RamSize
+
+#define MSR_MTRRcap 0x000000fe
+#define MSR_MTRRfix64K_00000 0x00000250
+#define MSR_MTRRfix16K_80000 0x00000258
+#define MSR_MTRRfix16K_A0000 0x00000259
+#define MSR_MTRRfix4K_C0000 0x00000268
+#define MSR_MTRRfix4K_C8000 0x00000269
+#define MSR_MTRRfix4K_D0000 0x0000026a
+#define MSR_MTRRfix4K_D8000 0x0000026b
+#define MSR_MTRRfix4K_E0000 0x0000026c
+#define MSR_MTRRfix4K_E8000 0x0000026d
+#define MSR_MTRRfix4K_F0000 0x0000026e
+#define MSR_MTRRfix4K_F8000 0x0000026f
+#define MSR_MTRRdefType 0x000002ff
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#define MTRR_MEMTYPE_UC 0
+#define MTRR_MEMTYPE_WC 1
+#define MTRR_MEMTYPE_WT 4
+#define MTRR_MEMTYPE_WP 5
+#define MTRR_MEMTYPE_WB 6
+
+void mtrr_setup(void)
+{
+ if (!CONFIG_MTRR_INIT)
+ return;
+
+ u32 eax, ebx, ecx, edx, cpuid_features;
+ cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+ if (!(cpuid_features & CPUID_MTRR))
+ return;
+ if (!(cpuid_features & CPUID_MSR))
+ return;
+
+ dprintf(3, "init mtrr\n");
+
+ u32 mtrr_cap = rdmsr(MSR_MTRRcap);
+ int vcnt = mtrr_cap & 0xff;
+ int fix = mtrr_cap & 0x100;
+ if (!vcnt || !fix)
+ return;
+
+ // Disable MTRRs
+ wrmsr_smp(MSR_MTRRdefType, 0);
+
+ // Set fixed MTRRs
+ union u64b {
+ u8 valb[8];
+ u64 val;
+ } u;
+ u.val = 0;
+ int i;
+ for (i = 0; i < 8; i++)
+ if (RamSize >= 65536 * (i + 1))
+ u.valb[i] = MTRR_MEMTYPE_WB;
+ wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
+ u.val = 0;
+ for (i = 0; i < 8; i++)
+ if (RamSize >= 0x80000 + 16384 * (i + 1))
+ u.valb[i] = MTRR_MEMTYPE_WB;
+ wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
+ wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached
+ int j;
+ for (j = 0; j < 8; j++) {
+ u.val = 0;
+ for (i = 0; i < 8; i++)
+ if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
+ u.valb[i] = MTRR_MEMTYPE_WP;
+ wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
+ }
+
+ // Set variable MTRRs
+ int phys_bits = 36;
+ cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
+ if (eax >= 0x80000008) {
+ /* Get physical bits from leaf 0x80000008 (if available) */
+ cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
+ phys_bits = eax & 0xff;
+ }
+ u64 phys_mask = ((1ull << phys_bits) - 1);
+ for (i=0; i<vcnt; i++) {
+ wrmsr_smp(MTRRphysBase_MSR(i), 0);
+ wrmsr_smp(MTRRphysMask_MSR(i), 0);
+ }
+ /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
+ wrmsr_smp(MTRRphysBase_MSR(0), pcimem_start | MTRR_MEMTYPE_UC);
+ wrmsr_smp(MTRRphysMask_MSR(0)
+ , (-((1ull<<32)-pcimem_start) & phys_mask) | 0x800);
+
+ // Enable fixed and variable MTRRs; set default type.
+ wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);
+}
--- /dev/null
+// Paravirtualization support.
+//
+// Copyright (C) 2013 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2009 Red Hat Inc.
+//
+// Authors:
+// Gleb Natapov <gnatapov@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h" // CONFIG_QEMU
+#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
+#include "ioport.h" // outw
+#include "paravirt.h" // qemu_cfg_preinit
+#include "smbios.h" // smbios_setup
+#include "memmap.h" // add_e820
+#include "hw/cmos.h" // CMOS_*
+#include "acpi.h" // acpi_setup
+#include "mptable.h" // mptable_setup
+#include "hw/pci.h" // create_pirtable
+#include "xen.h" // xen_biostable_setup
+
+// Amount of continuous ram under 4Gig
+u32 RamSize;
+// Amount of continuous ram >4Gig
+u64 RamSizeOver4G;
+// Type of emulator platform.
+int PlatformRunningOn VARFSEG;
+
+/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
+ * should be used to determine that a VM is running under KVM.
+ */
+#define KVM_CPUID_SIGNATURE 0x40000000
+
+static void kvm_preinit(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+ unsigned int eax, ebx, ecx, edx;
+ char signature[13];
+
+ cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
+ memcpy(signature + 0, &ebx, 4);
+ memcpy(signature + 4, &ecx, 4);
+ memcpy(signature + 8, &edx, 4);
+ signature[12] = 0;
+
+ if (strcmp(signature, "KVMKVMKVM") == 0) {
+ dprintf(1, "Running on KVM\n");
+ PlatformRunningOn |= PF_KVM;
+ }
+}
+
+void
+qemu_preinit(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ if (runningOnXen()) {
+ xen_ramsize_preinit();
+ return;
+ }
+
+ PlatformRunningOn = PF_QEMU;
+ kvm_preinit();
+
+ // On emulators, get memory size from nvram.
+ u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
+ | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24));
+ if (rs)
+ rs += 16 * 1024 * 1024;
+ else
+ rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10)
+ | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18))
+ + 1 * 1024 * 1024);
+ RamSize = rs;
+ add_e820(0, rs, E820_RAM);
+
+ // Check for memory over 4Gig
+ u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16)
+ | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24)
+ | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32));
+ RamSizeOver4G = high;
+ add_e820(0x100000000ull, high, E820_RAM);
+
+ /* reserve 256KB BIOS area at the end of 4 GB */
+ add_e820(0xfffc0000, 256*1024, E820_RESERVED);
+
+ dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G);
+}
+
+void
+qemu_platform_setup(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ if (runningOnXen()) {
+ pci_probe_devices();
+ xen_hypercall_setup();
+ xen_biostable_setup();
+ return;
+ }
+
+ // Initialize pci
+ pci_setup();
+ smm_device_setup();
+ smm_setup();
+
+ // Initialize mtrr and smp
+ mtrr_setup();
+ smp_setup();
+
+ // Create bios tables
+ pirtable_setup();
+ mptable_setup();
+ smbios_setup();
+ acpi_setup();
+}
+
+
+/****************************************************************
+ * QEMU firmware config (fw_cfg) interface
+ ****************************************************************/
+
+// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content
+// should be passed via the fw_cfg "file" interface.)
+#define QEMU_CFG_SIGNATURE 0x00
+#define QEMU_CFG_ID 0x01
+#define QEMU_CFG_UUID 0x02
+#define QEMU_CFG_NUMA 0x0d
+#define QEMU_CFG_BOOT_MENU 0x0e
+#define QEMU_CFG_MAX_CPUS 0x0f
+#define QEMU_CFG_FILE_DIR 0x19
+#define QEMU_CFG_ARCH_LOCAL 0x8000
+#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
+#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
+#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
+#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
+
+static void
+qemu_cfg_select(u16 f)
+{
+ outw(f, PORT_QEMU_CFG_CTL);
+}
+
+static void
+qemu_cfg_read(void *buf, int len)
+{
+ insb(PORT_QEMU_CFG_DATA, buf, len);
+}
+
+static void
+qemu_cfg_skip(int len)
+{
+ while (len--)
+ inb(PORT_QEMU_CFG_DATA);
+}
+
+static void
+qemu_cfg_read_entry(void *buf, int e, int len)
+{
+ qemu_cfg_select(e);
+ qemu_cfg_read(buf, len);
+}
+
+struct qemu_romfile_s {
+ struct romfile_s file;
+ int select, skip;
+};
+
+static int
+qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
+{
+ if (file->size > maxlen)
+ return -1;
+ struct qemu_romfile_s *qfile;
+ qfile = container_of(file, struct qemu_romfile_s, file);
+ qemu_cfg_select(qfile->select);
+ qemu_cfg_skip(qfile->skip);
+ qemu_cfg_read(dst, file->size);
+ return file->size;
+}
+
+static void
+qemu_romfile_add(char *name, int select, int skip, int size)
+{
+ struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile));
+ if (!qfile) {
+ warn_noalloc();
+ return;
+ }
+ memset(qfile, 0, sizeof(*qfile));
+ strtcpy(qfile->file.name, name, sizeof(qfile->file.name));
+ qfile->file.size = size;
+ qfile->select = select;
+ qfile->skip = skip;
+ qfile->file.copy = qemu_cfg_read_file;
+ romfile_add(&qfile->file);
+}
+
+struct e820_reservation {
+ u64 address;
+ u64 length;
+ u32 type;
+};
+
+#define SMBIOS_FIELD_ENTRY 0
+#define SMBIOS_TABLE_ENTRY 1
+
+struct qemu_smbios_header {
+ u16 length;
+ u8 headertype;
+ u8 tabletype;
+ u16 fieldoffset;
+} PACKED;
+
+// Populate romfile entries for legacy fw_cfg ports (that predate the
+// "file" interface).
+static void
+qemu_cfg_legacy(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ // Misc config items.
+ qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2);
+ qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);
+ qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
+
+ // NUMA data
+ u64 numacount;
+ qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount));
+ int max_cpu = romfile_loadint("etc/max-cpus", 0);
+ qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount)
+ , max_cpu*sizeof(u64));
+ qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA
+ , sizeof(numacount) + max_cpu*sizeof(u64)
+ , numacount*sizeof(u64));
+
+ // e820 data
+ u32 count32;
+ qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));
+ if (count32) {
+ struct e820_reservation entry;
+ int i;
+ for (i = 0; i < count32; i++) {
+ qemu_cfg_read(&entry, sizeof(entry));
+ add_e820(entry.address, entry.length, entry.type);
+ }
+ } else if (runningOnKVM()) {
+ // Backwards compatibility - provide hard coded range.
+ // 4 pages before the bios, 3 pages for vmx tss pages, the
+ // other page for EPT real mode pagetable
+ add_e820(0xfffbc000, 4*4096, E820_RESERVED);
+ }
+
+ // ACPI tables
+ char name[128];
+ u16 cnt;
+ qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
+ int i, offset = sizeof(cnt);
+ for (i = 0; i < cnt; i++) {
+ u16 len;
+ qemu_cfg_read(&len, sizeof(len));
+ offset += sizeof(len);
+ snprintf(name, sizeof(name), "acpi/table%d", i);
+ qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
+ qemu_cfg_skip(len);
+ offset += len;
+ }
+
+ // SMBIOS info
+ qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
+ offset = sizeof(cnt);
+ for (i = 0; i < cnt; i++) {
+ struct qemu_smbios_header header;
+ qemu_cfg_read(&header, sizeof(header));
+ if (header.headertype == SMBIOS_FIELD_ENTRY) {
+ snprintf(name, sizeof(name), "smbios/field%d-%d"
+ , header.tabletype, header.fieldoffset);
+ qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
+ , offset + sizeof(header)
+ , header.length - sizeof(header));
+ } else {
+ snprintf(name, sizeof(name), "smbios/table%d-%d"
+ , header.tabletype, i);
+ qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
+ , offset + 3, header.length - 3);
+ }
+ qemu_cfg_skip(header.length - sizeof(header));
+ offset += header.length;
+ }
+}
+
+struct QemuCfgFile {
+ u32 size; /* file size */
+ u16 select; /* write this to 0x510 to read it */
+ u16 reserved;
+ char name[56];
+};
+
+void qemu_cfg_init(void)
+{
+ if (!runningOnQEMU())
+ return;
+
+ // Detect fw_cfg interface.
+ qemu_cfg_select(QEMU_CFG_SIGNATURE);
+ char *sig = "QEMU";
+ int i;
+ for (i = 0; i < 4; i++)
+ if (inb(PORT_QEMU_CFG_DATA) != sig[i])
+ return;
+ dprintf(1, "Found QEMU fw_cfg\n");
+
+ // Populate romfiles for legacy fw_cfg entries
+ qemu_cfg_legacy();
+
+ // Load files found in the fw_cfg file directory
+ u32 count;
+ qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
+ count = be32_to_cpu(count);
+ u32 e;
+ for (e = 0; e < count; e++) {
+ struct QemuCfgFile qfile;
+ qemu_cfg_read(&qfile, sizeof(qfile));
+ qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
+ , 0, be32_to_cpu(qfile.size));
+ }
+}
--- /dev/null
+#ifndef __PV_H
+#define __PV_H
+
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+
+// Types of paravirtualized platforms.
+#define PF_QEMU (1<<0)
+#define PF_XEN (1<<1)
+#define PF_KVM (1<<2)
+
+extern u32 RamSize;
+extern u64 RamSizeOver4G;
+extern int PlatformRunningOn;
+
+static inline int runningOnQEMU(void) {
+ return CONFIG_QEMU || (
+ CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU);
+}
+static inline int runningOnXen(void) {
+ return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN;
+}
+static inline int runningOnKVM(void) {
+ return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM;
+}
+
+void qemu_preinit(void);
+void qemu_platform_setup(void);
+void qemu_cfg_init(void);
+
+#endif
--- /dev/null
+// Initialize PCI devices (on emulators)
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "hw/pci.h" // pci_config_readl
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_COMMAND
+#include "ioport.h" // PORT_ATA1_CMD_BASE
+#include "config.h" // CONFIG_*
+#include "memmap.h" // add_e820
+#include "paravirt.h" // RamSize
+#include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR
+#include "list.h" // struct hlist_node
+#include "acpi.h" // acpi_pm1a_cnt
+
+#define PCI_DEVICE_MEM_MIN 0x1000
+#define PCI_BRIDGE_IO_MIN 0x1000
+#define PCI_BRIDGE_MEM_MIN 0x100000
+
+enum pci_region_type {
+ PCI_REGION_TYPE_IO,
+ PCI_REGION_TYPE_MEM,
+ PCI_REGION_TYPE_PREFMEM,
+ PCI_REGION_TYPE_COUNT,
+};
+
+static const char *region_type_name[] = {
+ [ PCI_REGION_TYPE_IO ] = "io",
+ [ PCI_REGION_TYPE_MEM ] = "mem",
+ [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
+};
+
+u64 pcimem_start = BUILD_PCIMEM_START;
+u64 pcimem_end = BUILD_PCIMEM_END;
+u64 pcimem64_start = BUILD_PCIMEM64_START;
+u64 pcimem64_end = BUILD_PCIMEM64_END;
+
+struct pci_region_entry {
+ struct pci_device *dev;
+ int bar;
+ u64 size;
+ u64 align;
+ int is64;
+ enum pci_region_type type;
+ struct hlist_node node;
+};
+
+struct pci_region {
+ /* pci region assignments */
+ u64 base;
+ struct hlist_head list;
+};
+
+struct pci_bus {
+ struct pci_region r[PCI_REGION_TYPE_COUNT];
+ struct pci_device *bus_dev;
+};
+
+static u32 pci_bar(struct pci_device *pci, int region_num)
+{
+ if (region_num != PCI_ROM_SLOT) {
+ return PCI_BASE_ADDRESS_0 + region_num * 4;
+ }
+
+#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+ u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+ return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
+}
+
+static void
+pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64)
+{
+ u32 ofs = pci_bar(pci, bar);
+ pci_config_writel(pci->bdf, ofs, addr);
+ if (is64)
+ pci_config_writel(pci->bdf, ofs + 4, addr >> 32);
+}
+
+
+/****************************************************************
+ * Misc. device init
+ ****************************************************************/
+
+/* host irqs corresponding to PCI irqs A-D */
+const u8 pci_irqs[4] = {
+ 10, 10, 11, 11
+};
+
+static int dummy_pci_slot_get_irq(struct pci_device *pci, int pin)
+{
+ dprintf(1, "pci_slot_get_irq called with unknown routing\n");
+
+ return 0xff; /* PCI defined "unknown" or "no connection" for x86 */
+}
+
+static int (*pci_slot_get_irq)(struct pci_device *pci, int pin) =
+ dummy_pci_slot_get_irq;
+
+// Return the global irq number corresponding to a host bus device irq pin.
+static int piix_pci_slot_get_irq(struct pci_device *pci, int pin)
+{
+ int slot_addend = 0;
+
+ while (pci->parent != NULL) {
+ slot_addend += pci_bdf_to_dev(pci->bdf);
+ pci = pci->parent;
+ }
+ slot_addend += pci_bdf_to_dev(pci->bdf) - 1;
+ return pci_irqs[(pin - 1 + slot_addend) & 3];
+}
+
+static int mch_pci_slot_get_irq(struct pci_device *pci, int pin)
+{
+ int irq, slot, pin_addend = 0;
+
+ while (pci->parent != NULL) {
+ pin_addend += pci_bdf_to_dev(pci->bdf);
+ pci = pci->parent;
+ }
+ slot = pci_bdf_to_dev(pci->bdf);
+
+ switch (slot) {
+ /* Slots 0-24 rotate slot:pin mapping similar to piix above, but
+ with a different starting index - see q35-acpi-dsdt.dsl */
+ case 0 ... 24:
+ irq = pci_irqs[(pin - 1 + pin_addend + slot) & 3];
+ break;
+ /* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */
+ case 25 ... 31:
+ irq = pci_irqs[(pin - 1 + pin_addend) & 3];
+ break;
+ }
+
+ return irq;
+}
+
+/* PIIX3/PIIX4 PCI to ISA bridge */
+static void piix_isa_bridge_setup(struct pci_device *pci, void *arg)
+{
+ int i, irq;
+ u8 elcr[2];
+
+ elcr[0] = 0x00;
+ elcr[1] = 0x00;
+ for (i = 0; i < 4; i++) {
+ irq = pci_irqs[i];
+ /* set to trigger level */
+ elcr[irq >> 3] |= (1 << (irq & 7));
+ /* activate irq remapping in PIIX */
+ pci_config_writeb(pci->bdf, 0x60 + i, irq);
+ }
+ outb(elcr[0], 0x4d0);
+ outb(elcr[1], 0x4d1);
+ dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
+}
+
+/* ICH9 LPC PCI to ISA bridge */
+/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
+void mch_isa_bridge_setup(struct pci_device *dev, void *arg)
+{
+ u16 bdf = dev->bdf;
+ int i, irq;
+ u8 elcr[2];
+
+ elcr[0] = 0x00;
+ elcr[1] = 0x00;
+
+ for (i = 0; i < 4; i++) {
+ irq = pci_irqs[i];
+ /* set to trigger level */
+ elcr[irq >> 3] |= (1 << (irq & 7));
+
+ /* activate irq remapping in LPC */
+
+ /* PIRQ[A-D] routing */
+ pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i, irq);
+ /* PIRQ[E-H] routing */
+ pci_config_writeb(bdf, ICH9_LPC_PIRQE_ROUT + i, irq);
+ }
+ outb(elcr[0], ICH9_LPC_PORT_ELCR1);
+ outb(elcr[1], ICH9_LPC_PORT_ELCR2);
+ dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]);
+
+ /* pm io base */
+ pci_config_writel(bdf, ICH9_LPC_PMBASE,
+ PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE);
+
+ /* acpi enable, SCI: IRQ9 000b = irq9*/
+ pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
+
+ acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
+ pmtimer_setup(PORT_ACPI_PM_BASE + 0x08);
+}
+
+static void storage_ide_setup(struct pci_device *pci, void *arg)
+{
+ /* IDE: we map it as in ISA mode */
+ pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0);
+ pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0);
+ pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0);
+ pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0);
+}
+
+/* PIIX3/PIIX4 IDE */
+static void piix_ide_setup(struct pci_device *pci, void *arg)
+{
+ u16 bdf = pci->bdf;
+ pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
+ pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
+}
+
+static void pic_ibm_setup(struct pci_device *pci, void *arg)
+{
+ /* PIC, IBM, MPIC & MPIC2 */
+ pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0);
+}
+
+static void apple_macio_setup(struct pci_device *pci, void *arg)
+{
+ /* macio bridge */
+ pci_set_io_region_addr(pci, 0, 0x80800000, 0);
+}
+
+/* PIIX4 Power Management device (for ACPI) */
+static void piix4_pm_setup(struct pci_device *pci, void *arg)
+{
+ u16 bdf = pci->bdf;
+ // acpi sci is hardwired to 9
+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
+
+ pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
+ pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
+ pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
+ pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
+
+ acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
+ pmtimer_setup(PORT_ACPI_PM_BASE + 0x08);
+}
+
+/* ICH9 SMBUS */
+/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */
+void ich9_smbus_setup(struct pci_device *dev, void *arg)
+{
+ u16 bdf = dev->bdf;
+ /* map smbus into io space */
+ pci_config_writel(bdf, ICH9_SMB_SMB_BASE,
+ PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+
+ /* enable SMBus */
+ pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
+}
+
+static const struct pci_device_id pci_device_tbl[] = {
+ /* PIIX3/PIIX4 PCI to ISA bridge */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
+ piix_isa_bridge_setup),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+ piix_isa_bridge_setup),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
+ mch_isa_bridge_setup),
+
+ /* STORAGE IDE */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
+ PCI_CLASS_STORAGE_IDE, piix_ide_setup),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_CLASS_STORAGE_IDE, piix_ide_setup),
+ PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
+ storage_ide_setup),
+
+ /* PIC, IBM, MIPC & MPIC2 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_setup),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_setup),
+
+ /* PIIX4 Power Management device (for ACPI) */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ piix4_pm_setup),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS,
+ ich9_smbus_setup),
+
+ /* 0xff00 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup),
+
+ PCI_DEVICE_END,
+};
+
+static void pci_bios_init_device(struct pci_device *pci)
+{
+ u16 bdf = pci->bdf;
+ dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n"
+ , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
+ , pci->vendor, pci->device);
+
+ /* map the interrupt */
+ int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
+ if (pin != 0)
+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
+
+ pci_init_device(pci_device_tbl, pci, NULL);
+
+ /* enable memory mappings */
+ pci_config_maskw(bdf, PCI_COMMAND, 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR);
+}
+
+static void pci_bios_init_devices(void)
+{
+ struct pci_device *pci;
+ foreachpci(pci) {
+ pci_bios_init_device(pci);
+ }
+}
+
+static void pci_enable_default_vga(void)
+{
+ struct pci_device *pci;
+
+ foreachpci(pci) {
+ if (is_pci_vga(pci)) {
+ dprintf(1, "PCI: Using %02x:%02x.%x for primary VGA\n",
+ pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+ pci_bdf_to_fn(pci->bdf));
+ return;
+ }
+ }
+
+ pci = pci_find_class(PCI_CLASS_DISPLAY_VGA);
+ if (!pci) {
+ dprintf(1, "PCI: No VGA devices found\n");
+ return;
+ }
+
+ dprintf(1, "PCI: Enabling %02x:%02x.%x for primary VGA\n",
+ pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+ pci_bdf_to_fn(pci->bdf));
+
+ pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+ while (pci->parent) {
+ pci = pci->parent;
+
+ dprintf(1, "PCI: Setting VGA enable on bridge %02x:%02x.%x\n",
+ pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+ pci_bdf_to_fn(pci->bdf));
+
+ pci_config_maskw(pci->bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_VGA);
+ pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ }
+}
+
+/****************************************************************
+ * Platform device initialization
+ ****************************************************************/
+
+void i440fx_mem_addr_setup(struct pci_device *dev, void *arg)
+{
+ if (RamSize <= 0x80000000)
+ pcimem_start = 0x80000000;
+ else if (RamSize <= 0xc0000000)
+ pcimem_start = 0xc0000000;
+
+ pci_slot_get_irq = piix_pci_slot_get_irq;
+}
+
+void mch_mem_addr_setup(struct pci_device *dev, void *arg)
+{
+ u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
+ u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE;
+
+ /* setup mmconfig */
+ u16 bdf = dev->bdf;
+ u32 upper = addr >> 32;
+ u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
+ add_e820(addr, size, E820_RESERVED);
+
+ /* setup pci i/o window (above mmconfig) */
+ pcimem_start = addr + size;
+
+ pci_slot_get_irq = mch_pci_slot_get_irq;
+}
+
+static const struct pci_device_id pci_platform_tbl[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
+ i440fx_mem_addr_setup),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH,
+ mch_mem_addr_setup),
+ PCI_DEVICE_END
+};
+
+static void pci_bios_init_platform(void)
+{
+ struct pci_device *pci;
+ foreachpci(pci) {
+ pci_init_device(pci_platform_tbl, pci, NULL);
+ }
+}
+
+
+/****************************************************************
+ * Bus initialization
+ ****************************************************************/
+
+static void
+pci_bios_init_bus_rec(int bus, u8 *pci_bus)
+{
+ int bdf;
+ u16 class;
+
+ dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
+
+ /* prevent accidental access to unintended devices */
+ foreachbdf(bdf, bus) {
+ class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+ if (class == PCI_CLASS_BRIDGE_PCI) {
+ pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
+ pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
+ }
+ }
+
+ foreachbdf(bdf, bus) {
+ class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+ if (class != PCI_CLASS_BRIDGE_PCI) {
+ continue;
+ }
+ dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
+
+ u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
+ if (pribus != bus) {
+ dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
+ pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
+ } else {
+ dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
+ }
+
+ u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+ (*pci_bus)++;
+ if (*pci_bus != secbus) {
+ dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
+ secbus, *pci_bus);
+ secbus = *pci_bus;
+ pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
+ } else {
+ dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
+ }
+
+ /* set to max for access to all subordinate buses.
+ later set it to accurate value */
+ u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
+ pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
+
+ pci_bios_init_bus_rec(secbus, pci_bus);
+
+ if (subbus != *pci_bus) {
+ dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
+ subbus, *pci_bus);
+ subbus = *pci_bus;
+ } else {
+ dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
+ }
+ pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
+ }
+}
+
+static void
+pci_bios_init_bus(void)
+{
+ u8 pci_bus = 0;
+ pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
+}
+
+
+/****************************************************************
+ * Bus sizing
+ ****************************************************************/
+
+static void
+pci_bios_get_bar(struct pci_device *pci, int bar,
+ int *ptype, u64 *psize, int *pis64)
+{
+ u32 ofs = pci_bar(pci, bar);
+ u16 bdf = pci->bdf;
+ u32 old = pci_config_readl(bdf, ofs);
+ int is64 = 0, type = PCI_REGION_TYPE_MEM;
+ u64 mask;
+
+ if (bar == PCI_ROM_SLOT) {
+ mask = PCI_ROM_ADDRESS_MASK;
+ pci_config_writel(bdf, ofs, mask);
+ } else {
+ if (old & PCI_BASE_ADDRESS_SPACE_IO) {
+ mask = PCI_BASE_ADDRESS_IO_MASK;
+ type = PCI_REGION_TYPE_IO;
+ } else {
+ mask = PCI_BASE_ADDRESS_MEM_MASK;
+ if (old & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ type = PCI_REGION_TYPE_PREFMEM;
+ is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
+ == PCI_BASE_ADDRESS_MEM_TYPE_64);
+ }
+ pci_config_writel(bdf, ofs, ~0);
+ }
+ u64 val = pci_config_readl(bdf, ofs);
+ pci_config_writel(bdf, ofs, old);
+ if (is64) {
+ u32 hold = pci_config_readl(bdf, ofs + 4);
+ pci_config_writel(bdf, ofs + 4, ~0);
+ u32 high = pci_config_readl(bdf, ofs + 4);
+ pci_config_writel(bdf, ofs + 4, hold);
+ val |= ((u64)high << 32);
+ mask |= ((u64)0xffffffff << 32);
+ *psize = (~(val & mask)) + 1;
+ } else {
+ *psize = ((~(val & mask)) + 1) & 0xffffffff;
+ }
+ *ptype = type;
+ *pis64 = is64;
+}
+
+static int pci_bios_bridge_region_is64(struct pci_region *r,
+ struct pci_device *pci, int type)
+{
+ if (type != PCI_REGION_TYPE_PREFMEM)
+ return 0;
+ u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
+ if (!pmem) {
+ pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0);
+ pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
+ pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0);
+ }
+ if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64)
+ return 0;
+ struct pci_region_entry *entry;
+ hlist_for_each_entry(entry, &r->list, node) {
+ if (!entry->is64)
+ return 0;
+ }
+ return 1;
+}
+
+static u64 pci_region_align(struct pci_region *r)
+{
+ struct pci_region_entry *entry;
+ hlist_for_each_entry(entry, &r->list, node) {
+ // The first entry in the sorted list has the largest alignment
+ return entry->align;
+ }
+ return 1;
+}
+
+static u64 pci_region_sum(struct pci_region *r)
+{
+ u64 sum = 0;
+ struct pci_region_entry *entry;
+ hlist_for_each_entry(entry, &r->list, node) {
+ sum += entry->size;
+ }
+ return sum;
+}
+
+static void pci_region_migrate_64bit_entries(struct pci_region *from,
+ struct pci_region *to)
+{
+ struct hlist_node *n, **last = &to->list.first;
+ struct pci_region_entry *entry;
+ hlist_for_each_entry_safe(entry, n, &from->list, node) {
+ if (!entry->is64)
+ continue;
+ // Move from source list to destination list.
+ hlist_del(&entry->node);
+ hlist_add(&entry->node, last);
+ }
+}
+
+static struct pci_region_entry *
+pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
+ int bar, u64 size, u64 align, int type, int is64)
+{
+ struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
+ if (!entry) {
+ warn_noalloc();
+ return NULL;
+ }
+ memset(entry, 0, sizeof(*entry));
+ entry->dev = dev;
+ entry->bar = bar;
+ entry->size = size;
+ entry->align = align;
+ entry->is64 = is64;
+ entry->type = type;
+ // Insert into list in sorted order.
+ struct hlist_node **pprev;
+ struct pci_region_entry *pos;
+ hlist_for_each_entry_pprev(pos, pprev, &bus->r[type].list, node) {
+ if (pos->align < align || (pos->align == align && pos->size < size))
+ break;
+ }
+ hlist_add(&entry->node, pprev);
+ return entry;
+}
+
+static int pci_bios_check_devices(struct pci_bus *busses)
+{
+ dprintf(1, "PCI: check devices\n");
+
+ // Calculate resources needed for regular (non-bus) devices.
+ struct pci_device *pci;
+ foreachpci(pci) {
+ if (pci->class == PCI_CLASS_BRIDGE_PCI)
+ busses[pci->secondary_bus].bus_dev = pci;
+
+ struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)];
+ int i;
+ for (i = 0; i < PCI_NUM_REGIONS; i++) {
+ if ((pci->class == PCI_CLASS_BRIDGE_PCI) &&
+ (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT))
+ continue;
+ int type, is64;
+ u64 size;
+ pci_bios_get_bar(pci, i, &type, &size, &is64);
+ if (size == 0)
+ continue;
+
+ if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN)
+ size = PCI_DEVICE_MEM_MIN;
+ struct pci_region_entry *entry = pci_region_create_entry(
+ bus, pci, i, size, size, type, is64);
+ if (!entry)
+ return -1;
+
+ if (is64)
+ i++;
+ }
+ }
+
+ // Propagate required bus resources to parent busses.
+ int secondary_bus;
+ for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) {
+ struct pci_bus *s = &busses[secondary_bus];
+ if (!s->bus_dev)
+ continue;
+ struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
+ int type;
+ for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
+ u64 align = (type == PCI_REGION_TYPE_IO) ?
+ PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
+ if (pci_region_align(&s->r[type]) > align)
+ align = pci_region_align(&s->r[type]);
+ u64 sum = pci_region_sum(&s->r[type]);
+ u64 size = ALIGN(sum, align);
+ int is64 = pci_bios_bridge_region_is64(&s->r[type],
+ s->bus_dev, type);
+ // entry->bar is -1 if the entry represents a bridge region
+ struct pci_region_entry *entry = pci_region_create_entry(
+ parent, s->bus_dev, -1, size, align, type, is64);
+ if (!entry)
+ return -1;
+ dprintf(1, "PCI: secondary bus %d size %08llx type %s\n",
+ entry->dev->secondary_bus, size,
+ region_type_name[entry->type]);
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************************
+ * BAR assignment
+ ****************************************************************/
+
+// Setup region bases (given the regions' size and alignment)
+static int pci_bios_init_root_regions(struct pci_bus *bus)
+{
+ bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
+
+ struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
+ struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
+
+ if (pci_region_align(r_start) < pci_region_align(r_end)) {
+ // Swap regions to improve alignment.
+ r_end = r_start;
+ r_start = &bus->r[PCI_REGION_TYPE_PREFMEM];
+ }
+ u64 sum = pci_region_sum(r_end);
+ u64 align = pci_region_align(r_end);
+ r_end->base = ALIGN_DOWN((pcimem_end - sum), align);
+ sum = pci_region_sum(r_start);
+ align = pci_region_align(r_start);
+ r_start->base = ALIGN_DOWN((r_end->base - sum), align);
+
+ if ((r_start->base < pcimem_start) ||
+ (r_start->base > pcimem_end))
+ // Memory range requested is larger than available.
+ return -1;
+ return 0;
+}
+
+#define PCI_IO_SHIFT 8
+#define PCI_MEMORY_SHIFT 16
+#define PCI_PREF_MEMORY_SHIFT 16
+
+static void
+pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr)
+{
+ u16 bdf = entry->dev->bdf;
+ if (entry->bar >= 0) {
+ dprintf(1, "PCI: map device bdf=%02x:%02x.%x"
+ " bar %d, addr %08llx, size %08llx [%s]\n",
+ pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
+ entry->bar, addr, entry->size, region_type_name[entry->type]);
+
+ pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64);
+ return;
+ }
+
+ u64 limit = addr + entry->size - 1;
+ if (entry->type == PCI_REGION_TYPE_IO) {
+ pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT);
+ pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
+ pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
+ pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
+ }
+ if (entry->type == PCI_REGION_TYPE_MEM) {
+ pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT);
+ pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
+ }
+ if (entry->type == PCI_REGION_TYPE_PREFMEM) {
+ pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT);
+ pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT);
+ pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32);
+ pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32);
+ }
+}
+
+static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
+{
+ struct hlist_node *n;
+ struct pci_region_entry *entry;
+ hlist_for_each_entry_safe(entry, n, &r->list, node) {
+ u64 addr = r->base;
+ r->base += entry->size;
+ if (entry->bar == -1)
+ // Update bus base address if entry is a bridge region
+ busses[entry->dev->secondary_bus].r[entry->type].base = addr;
+ pci_region_map_one_entry(entry, addr);
+ hlist_del(&entry->node);
+ free(entry);
+ }
+}
+
+static void pci_bios_map_devices(struct pci_bus *busses)
+{
+ if (pci_bios_init_root_regions(busses)) {
+ struct pci_region r64_mem, r64_pref;
+ r64_mem.list.first = NULL;
+ r64_pref.list.first = NULL;
+ pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
+ &r64_mem);
+ pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
+ &r64_pref);
+
+ if (pci_bios_init_root_regions(busses))
+ panic("PCI: out of 32bit address space\n");
+
+ u64 sum_mem = pci_region_sum(&r64_mem);
+ u64 sum_pref = pci_region_sum(&r64_pref);
+ u64 align_mem = pci_region_align(&r64_mem);
+ u64 align_pref = pci_region_align(&r64_pref);
+
+ r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem);
+ r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref);
+ pcimem64_start = r64_mem.base;
+ pcimem64_end = r64_pref.base + sum_pref;
+
+ pci_region_map_entries(busses, &r64_mem);
+ pci_region_map_entries(busses, &r64_pref);
+ } else {
+ // no bars mapped high -> drop 64bit window (see dsdt)
+ pcimem64_start = 0;
+ }
+ // Map regions on each device.
+ int bus;
+ for (bus = 0; bus<=MaxPCIBus; bus++) {
+ int type;
+ for (type = 0; type < PCI_REGION_TYPE_COUNT; type++)
+ pci_region_map_entries(busses, &busses[bus].r[type]);
+ }
+}
+
+
+/****************************************************************
+ * Main setup code
+ ****************************************************************/
+
+void
+pci_setup(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ dprintf(3, "pci setup\n");
+
+ dprintf(1, "=== PCI bus & bridge init ===\n");
+ if (pci_probe_host() != 0) {
+ return;
+ }
+ pci_bios_init_bus();
+
+ dprintf(1, "=== PCI device probing ===\n");
+ pci_probe_devices();
+
+ pcimem_start = RamSize;
+ pci_bios_init_platform();
+
+ dprintf(1, "=== PCI new allocation pass #1 ===\n");
+ struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1));
+ if (!busses) {
+ warn_noalloc();
+ return;
+ }
+ memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
+ if (pci_bios_check_devices(busses))
+ return;
+
+ dprintf(1, "=== PCI new allocation pass #2 ===\n");
+ pci_bios_map_devices(busses);
+
+ pci_bios_init_devices();
+
+ free(busses);
+
+ pci_enable_default_vga();
+}
--- /dev/null
+// PIR table generation (for emulators)
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002 MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "hw/pci.h" // struct pir_header
+#include "config.h" // CONFIG_*
+#include "util.h" // checksum
+
+struct pir_header *PirAddr VARFSEG;
+
+struct pir_table {
+ struct pir_header pir;
+ struct pir_slot slots[6];
+} PACKED;
+
+extern struct pir_table PIR_TABLE;
+#if CONFIG_PIRTABLE
+struct pir_table PIR_TABLE __aligned(16) VARFSEG = {
+ .pir = {
+ .version = 0x0100,
+ .size = sizeof(struct pir_table),
+ .router_devfunc = 0x08,
+ .compatible_devid = 0x122e8086,
+ },
+ .slots = {
+ {
+ // first slot entry PCI-to-ISA (embedded)
+ .dev = 1<<3,
+ .links = {
+ {.link = 0x60, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x61, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x62, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x63, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 0, // embedded
+ }, {
+ // second slot entry: 1st PCI slot
+ .dev = 2<<3,
+ .links = {
+ {.link = 0x61, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x62, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x63, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x60, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 1,
+ }, {
+ // third slot entry: 2nd PCI slot
+ .dev = 3<<3,
+ .links = {
+ {.link = 0x62, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x63, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x60, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x61, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 2,
+ }, {
+ // 4th slot entry: 3rd PCI slot
+ .dev = 4<<3,
+ .links = {
+ {.link = 0x63, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x60, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x61, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x62, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 3,
+ }, {
+ // 5th slot entry: 4rd PCI slot
+ .dev = 5<<3,
+ .links = {
+ {.link = 0x60, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x61, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x62, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x63, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 4,
+ }, {
+ // 6th slot entry: 5rd PCI slot
+ .dev = 6<<3,
+ .links = {
+ {.link = 0x61, .bitmap = 0xdef8}, // INTA#
+ {.link = 0x62, .bitmap = 0xdef8}, // INTB#
+ {.link = 0x63, .bitmap = 0xdef8}, // INTC#
+ {.link = 0x60, .bitmap = 0xdef8}, // INTD#
+ },
+ .slot_nr = 5,
+ },
+ }
+};
+#endif // CONFIG_PIRTABLE
+
+void
+pirtable_setup(void)
+{
+ if (! CONFIG_PIRTABLE)
+ return;
+
+ dprintf(3, "init PIR table\n");
+
+ PIR_TABLE.pir.signature = PIR_SIGNATURE;
+ PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE));
+ PirAddr = &PIR_TABLE.pir;
+}
--- /dev/null
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+/*
+ * Copyright (c) 2010 Isaku Yamahata
+ * yamahata at valinux co jp
+ * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
+ */
+
+DefinitionBlock (
+ "q35-acpi-dsdt.aml",// Output Filename
+ "DSDT", // Signature
+ 0x01, // DSDT Compliance Revision
+ "BXPC", // OEMID
+ "BXDSDT", // TABLE ID
+ 0x2 // OEM Revision
+ )
+{
+
+#include "acpi-dsdt-dbug.dsl"
+
+ Scope(\_SB) {
+ OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
+ OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
+ Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
+ PCIB, 8,
+ }
+ }
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+ Scope(\_SB) {
+ Device(PCI0) {
+ Name(_HID, EisaId("PNP0A08"))
+ Name(_CID, EisaId("PNP0A03"))
+ Name(_ADR, 0x00)
+ Name(_UID, 1)
+
+ // _OSC: based on sample of ACPI3.0b spec
+ Name(SUPP, 0) // PCI _OSC Support Field value
+ Name(CTRL, 0) // PCI _OSC Control Field value
+ Method(_OSC, 4) {
+ // Create DWORD-addressable fields from the Capabilities Buffer
+ CreateDWordField(Arg3, 0, CDW1)
+
+ // Check for proper UUID
+ If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+ // Create DWORD-addressable fields from the Capabilities Buffer
+ CreateDWordField(Arg3, 4, CDW2)
+ CreateDWordField(Arg3, 8, CDW3)
+
+ // Save Capabilities DWORD2 & 3
+ Store(CDW2, SUPP)
+ Store(CDW3, CTRL)
+
+ // Always allow native PME, AER (no dependencies)
+ // Never allow SHPC (no SHPC controller in this system)
+ And(CTRL, 0x1D, CTRL)
+
+#if 0 // For now, nothing to do
+ If (Not(And(CDW1, 1))) { // Query flag clear?
+ // Disable GPEs for features granted native control.
+ If (And(CTRL, 0x01)) { // Hot plug control granted?
+ Store(0, HPCE) // clear the hot plug SCI enable bit
+ Store(1, HPCS) // clear the hot plug SCI status bit
+ }
+ If (And(CTRL, 0x04)) { // PME control granted?
+ Store(0, PMCE) // clear the PME SCI enable bit
+ Store(1, PMCS) // clear the PME SCI status bit
+ }
+ If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
+ // Set status to not restore PCI Express cap structure
+ // upon resume from S3
+ Store(1, S3CR)
+ }
+ }
+#endif
+ If (LNotEqual(Arg1, One)) {
+ // Unknown revision
+ Or(CDW1, 0x08, CDW1)
+ }
+ If (LNotEqual(CDW3, CTRL)) {
+ // Capabilities bits were masked
+ Or(CDW1, 0x10, CDW1)
+ }
+ // Update DWORD3 in the buffer
+ Store(CTRL, CDW3)
+ } Else {
+ Or(CDW1, 4, CDW1) // Unrecognized UUID
+ }
+ Return (Arg3)
+ }
+ }
+ }
+
+#include "acpi-dsdt-pci-crs.dsl"
+#include "acpi-dsdt-hpet.dsl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ Device(VGA) {
+ Name(_ADR, 0x00010000)
+ Method(_S1D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S2D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ Method(_S3D, 0, NotSerialized) {
+ Return (0x00)
+ }
+ }
+ }
+
+
+/****************************************************************
+ * LPC ISA bridge
+ ****************************************************************/
+
+ Scope(\_SB.PCI0) {
+ /* PCI D31:f0 LPC ISA bridge */
+ Device(ISA) {
+ /* PCI D31:f0 */
+ Name(_ADR, 0x001f0000)
+
+ /* ICH9 PCI to ISA irq remapping */
+ OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
+
+ OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
+ Field(LPCD, AnyAcc, NoLock, Preserve) {
+ COMA, 3,
+ , 1,
+ COMB, 3,
+
+ Offset(0x01),
+ LPTD, 2,
+ , 2,
+ FDCD, 2
+ }
+ OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
+ Field(LPCE, AnyAcc, NoLock, Preserve) {
+ CAEN, 1,
+ CBEN, 1,
+ LPEN, 1,
+ FDEN, 1
+ }
+ }
+ }
+
+#include "acpi-dsdt-isa.dsl"
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+ /* Zero => PIC mode, One => APIC Mode */
+ Name(\PICF, Zero)
+ Method(\_PIC, 1, NotSerialized) {
+ Store(Arg0, \PICF)
+ }
+
+ Scope(\_SB) {
+ Scope(PCI0) {
+#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \
+ Package() { nr##ffff, 0, lnk0, 0 }, \
+ Package() { nr##ffff, 1, lnk1, 0 }, \
+ Package() { nr##ffff, 2, lnk2, 0 }, \
+ Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
+#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
+
+#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
+#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
+#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
+#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
+
+ Name(PRTP, package() {
+ prt_slot_lnkE(0x0000),
+ prt_slot_lnkF(0x0001),
+ prt_slot_lnkG(0x0002),
+ prt_slot_lnkH(0x0003),
+ prt_slot_lnkE(0x0004),
+ prt_slot_lnkF(0x0005),
+ prt_slot_lnkG(0x0006),
+ prt_slot_lnkH(0x0007),
+ prt_slot_lnkE(0x0008),
+ prt_slot_lnkF(0x0009),
+ prt_slot_lnkG(0x000a),
+ prt_slot_lnkH(0x000b),
+ prt_slot_lnkE(0x000c),
+ prt_slot_lnkF(0x000d),
+ prt_slot_lnkG(0x000e),
+ prt_slot_lnkH(0x000f),
+ prt_slot_lnkE(0x0010),
+ prt_slot_lnkF(0x0011),
+ prt_slot_lnkG(0x0012),
+ prt_slot_lnkH(0x0013),
+ prt_slot_lnkE(0x0014),
+ prt_slot_lnkF(0x0015),
+ prt_slot_lnkG(0x0016),
+ prt_slot_lnkH(0x0017),
+ prt_slot_lnkE(0x0018),
+
+ /* INTA -> PIRQA for slot 25 - 31
+ see the default value of D<N>IR */
+ prt_slot_lnkA(0x0019),
+ prt_slot_lnkA(0x001a),
+ prt_slot_lnkA(0x001b),
+ prt_slot_lnkA(0x001c),
+ prt_slot_lnkA(0x001d),
+
+ /* PCIe->PCI bridge. use PIRQ[E-H] */
+ prt_slot_lnkE(0x001e),
+
+ prt_slot_lnkA(0x001f)
+ })
+
+#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \
+ Package() { nr##ffff, 0, gsi0, 0 }, \
+ Package() { nr##ffff, 1, gsi1, 0 }, \
+ Package() { nr##ffff, 2, gsi2, 0 }, \
+ Package() { nr##ffff, 3, gsi3, 0 }
+
+#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
+#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
+#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
+#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
+
+#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
+#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
+#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
+#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
+
+ Name(PRTA, package() {
+ prt_slot_gsiE(0x0000),
+ prt_slot_gsiF(0x0001),
+ prt_slot_gsiG(0x0002),
+ prt_slot_gsiH(0x0003),
+ prt_slot_gsiE(0x0004),
+ prt_slot_gsiF(0x0005),
+ prt_slot_gsiG(0x0006),
+ prt_slot_gsiH(0x0007),
+ prt_slot_gsiE(0x0008),
+ prt_slot_gsiF(0x0009),
+ prt_slot_gsiG(0x000a),
+ prt_slot_gsiH(0x000b),
+ prt_slot_gsiE(0x000c),
+ prt_slot_gsiF(0x000d),
+ prt_slot_gsiG(0x000e),
+ prt_slot_gsiH(0x000f),
+ prt_slot_gsiE(0x0010),
+ prt_slot_gsiF(0x0011),
+ prt_slot_gsiG(0x0012),
+ prt_slot_gsiH(0x0013),
+ prt_slot_gsiE(0x0014),
+ prt_slot_gsiF(0x0015),
+ prt_slot_gsiG(0x0016),
+ prt_slot_gsiH(0x0017),
+ prt_slot_gsiE(0x0018),
+
+ /* INTA -> PIRQA for slot 25 - 31, but 30
+ see the default value of D<N>IR */
+ prt_slot_gsiA(0x0019),
+ prt_slot_gsiA(0x001a),
+ prt_slot_gsiA(0x001b),
+ prt_slot_gsiA(0x001c),
+ prt_slot_gsiA(0x001d),
+
+ /* PCIe->PCI bridge. use PIRQ[E-H] */
+ prt_slot_gsiE(0x001e),
+
+ prt_slot_gsiA(0x001f)
+ })
+
+ Method(_PRT, 0, NotSerialized) {
+ /* PCI IRQ routing table, example from ACPI 2.0a specification,
+ section 6.2.8.1 */
+ /* Note: we provide the same info as the PCI routing
+ table of the Bochs BIOS */
+ If (LEqual(\PICF, Zero)) {
+ Return (PRTP)
+ } Else {
+ Return (PRTA)
+ }
+ }
+ }
+
+ Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
+ PRQA, 8,
+ PRQB, 8,
+ PRQC, 8,
+ PRQD, 8,
+
+ Offset(0x08),
+ PRQE, 8,
+ PRQF, 8,
+ PRQG, 8,
+ PRQH, 8
+ }
+
+ Method(IQST, 1, NotSerialized) {
+ // _STA method - get status
+ If (And(0x80, Arg0)) {
+ Return (0x09)
+ }
+ Return (0x0B)
+ }
+ Method(IQCR, 1, NotSerialized) {
+ // _CRS method - get current settings
+ Name(PRR0, ResourceTemplate() {
+ Interrupt(, Level, ActiveHigh, Shared) { 0 }
+ })
+ CreateDWordField(PRR0, 0x05, PRRI)
+ Store(And(Arg0, 0x0F), PRRI)
+ Return (PRR0)
+ }
+
+#define define_link(link, uid, reg) \
+ Device(link) { \
+ Name(_HID, EISAID("PNP0C0F")) \
+ Name(_UID, uid) \
+ Name(_PRS, ResourceTemplate() { \
+ Interrupt(, Level, ActiveHigh, Shared) { \
+ 5, 10, 11 \
+ } \
+ }) \
+ Method(_STA, 0, NotSerialized) { \
+ Return (IQST(reg)) \
+ } \
+ Method(_DIS, 0, NotSerialized) { \
+ Or(reg, 0x80, reg) \
+ } \
+ Method(_CRS, 0, NotSerialized) { \
+ Return (IQCR(reg)) \
+ } \
+ Method(_SRS, 1, NotSerialized) { \
+ CreateDWordField(Arg0, 0x05, PRRI) \
+ Store(PRRI, reg) \
+ } \
+ }
+
+ define_link(LNKA, 0, PRQA)
+ define_link(LNKB, 1, PRQB)
+ define_link(LNKC, 2, PRQC)
+ define_link(LNKD, 3, PRQD)
+ define_link(LNKE, 4, PRQE)
+ define_link(LNKF, 5, PRQF)
+ define_link(LNKG, 6, PRQG)
+ define_link(LNKH, 7, PRQH)
+
+#define define_gsi_link(link, uid, gsi) \
+ Device(link) { \
+ Name(_HID, EISAID("PNP0C0F")) \
+ Name(_UID, uid) \
+ Name(_PRS, ResourceTemplate() { \
+ Interrupt(, Level, ActiveHigh, Shared) { \
+ gsi \
+ } \
+ }) \
+ Name(_CRS, ResourceTemplate() { \
+ Interrupt(, Level, ActiveHigh, Shared) { \
+ gsi \
+ } \
+ }) \
+ Method(_SRS, 1, NotSerialized) { \
+ } \
+ }
+
+ define_gsi_link(GSIA, 0, 0x10)
+ define_gsi_link(GSIB, 0, 0x11)
+ define_gsi_link(GSIC, 0, 0x12)
+ define_gsi_link(GSID, 0, 0x13)
+ define_gsi_link(GSIE, 0, 0x14)
+ define_gsi_link(GSIF, 0, 0x15)
+ define_gsi_link(GSIG, 0, 0x16)
+ define_gsi_link(GSIH, 0, 0x17)
+ }
+
+#include "acpi-dsdt-cpu-hotplug.dsl"
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+ Scope(\_GPE) {
+ Name(_HID, "ACPI0006")
+
+ Method(_L00) {
+ }
+ Method(_L01) {
+ // CPU hotplug event
+ \_SB.PRSC()
+ }
+ Method(_L02) {
+ }
+ Method(_L03) {
+ }
+ Method(_L04) {
+ }
+ Method(_L05) {
+ }
+ Method(_L06) {
+ }
+ Method(_L07) {
+ }
+ Method(_L08) {
+ }
+ Method(_L09) {
+ }
+ Method(_L0A) {
+ }
+ Method(_L0B) {
+ }
+ Method(_L0C) {
+ }
+ Method(_L0D) {
+ }
+ Method(_L0E) {
+ }
+ Method(_L0F) {
+ }
+ }
+}
--- /dev/null
+// Support for enabling/disabling BIOS ram shadowing.
+//
+// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // memcpy
+#include "hw/pci.h" // pci_config_writeb
+#include "config.h" // CONFIG_*
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_VENDOR_ID
+#include "paravirt.h" // runningOnXen
+#include "dev-q35.h" // PCI_VENDOR_ID_INTEL
+
+// On the emulators, the bios at 0xf0000 is also at 0xffff0000
+#define BIOS_SRC_OFFSET 0xfff00000
+
+#define I440FX_PAM0 0x59
+
+// Enable shadowing and copy bios.
+static void
+__make_bios_writable_intel(u16 bdf, u32 pam0)
+{
+ // Make ram from 0xc0000-0xf0000 writable
+ int clear = 0;
+ int i;
+ for (i=0; i<6; i++) {
+ u32 pam = pam0 + 1 + i;
+ int reg = pci_config_readb(bdf, pam);
+ if (CONFIG_OPTIONROMS_DEPLOYED && (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, pam, 0x33);
+ memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
+ clear = 1;
+ } else {
+ pci_config_writeb(bdf, pam, 0x33);
+ }
+ }
+ if (clear)
+ memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
+
+ // Make ram from 0xf0000-0x100000 writable
+ int reg = pci_config_readb(bdf, pam0);
+ pci_config_writeb(bdf, pam0, 0x30);
+ if (reg & 0x10)
+ // Ram already present.
+ return;
+
+ // Copy bios.
+ extern u8 code32flat_start[], code32flat_end[];
+ memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
+ , code32flat_end - code32flat_start);
+}
+
+static void
+make_bios_writable_intel(u16 bdf, u32 pam0)
+{
+ int reg = pci_config_readb(bdf, pam0);
+ if (!(reg & 0x10)) {
+ // QEMU doesn't fully implement the piix shadow capabilities -
+ // if ram isn't backing the bios segment when shadowing is
+ // disabled, the code itself wont be in memory. So, run the
+ // code from the high-memory flash location.
+ u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
+ void (*func)(u16 bdf, u32 pam0) = (void*)pos;
+ func(bdf, pam0);
+ return;
+ }
+ // Ram already present - just enable writes
+ __make_bios_writable_intel(bdf, pam0);
+}
+
+static void
+make_bios_readonly_intel(u16 bdf, u32 pam0)
+{
+ // Flush any pending writes before locking memory.
+ wbinvd();
+
+ // Write protect roms from 0xc0000-0xf0000
+ u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
+ if (CONFIG_WRITABLE_UPPERMEMORY)
+ romlast = rom_get_last();
+ if (CONFIG_MALLOC_UPPERMEMORY)
+ rommax = rom_get_max();
+ int i;
+ for (i=0; i<6; i++) {
+ u32 mem = BUILD_ROM_START + i * 32*1024;
+ u32 pam = pam0 + 1 + i;
+ if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
+ if (romlast >= mem && rommax >= mem + 16*1024)
+ pci_config_writeb(bdf, pam, 0x31);
+ break;
+ }
+ pci_config_writeb(bdf, pam, 0x11);
+ }
+
+ // Write protect 0xf0000-0x100000
+ pci_config_writeb(bdf, pam0, 0x10);
+}
+
+static int ShadowBDF = -1;
+
+// Make the 0xc0000-0x100000 area read/writable.
+void
+make_bios_writable(void)
+{
+ if (!CONFIG_QEMU || runningOnXen())
+ return;
+
+ dprintf(3, "enabling shadow ram\n");
+
+ // At this point, statically allocated variables can't be written,
+ // so do this search manually.
+ int bdf;
+ foreachbdf(bdf, 0) {
+ u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
+ u16 vendor = vendev & 0xffff, device = vendev >> 16;
+ if (vendor == PCI_VENDOR_ID_INTEL
+ && device == PCI_DEVICE_ID_INTEL_82441) {
+ make_bios_writable_intel(bdf, I440FX_PAM0);
+ ShadowBDF = bdf;
+ return;
+ }
+ if (vendor == PCI_VENDOR_ID_INTEL
+ && device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
+ make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0);
+ ShadowBDF = bdf;
+ return;
+ }
+ }
+ dprintf(1, "Unable to unlock ram - bridge not found\n");
+}
+
+// Make the BIOS code segment area (0xf0000) read-only.
+void
+make_bios_readonly(void)
+{
+ if (!CONFIG_QEMU || runningOnXen())
+ return;
+ dprintf(3, "locking shadow ram\n");
+
+ if (ShadowBDF < 0) {
+ dprintf(1, "Unable to lock ram - bridge not found\n");
+ return;
+ }
+
+ u16 device = pci_config_readw(ShadowBDF, PCI_DEVICE_ID);
+ if (device == PCI_DEVICE_ID_INTEL_82441)
+ make_bios_readonly_intel(ShadowBDF, I440FX_PAM0);
+ else
+ make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0);
+}
+
+void
+qemu_prep_reset(void)
+{
+ if (!CONFIG_QEMU || runningOnXen())
+ return;
+ // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
+ // reset, so do that manually before invoking a hard reset.
+ make_bios_writable();
+ extern u8 code32flat_start[], code32flat_end[];
+ memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
+ , code32flat_end - code32flat_start);
+}
--- /dev/null
+// smbios table generation (on emulators)
+//
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "paravirt.h" // RamSize
+#include "smbios.h" // struct smbios_entry_point
+
+struct smbios_entry_point *SMBiosAddr;
+
+static void
+smbios_entry_point_setup(u16 max_structure_size,
+ u16 structure_table_length,
+ void *structure_table_address,
+ u16 number_of_structures)
+{
+ struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep));
+ void *finaltable;
+ if (structure_table_length <= BUILD_MAX_SMBIOS_FSEG)
+ // Table is small enough for f-seg - allocate there. This
+ // works around a bug in JunOS (at least for small SMBIOS tables).
+ finaltable = malloc_fseg(structure_table_length);
+ else
+ finaltable = malloc_high(structure_table_length);
+ if (!ep || !finaltable) {
+ warn_noalloc();
+ free(ep);
+ free(finaltable);
+ return;
+ }
+ memcpy(finaltable, structure_table_address, structure_table_length);
+
+ memcpy(ep->anchor_string, "_SM_", 4);
+ ep->length = 0x1f;
+ ep->smbios_major_version = 2;
+ ep->smbios_minor_version = 4;
+ ep->max_structure_size = max_structure_size;
+ ep->entry_point_revision = 0;
+ memset(ep->formatted_area, 0, 5);
+ memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
+
+ ep->structure_table_length = structure_table_length;
+ ep->structure_table_address = (u32)finaltable;
+ ep->number_of_structures = number_of_structures;
+ ep->smbios_bcd_revision = 0x24;
+
+ ep->checksum -= checksum(ep, 0x10);
+
+ ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10);
+
+ SMBiosAddr = ep;
+ dprintf(1, "SMBIOS ptr=%p table=%p size=%d\n"
+ , ep, finaltable, structure_table_length);
+}
+
+static int
+get_field(int type, int offset, void *dest)
+{
+ char name[128];
+ snprintf(name, sizeof(name), "smbios/field%d-%d", type, offset);
+ struct romfile_s *file = romfile_find(name);
+ if (!file)
+ return 0;
+ file->copy(file, dest, file->size);
+ return file->size;
+}
+
+static int
+get_external(int type, char **p, unsigned *nr_structs,
+ unsigned *max_struct_size, char *end)
+{
+ static u64 used_bitmap[4] = { 0 };
+ char *start = *p;
+
+ /* Check if we've already reported these tables */
+ if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
+ return 1;
+
+ /* Don't introduce spurious end markers */
+ if (type == 127)
+ return 0;
+
+ char prefix[128];
+ snprintf(prefix, sizeof(prefix), "smbios/table%d-", type);
+ struct romfile_s *file = NULL;
+ for (;;) {
+ file = romfile_findprefix(prefix, file);
+ if (!file)
+ break;
+
+ if (end - *p < file->size) {
+ warn_noalloc();
+ break;
+ }
+
+ struct smbios_structure_header *header = (void*)*p;
+ file->copy(file, header, file->size);
+ *p += file->size;
+
+ /* Entries end with a double NULL char, if there's a string at
+ * the end (length is greater than formatted length), the string
+ * terminator provides the first NULL. */
+ *((u8*)*p) = 0;
+ (*p)++;
+ if (header->length >= file->size) {
+ *((u8*)*p) = 0;
+ (*p)++;
+ }
+
+ (*nr_structs)++;
+ if (*p - (char*)header > *max_struct_size)
+ *max_struct_size = *p - (char*)header;
+ }
+
+ if (start == *p)
+ return 0;
+
+ /* Mark that we've reported on this type */
+ used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
+ return 1;
+}
+
+#define load_str_field_with_default(type, field, def) \
+ do { \
+ size = get_field(type, offsetof(struct smbios_type_##type, \
+ field), end); \
+ if (size > 0) { \
+ end += size; \
+ } else { \
+ memcpy(end, def, sizeof(def)); \
+ end += sizeof(def); \
+ } \
+ p->field = ++str_index; \
+ } while (0)
+
+#define load_str_field_or_skip(type, field) \
+ do { \
+ size = get_field(type, offsetof(struct smbios_type_##type, \
+ field), end); \
+ if (size > 0) { \
+ end += size; \
+ p->field = ++str_index; \
+ } else { \
+ p->field = 0; \
+ } \
+ } while (0)
+
+#define set_field_with_default(type, field, def) \
+ do { \
+ if (!get_field(type, offsetof(struct smbios_type_##type, \
+ field), &p->field)) { \
+ p->field = def; \
+ } \
+ } while (0)
+
+/* Type 0 -- BIOS Information */
+#define RELEASE_DATE_STR "01/01/2011"
+static void *
+smbios_init_type_0(void *start)
+{
+ struct smbios_type_0 *p = (struct smbios_type_0 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_0);
+ size_t size;
+ int str_index = 0;
+
+ p->header.type = 0;
+ p->header.length = sizeof(struct smbios_type_0);
+ p->header.handle = 0;
+
+ load_str_field_with_default(0, vendor_str, BUILD_APPNAME);
+ load_str_field_with_default(0, bios_version_str, BUILD_APPNAME);
+
+ p->bios_starting_address_segment = 0xe800;
+
+ load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
+
+ p->bios_rom_size = 0; /* FIXME */
+
+ if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics),
+ &p->bios_characteristics)) {
+ memset(p->bios_characteristics, 0, 8);
+ /* BIOS characteristics not supported */
+ p->bios_characteristics[0] = 0x08;
+ }
+
+ if (!get_field(0, offsetof(struct smbios_type_0,
+ bios_characteristics_extension_bytes),
+ &p->bios_characteristics_extension_bytes)) {
+ p->bios_characteristics_extension_bytes[0] = 0;
+ /* Enable targeted content distribution. Needed for SVVP */
+ p->bios_characteristics_extension_bytes[1] = 4;
+ }
+
+ set_field_with_default(0, system_bios_major_release, 1);
+ set_field_with_default(0, system_bios_minor_release, 0);
+ set_field_with_default(0, embedded_controller_major_release, 0xff);
+ set_field_with_default(0, embedded_controller_minor_release, 0xff);
+
+ *end = 0;
+ end++;
+
+ return end;
+}
+
+/* Type 1 -- System Information */
+static void *
+smbios_init_type_1(void *start)
+{
+ struct smbios_type_1 *p = (struct smbios_type_1 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_1);
+ size_t size;
+ int str_index = 0;
+
+ p->header.type = 1;
+ p->header.length = sizeof(struct smbios_type_1);
+ p->header.handle = 0x100;
+
+ load_str_field_with_default(1, manufacturer_str, BUILD_APPNAME);
+ load_str_field_with_default(1, product_name_str, BUILD_APPNAME);
+ load_str_field_or_skip(1, version_str);
+ load_str_field_or_skip(1, serial_number_str);
+
+ if (!get_field(1, offsetof(struct smbios_type_1, uuid), &p->uuid))
+ memset(p->uuid, 0, 16);
+
+ set_field_with_default(1, wake_up_type, 0x06); /* power switch */
+
+ load_str_field_or_skip(1, sku_number_str);
+ load_str_field_or_skip(1, family_str);
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
+}
+
+/* Type 3 -- System Enclosure */
+static void *
+smbios_init_type_3(void *start)
+{
+ struct smbios_type_3 *p = (struct smbios_type_3 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_3);
+ size_t size;
+ int str_index = 0;
+
+ p->header.type = 3;
+ p->header.length = sizeof(struct smbios_type_3);
+ p->header.handle = 0x300;
+
+ load_str_field_with_default(3, manufacturer_str, BUILD_APPNAME);
+ set_field_with_default(3, type, 0x01); /* other */
+
+ load_str_field_or_skip(3, version_str);
+ load_str_field_or_skip(3, serial_number_str);
+ load_str_field_or_skip(3, asset_tag_number_str);
+
+ set_field_with_default(3, boot_up_state, 0x03); /* safe */
+ set_field_with_default(3, power_supply_state, 0x03); /* safe */
+ set_field_with_default(3, thermal_state, 0x03); /* safe */
+ set_field_with_default(3, security_status, 0x02); /* unknown */
+
+ set_field_with_default(3, oem_defined, 0);
+ set_field_with_default(3, height, 0);
+ set_field_with_default(3, number_of_power_cords, 0);
+ set_field_with_default(3, contained_element_count, 0);
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
+}
+
+/* Type 4 -- Processor Information */
+static void *
+smbios_init_type_4(void *start, unsigned int cpu_number)
+{
+ struct smbios_type_4 *p = (struct smbios_type_4 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_4);
+ size_t size;
+ int str_index = 0;
+ char name[1024];
+
+ p->header.type = 4;
+ p->header.length = sizeof(struct smbios_type_4);
+ p->header.handle = 0x400 + cpu_number;
+
+ size = get_field(4, offsetof(struct smbios_type_4, socket_designation_str),
+ name);
+ if (size)
+ snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number);
+ else
+ snprintf(name, sizeof(name), "CPU%2x", cpu_number);
+
+ memcpy(end, name, strlen(name) + 1);
+ end += strlen(name) + 1;
+ p->socket_designation_str = ++str_index;
+
+ set_field_with_default(4, processor_type, 0x03); /* CPU */
+ set_field_with_default(4, processor_family, 0x01); /* other */
+
+ load_str_field_with_default(4, processor_manufacturer_str, BUILD_APPNAME);
+
+ if (!get_field(4, offsetof(struct smbios_type_4, processor_id)
+ , p->processor_id)) {
+ u32 cpuid_signature, ebx, ecx, cpuid_features;
+ cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
+ p->processor_id[0] = cpuid_signature;
+ p->processor_id[1] = cpuid_features;
+ }
+
+ load_str_field_or_skip(4, processor_version_str);
+ set_field_with_default(4, voltage, 0);
+ set_field_with_default(4, external_clock, 0);
+
+ set_field_with_default(4, max_speed, 2000);
+ set_field_with_default(4, current_speed, 2000);
+
+ set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */
+ set_field_with_default(4, processor_upgrade, 0x01); /* other */
+
+ /* cache information structure not provided */
+ p->l1_cache_handle = 0xffff;
+ p->l2_cache_handle = 0xffff;
+ p->l3_cache_handle = 0xffff;
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
+}
+
+/* Type 16 -- Physical Memory Array */
+static void *
+smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
+{
+ struct smbios_type_16 *p = (struct smbios_type_16*)start;
+
+ p->header.type = 16;
+ p->header.length = sizeof(struct smbios_type_16);
+ p->header.handle = 0x1000;
+
+ set_field_with_default(16, location, 0x01); /* other */
+ set_field_with_default(16, use, 0x03); /* system memory */
+ /* Multi-bit ECC to make Microsoft happy */
+ set_field_with_default(16, error_correction, 0x06);
+ /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */
+ p->maximum_capacity = memory_size_mb < 2 << 20 ?
+ memory_size_mb << 10 : 0x80000000;
+ p->memory_error_information_handle = 0xfffe; /* none provided */
+ p->number_of_memory_devices = nr_mem_devs;
+
+ start += sizeof(struct smbios_type_16);
+ *((u16 *)start) = 0;
+
+ return start + 2;
+}
+
+/* Type 17 -- Memory Device */
+static void *
+smbios_init_type_17(void *start, u32 size_mb, int instance)
+{
+ struct smbios_type_17 *p = (struct smbios_type_17 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_17);
+ size_t size;
+ int str_index = 0;
+ char name[1024];
+
+ p->header.type = 17;
+ p->header.length = sizeof(struct smbios_type_17);
+ p->header.handle = 0x1100 + instance;
+
+ p->physical_memory_array_handle = 0x1000;
+ set_field_with_default(17, total_width, 64);
+ set_field_with_default(17, data_width, 64);
+/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
+ p->size = size_mb;
+ set_field_with_default(17, form_factor, 0x09); /* DIMM */
+ p->device_set = 0;
+
+ size = get_field(17, offsetof(struct smbios_type_17, device_locator_str),
+ name);
+ if (size)
+ snprintf(name + size - 1, sizeof(name) - size, "%d", instance);
+ else
+ snprintf(name, sizeof(name), "DIMM %d", instance);
+
+ memcpy(end, name, strlen(name) + 1);
+ end += strlen(name) + 1;
+ p->device_locator_str = ++str_index;
+
+ load_str_field_or_skip(17, bank_locator_str);
+ set_field_with_default(17, memory_type, 0x07); /* RAM */
+ set_field_with_default(17, type_detail, 0);
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
+}
+
+/* Type 19 -- Memory Array Mapped Address */
+static void *
+smbios_init_type_19(void *start, u32 start_mb, u32 size_mb, int instance)
+{
+ struct smbios_type_19 *p = (struct smbios_type_19 *)start;
+
+ p->header.type = 19;
+ p->header.length = sizeof(struct smbios_type_19);
+ p->header.handle = 0x1300 + instance;
+
+ p->starting_address = start_mb << 10;
+ p->ending_address = p->starting_address + (size_mb << 10) - 1;
+ p->memory_array_handle = 0x1000;
+ p->partition_width = 1;
+
+ start += sizeof(struct smbios_type_19);
+ *((u16 *)start) = 0;
+
+ return start + 2;
+}
+
+/* Type 20 -- Memory Device Mapped Address */
+static void *
+smbios_init_type_20(void *start, u32 start_mb, u32 size_mb, int instance,
+ int dev_handle, int array_handle)
+{
+ struct smbios_type_20 *p = (struct smbios_type_20 *)start;
+
+ p->header.type = 20;
+ p->header.length = sizeof(struct smbios_type_20);
+ p->header.handle = 0x1400 + instance;
+
+ p->starting_address = start_mb << 10;
+ p->ending_address = p->starting_address + (size_mb << 10) - 1;
+ p->memory_device_handle = 0x1100 + dev_handle;
+ p->memory_array_mapped_address_handle = 0x1300 + array_handle;
+ p->partition_row_position = 1;
+ p->interleave_position = 0;
+ p->interleaved_data_depth = 0;
+
+ start += sizeof(struct smbios_type_20);
+
+ *((u16 *)start) = 0;
+ return start+2;
+}
+
+/* Type 32 -- System Boot Information */
+static void *
+smbios_init_type_32(void *start)
+{
+ struct smbios_type_32 *p = (struct smbios_type_32 *)start;
+
+ p->header.type = 32;
+ p->header.length = sizeof(struct smbios_type_32);
+ p->header.handle = 0x2000;
+ memset(p->reserved, 0, 6);
+ set_field_with_default(32, boot_status, 0); /* no errors detected */
+
+ start += sizeof(struct smbios_type_32);
+ *((u16 *)start) = 0;
+
+ return start+2;
+}
+
+/* Type 127 -- End of Table */
+static void *
+smbios_init_type_127(void *start)
+{
+ struct smbios_type_127 *p = (struct smbios_type_127 *)start;
+
+ p->header.type = 127;
+ p->header.length = sizeof(struct smbios_type_127);
+ p->header.handle = 0x7f00;
+
+ start += sizeof(struct smbios_type_127);
+ *((u16 *)start) = 0;
+
+ return start + 2;
+}
+
+#define TEMPSMBIOSSIZE (32 * 1024)
+
+void
+smbios_setup(void)
+{
+ if (! CONFIG_SMBIOS)
+ return;
+
+ dprintf(3, "init SMBIOS tables\n");
+
+ char *start = malloc_tmphigh(TEMPSMBIOSSIZE);
+ if (! start) {
+ warn_noalloc();
+ return;
+ }
+
+ u32 nr_structs = 0, max_struct_size = 0;
+ char *q, *p = start;
+ char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127);
+
+#define add_struct(type, args...) \
+ do { \
+ if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \
+ q = smbios_init_type_##type(args); \
+ nr_structs++; \
+ if ((q - p) > max_struct_size) \
+ max_struct_size = q - p; \
+ p = q; \
+ } \
+ } while (0)
+
+ add_struct(0, p);
+ add_struct(1, p);
+ add_struct(3, p);
+
+ int cpu_num;
+ for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
+ add_struct(4, p, cpu_num);
+
+ int ram_mb = (RamSize + RamSizeOver4G) >> 20;
+ int nr_mem_devs = (ram_mb + 0x3fff) >> 14;
+ add_struct(16, p, ram_mb, nr_mem_devs);
+
+ int i, j;
+ for (i = 0; i < nr_mem_devs; i++) {
+ u32 dev_mb = ((i == (nr_mem_devs - 1))
+ ? (((ram_mb - 1) & 0x3fff) + 1)
+ : 16384);
+ add_struct(17, p, dev_mb, i);
+ }
+
+ add_struct(19, p, 0, RamSize >> 20, 0);
+ if (RamSizeOver4G)
+ add_struct(19, p, 4096, RamSizeOver4G >> 20, 1);
+
+ add_struct(20, p, 0, RamSize >> 20, 0, 0, 0);
+ if (RamSizeOver4G) {
+ u32 start_mb = 4096;
+ for (j = 1, i = 0; i < nr_mem_devs; i++, j++) {
+ u32 dev_mb = ((i == (nr_mem_devs - 1))
+ ? (((ram_mb - 1) & 0x3fff) + 1)
+ : 16384);
+ if (i == 0)
+ dev_mb -= RamSize >> 20;
+
+ add_struct(20, p, start_mb, dev_mb, j, i, 1);
+ start_mb += dev_mb;
+ }
+ }
+
+ add_struct(32, p);
+ /* Add any remaining provided entries before the end marker */
+ for (i = 0; i < 256; i++)
+ get_external(i, &p, &nr_structs, &max_struct_size, end);
+ add_struct(127, p);
+
+#undef add_struct
+
+ smbios_entry_point_setup(max_struct_size, p - start, start, nr_structs);
+ free(start);
+}
+
+void
+display_uuid(void)
+{
+ u32 addr, end;
+ u8 *uuid;
+ u8 empty_uuid[16] = { 0 };
+
+ if (SMBiosAddr == NULL)
+ return;
+
+ addr = SMBiosAddr->structure_table_address;
+ end = addr + SMBiosAddr->structure_table_length;
+
+ /* the following takes care of any initial wraparound too */
+ while (addr < end) {
+ const struct smbios_structure_header *hdr;
+
+ /* partial structure header */
+ if (end - addr < sizeof(struct smbios_structure_header))
+ return;
+
+ hdr = (struct smbios_structure_header *)addr;
+
+ /* partial structure */
+ if (end - addr < hdr->length)
+ return;
+
+ /* any Type 1 structure version will do that has the UUID */
+ if (hdr->type == 1 &&
+ hdr->length >= offsetof(struct smbios_type_1, uuid) + 16)
+ break;
+
+ /* done with formatted area, skip string-set */
+ addr += hdr->length;
+
+ while (end - addr >= 2 &&
+ (*(u8 *)addr != '\0' ||
+ *(u8 *)(addr+1) != '\0'))
+ ++addr;
+
+ /* structure terminator not found */
+ if (end - addr < 2)
+ return;
+
+ addr += 2;
+ }
+
+ /* parsing finished or skipped entirely, UUID not found */
+ if (addr >= end)
+ return;
+
+ uuid = (u8 *)(addr + offsetof(struct smbios_type_1, uuid));
+ if (memcmp(uuid, empty_uuid, sizeof empty_uuid) == 0)
+ return;
+
+ printf("Machine UUID"
+ " %02x%02x%02x%02x"
+ "-%02x%02x"
+ "-%02x%02x"
+ "-%02x%02x"
+ "-%02x%02x%02x%02x%02x%02x\n"
+ , uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3]
+ , uuid[ 4], uuid[ 5]
+ , uuid[ 6], uuid[ 7]
+ , uuid[ 8], uuid[ 9]
+ , uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
+}
--- /dev/null
+#ifndef __SMBIOS_H
+#define __SMBIOS_H
+
+// smbios.c
+void smbios_setup(void);
+
+/* SMBIOS entry point -- must be written to a 16-bit aligned address
+ between 0xf0000 and 0xfffff.
+ */
+struct smbios_entry_point {
+ char anchor_string[4];
+ u8 checksum;
+ u8 length;
+ u8 smbios_major_version;
+ u8 smbios_minor_version;
+ u16 max_structure_size;
+ u8 entry_point_revision;
+ u8 formatted_area[5];
+ char intermediate_anchor_string[5];
+ u8 intermediate_checksum;
+ u16 structure_table_length;
+ u32 structure_table_address;
+ u16 number_of_structures;
+ u8 smbios_bcd_revision;
+} PACKED;
+
+extern struct smbios_entry_point *SMBiosAddr;
+
+/* This goes at the beginning of every SMBIOS structure. */
+struct smbios_structure_header {
+ u8 type;
+ u8 length;
+ u16 handle;
+} PACKED;
+
+/* SMBIOS type 0 - BIOS Information */
+struct smbios_type_0 {
+ struct smbios_structure_header header;
+ u8 vendor_str;
+ u8 bios_version_str;
+ u16 bios_starting_address_segment;
+ u8 bios_release_date_str;
+ u8 bios_rom_size;
+ u8 bios_characteristics[8];
+ u8 bios_characteristics_extension_bytes[2];
+ u8 system_bios_major_release;
+ u8 system_bios_minor_release;
+ u8 embedded_controller_major_release;
+ u8 embedded_controller_minor_release;
+} PACKED;
+
+/* SMBIOS type 1 - System Information */
+struct smbios_type_1 {
+ struct smbios_structure_header header;
+ u8 manufacturer_str;
+ u8 product_name_str;
+ u8 version_str;
+ u8 serial_number_str;
+ u8 uuid[16];
+ u8 wake_up_type;
+ u8 sku_number_str;
+ u8 family_str;
+} PACKED;
+
+/* SMBIOS type 3 - System Enclosure (v2.3) */
+struct smbios_type_3 {
+ struct smbios_structure_header header;
+ u8 manufacturer_str;
+ u8 type;
+ u8 version_str;
+ u8 serial_number_str;
+ u8 asset_tag_number_str;
+ u8 boot_up_state;
+ u8 power_supply_state;
+ u8 thermal_state;
+ u8 security_status;
+ u32 oem_defined;
+ u8 height;
+ u8 number_of_power_cords;
+ u8 contained_element_count;
+ // contained elements follow
+} PACKED;
+
+/* SMBIOS type 4 - Processor Information (v2.0) */
+struct smbios_type_4 {
+ struct smbios_structure_header header;
+ u8 socket_designation_str;
+ u8 processor_type;
+ u8 processor_family;
+ u8 processor_manufacturer_str;
+ u32 processor_id[2];
+ u8 processor_version_str;
+ u8 voltage;
+ u16 external_clock;
+ u16 max_speed;
+ u16 current_speed;
+ u8 status;
+ u8 processor_upgrade;
+ u16 l1_cache_handle;
+ u16 l2_cache_handle;
+ u16 l3_cache_handle;
+} PACKED;
+
+/* SMBIOS type 16 - Physical Memory Array
+ * Associated with one type 17 (Memory Device).
+ */
+struct smbios_type_16 {
+ struct smbios_structure_header header;
+ u8 location;
+ u8 use;
+ u8 error_correction;
+ u32 maximum_capacity;
+ u16 memory_error_information_handle;
+ u16 number_of_memory_devices;
+} PACKED;
+
+/* SMBIOS type 17 - Memory Device
+ * Associated with one type 19
+ */
+struct smbios_type_17 {
+ struct smbios_structure_header header;
+ u16 physical_memory_array_handle;
+ u16 memory_error_information_handle;
+ u16 total_width;
+ u16 data_width;
+ u16 size;
+ u8 form_factor;
+ u8 device_set;
+ u8 device_locator_str;
+ u8 bank_locator_str;
+ u8 memory_type;
+ u16 type_detail;
+} PACKED;
+
+/* SMBIOS type 19 - Memory Array Mapped Address */
+struct smbios_type_19 {
+ struct smbios_structure_header header;
+ u32 starting_address;
+ u32 ending_address;
+ u16 memory_array_handle;
+ u8 partition_width;
+} PACKED;
+
+/* SMBIOS type 20 - Memory Device Mapped Address */
+struct smbios_type_20 {
+ struct smbios_structure_header header;
+ u32 starting_address;
+ u32 ending_address;
+ u16 memory_device_handle;
+ u16 memory_array_mapped_address_handle;
+ u8 partition_row_position;
+ u8 interleave_position;
+ u8 interleaved_data_depth;
+} PACKED;
+
+/* SMBIOS type 32 - System Boot Information */
+struct smbios_type_32 {
+ struct smbios_structure_header header;
+ u8 reserved[6];
+ u8 boot_status;
+} PACKED;
+
+/* SMBIOS type 127 -- End-of-table */
+struct smbios_type_127 {
+ struct smbios_structure_header header;
+} PACKED;
+
+void display_uuid(void);
+#endif // smbios.h
--- /dev/null
+// System Management Mode support (on emulators)
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "hw/pci.h" // pci_config_writel
+#include "hw/pci_regs.h" // PCI_DEVICE_ID
+#include "util.h" // wbinvd
+#include "config.h" // CONFIG_*
+#include "ioport.h" // outb
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "dev-q35.h"
+
+extern u8 smm_relocation_start, smm_relocation_end;
+ASM32FLAT(
+ ".global smm_relocation_start, smm_relocation_end\n"
+ " .code16gcc\n"
+
+ /* code to relocate SMBASE to 0xa0000 */
+ "smm_relocation_start:\n"
+ " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n"
+ " addr32 movb (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */
+ " cmpb $0x64, %al\n"
+ " je 1f\n"
+ " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n"
+ " jmp 2f\n"
+ "1:\n"
+ " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n"
+ "2:\n"
+ " movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n"
+ " addr32 movl %eax, (%ebx)\n"
+ /* indicate to the BIOS that the SMM code was executed */
+ " movb $0x00, %al\n"
+ " movw $" __stringify(PORT_SMI_STATUS) ", %dx\n"
+ " outb %al, %dx\n"
+ " rsm\n"
+ "smm_relocation_end:\n"
+ " .code32\n"
+ );
+
+extern u8 smm_code_start, smm_code_end;
+ASM32FLAT(
+ /* minimal SMM code to enable or disable ACPI */
+ ".global smm_code_start, smm_code_end\n"
+ " .code16gcc\n"
+ "smm_code_start:\n"
+ " movw $" __stringify(PORT_SMI_CMD) ", %dx\n"
+ " inb %dx, %al\n"
+ " cmpb $0xf0, %al\n"
+ " jne 1f\n"
+
+ /* ACPI disable */
+ " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
+ " inw %dx, %ax\n"
+ " andw $~1, %ax\n"
+ " outw %ax, %dx\n"
+
+ " jmp 2f\n"
+
+ "1:\n"
+ " cmpb $0xf1, %al\n"
+ " jne 2f\n"
+
+ /* ACPI enable */
+ " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
+ " inw %dx, %ax\n"
+ " orw $1, %ax\n"
+ " outw %ax, %dx\n"
+
+ "2:\n"
+ " rsm\n"
+ "smm_code_end:\n"
+ " .code32\n"
+ );
+
+static void
+smm_save_and_copy(void)
+{
+ /* save original memory content */
+ memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
+
+ /* copy the SMM relocation code */
+ memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
+ &smm_relocation_end - &smm_relocation_start);
+}
+
+static void
+smm_relocate_and_restore(void)
+{
+ /* init APM status port */
+ outb(0x01, PORT_SMI_STATUS);
+
+ /* raise an SMI interrupt */
+ outb(0x00, PORT_SMI_CMD);
+
+ /* wait until SMM code executed */
+ while (inb(PORT_SMI_STATUS) != 0x00)
+ ;
+
+ /* restore original memory content */
+ memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);
+
+ /* copy the SMM code */
+ memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
+ , &smm_code_end - &smm_code_start);
+ wbinvd();
+}
+
+#define I440FX_SMRAM 0x72
+#define PIIX_DEVACTB 0x58
+#define PIIX_APMC_EN (1 << 25)
+
+// This code is hardcoded for PIIX4 Power Management device.
+static void piix4_apmc_smm_setup(int isabdf, int i440_bdf)
+{
+ /* check if SMM init is already done */
+ u32 value = pci_config_readl(isabdf, PIIX_DEVACTB);
+ if (value & PIIX_APMC_EN)
+ return;
+
+ /* enable the SMM memory window */
+ pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48);
+
+ smm_save_and_copy();
+
+ /* enable SMI generation when writing to the APMC register */
+ pci_config_writel(isabdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
+
+ smm_relocate_and_restore();
+
+ /* close the SMM memory window and enable normal SMM */
+ pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08);
+}
+
+/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
+void ich9_lpc_apmc_smm_setup(int isabdf, int mch_bdf)
+{
+ /* check if SMM init is already done */
+ u32 value = inl(PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN);
+ if (value & ICH9_PMIO_SMI_EN_APMC_EN)
+ return;
+
+ /* enable the SMM memory window */
+ pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x48);
+
+ smm_save_and_copy();
+
+ /* enable SMI generation when writing to the APMC register */
+ outl(value | ICH9_PMIO_SMI_EN_APMC_EN,
+ PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN);
+
+ smm_relocate_and_restore();
+
+ /* close the SMM memory window and enable normal SMM */
+ pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x08);
+}
+
+static int SMMISADeviceBDF = -1, SMMPMDeviceBDF = -1;
+
+void
+smm_device_setup(void)
+{
+ if (!CONFIG_USE_SMM)
+ return;
+
+ struct pci_device *isapci, *pmpci;
+ isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3);
+ pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
+ if (isapci && pmpci) {
+ SMMISADeviceBDF = isapci->bdf;
+ SMMPMDeviceBDF = pmpci->bdf;
+ return;
+ }
+ isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC);
+ pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH);
+ if (isapci && pmpci) {
+ SMMISADeviceBDF = isapci->bdf;
+ SMMPMDeviceBDF = pmpci->bdf;
+ }
+}
+
+void
+smm_setup(void)
+{
+ if (!CONFIG_USE_SMM || SMMISADeviceBDF < 0)
+ return;
+
+ dprintf(3, "init smm\n");
+ u16 device = pci_config_readw(SMMISADeviceBDF, PCI_DEVICE_ID);
+ if (device == PCI_DEVICE_ID_INTEL_82371AB_3)
+ piix4_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
+ else
+ ich9_lpc_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
+}
--- /dev/null
+// CPU count detection
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "hw/cmos.h" // CMOS_BIOS_SMP_COUNT
+
+#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
+#define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0)
+#define APIC_LINT0 ((u8*)BUILD_APIC_ADDR + 0x350)
+#define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360)
+
+#define APIC_ENABLED 0x0100
+
+struct { u32 ecx, eax, edx; } smp_mtrr[32] VARFSEG;
+u32 smp_mtrr_count VARFSEG;
+
+void
+wrmsr_smp(u32 index, u64 val)
+{
+ wrmsr(index, val);
+ if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr)) {
+ warn_noalloc();
+ return;
+ }
+ smp_mtrr[smp_mtrr_count].ecx = index;
+ smp_mtrr[smp_mtrr_count].eax = val;
+ smp_mtrr[smp_mtrr_count].edx = val >> 32;
+ smp_mtrr_count++;
+}
+
+u32 CountCPUs VARFSEG;
+u32 MaxCountCPUs;
+// 256 bits for the found APIC IDs
+u32 FoundAPICIDs[256/32] VARFSEG;
+extern void smp_ap_boot_code(void);
+ASM16(
+ " .global smp_ap_boot_code\n"
+ "smp_ap_boot_code:\n"
+
+ // Setup data segment
+ " movw $" __stringify(SEG_BIOS) ", %ax\n"
+ " movw %ax, %ds\n"
+
+ // MTRR setup
+ " movl $smp_mtrr, %esi\n"
+ " movl smp_mtrr_count, %ebx\n"
+ "1:testl %ebx, %ebx\n"
+ " jz 2f\n"
+ " movl 0(%esi), %ecx\n"
+ " movl 4(%esi), %eax\n"
+ " movl 8(%esi), %edx\n"
+ " wrmsr\n"
+ " addl $12, %esi\n"
+ " decl %ebx\n"
+ " jmp 1b\n"
+ "2:\n"
+
+ // get apic ID on EBX, set bit on FoundAPICIDs
+ " movl $1, %eax\n"
+ " cpuid\n"
+ " shrl $24, %ebx\n"
+ " lock btsl %ebx, FoundAPICIDs\n"
+
+ // Increment the cpu counter
+ " lock incl CountCPUs\n"
+
+ // Halt the processor.
+ "1:hlt\n"
+ " jmp 1b\n"
+ );
+
+int apic_id_is_present(u8 apic_id)
+{
+ return !!(FoundAPICIDs[apic_id/32] & (1ul << (apic_id % 32)));
+}
+
+// find and initialize the CPUs by launching a SIPI to them
+void
+smp_setup(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ ASSERT32FLAT();
+ u32 eax, ebx, ecx, cpuid_features;
+ cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+ if (eax < 1 || !(cpuid_features & CPUID_APIC)) {
+ // No apic - only the main cpu is present.
+ dprintf(1, "No apic - only the main cpu is present.\n");
+ CountCPUs= 1;
+ MaxCountCPUs = 1;
+ return;
+ }
+
+ // mark the BSP initial APIC ID as found, too:
+ u8 apic_id = ebx>>24;
+ FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32));
+
+ // Init the counter.
+ writel(&CountCPUs, 1);
+
+ // Setup jump trampoline to counter code.
+ u64 old = *(u64*)BUILD_AP_BOOT_ADDR;
+ // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR)
+ u64 new = (0xea | ((u64)SEG_BIOS<<24)
+ | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8));
+ *(u64*)BUILD_AP_BOOT_ADDR = new;
+
+ // enable local APIC
+ u32 val = readl(APIC_SVR);
+ writel(APIC_SVR, val | APIC_ENABLED);
+
+ /* Set LINT0 as Ext_INT, level triggered */
+ writel(APIC_LINT0, 0x8700);
+
+ /* Set LINT1 as NMI, level triggered */
+ writel(APIC_LINT1, 0x8400);
+
+ // broadcast SIPI
+ barrier();
+ writel(APIC_ICR_LOW, 0x000C4500);
+ u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
+ writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
+
+ // Wait for other CPUs to process the SIPI.
+ u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
+ while (cmos_smp_count + 1 != readl(&CountCPUs))
+ yield();
+
+ // Restore memory.
+ *(u64*)BUILD_AP_BOOT_ADDR = old;
+
+ MaxCountCPUs = romfile_loadint("etc/max-cpus", 0);
+ if (!MaxCountCPUs || MaxCountCPUs < CountCPUs)
+ MaxCountCPUs = CountCPUs;
+
+ dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", readl(&CountCPUs),
+ MaxCountCPUs);
+}
--- /dev/null
+ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
+
+DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
+{
+
+/****************************************************************
+ * PCI memory ranges
+ ****************************************************************/
+
+ Scope(\) {
+ ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
+ Name(P0S, 0x12345678)
+ ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
+ Name(P0E, 0x12345678)
+ ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
+ Name(P1V, 0x12)
+ ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
+ Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+ ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
+ Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+ ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
+ Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+ }
+
+
+/****************************************************************
+ * Suspend
+ ****************************************************************/
+
+ Scope(\) {
+ /*
+ * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
+ * must match piix4 emulation.
+ */
+
+ ACPI_EXTRACT_NAME_STRING acpi_s3_name
+ Name(_S3, Package(0x04) {
+ One, /* PM1a_CNT.SLP_TYP */
+ One, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ ACPI_EXTRACT_NAME_STRING acpi_s4_name
+ ACPI_EXTRACT_PKG_START acpi_s4_pkg
+ Name(_S4, Package(0x04) {
+ 0x2, /* PM1a_CNT.SLP_TYP */
+ 0x2, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ Name(_S5, Package(0x04) {
+ Zero, /* PM1a_CNT.SLP_TYP */
+ Zero, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ }
+
+ External(\_SB.PCI0, DeviceObj)
+ External(\_SB.PCI0.ISA, DeviceObj)
+
+ Scope(\_SB.PCI0.ISA) {
+ Device(PEVT) {
+ Name(_HID, "QEMU0001")
+ /* PEST will be patched to be Zero if no such device */
+ ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
+ Name(PEST, 0xFFFF)
+ OperationRegion(PEOR, SystemIO, PEST, 0x01)
+ Field(PEOR, ByteAcc, NoLock, Preserve) {
+ PEPT, 8,
+ }
+
+ Method(_STA, 0, NotSerialized) {
+ Store(PEST, Local0)
+ If (LEqual(Local0, Zero)) {
+ Return (0x00)
+ } Else {
+ Return (0x0F)
+ }
+ }
+
+ Method(RDPT, 0, NotSerialized) {
+ Store(PEPT, Local0)
+ Return (Local0)
+ }
+
+ Method(WRPT, 1, NotSerialized) {
+ Store(Arg0, PEPT)
+ }
+
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
+ })
+
+ CreateWordField(_CRS, IO._MIN, IOMN)
+ CreateWordField(_CRS, IO._MAX, IOMX)
+
+ Method(_INI, 0, NotSerialized) {
+ Store(PEST, IOMN)
+ Store(PEST, IOMX)
+ }
+ }
+ }
+}
--- /dev/null
+ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
+
+DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
+{
+
+/****************************************************************
+ * PCI hotplug
+ ****************************************************************/
+
+ /* Objects supplied by DSDT */
+ External(\_SB.PCI0, DeviceObj)
+ External(\_SB.PCI0.PCEJ, MethodObj)
+
+ Scope(\_SB.PCI0) {
+
+ /* Bulk generated PCI hotplug devices */
+ ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
+ ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
+ ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
+
+ // Method _EJ0 can be patched by BIOS to EJ0_
+ // at runtime, if the slot is detected to not support hotplug.
+ // Extract the offset of the address dword and the
+ // _EJ0 name to allow this patching.
+ Device(SAA) {
+ ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
+ Name(_SUN, 0xAA)
+ ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
+ Name(_ADR, 0xAA0000)
+ ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
+ Method(_EJ0, 1) {
+ Return (PCEJ(_SUN))
+ }
+ }
+ }
+}
--- /dev/null
+/* This file is the basis for the ssdt table generated in src/acpi.c.
+ * It defines the contents of the per-cpu Processor() object. At
+ * runtime, a dynamically generated SSDT will contain one copy of this
+ * AML snippet for every possible cpu in the system. The objects will
+ * be placed in the \_SB_ namespace.
+ *
+ * In addition to the aml code generated from this file, the
+ * src/acpi.c file creates a NTFY method with an entry for each cpu:
+ * Method(NTFY, 2) {
+ * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
+ * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
+ * ...
+ * }
+ * and a CPON array with the list of active and inactive cpus:
+ * Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
+ */
+
+ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
+
+DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
+{
+ ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
+ ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
+ ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
+ Processor(CPAA, 0xAA, 0x0000b010, 0x06) {
+ ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
+ Name(ID, 0xAA)
+/*
+ * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
+ * CPAA and 0xAA with the appropriate CPU id (see
+ * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without
+ * also updating the C code.
+ */
+ Name(_HID, "ACPI0007")
+ External(CPMA, MethodObj)
+ External(CPST, MethodObj)
+ External(CPEJ, MethodObj)
+ Method(_MAT, 0) {
+ Return (CPMA(ID))
+ }
+ Method(_STA, 0) {
+ Return (CPST(ID))
+ }
+ Method(_EJ0, 1, NotSerialized) {
+ CPEJ(ID, Arg0)
+ }
+ }
+}
--- /dev/null
+// Xen HVM support
+//
+// Copyright (C) 2011 Citrix Systems.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h"
+#include "xen.h"
+#include "paravirt.h" // PlatformRunningOn
+#include "memmap.h" // add_e820
+#include "types.h" // ASM32FLAT
+#include "util.h" // copy_acpi_rsdp
+#include "acpi.h" // find_acpi_features
+
+#define INFO_PHYSICAL_ADDRESS 0x00001000
+
+u32 xen_cpuid_base = 0;
+unsigned long xen_hypercall_page = 0;
+
+struct xen_seabios_info {
+ char signature[14]; /* XenHVMSeaBIOS\0 */
+ u8 length; /* Length of this struct */
+ u8 checksum; /* Set such that the sum over bytes 0..length == 0 */
+ /*
+ * Physical address of an array of tables_nr elements.
+ *
+ * Each element is a 32 bit value contianing the physical address
+ * of a BIOS table.
+ */
+ u32 tables;
+ u32 tables_nr;
+ /*
+ * Physical address of the e820 table, contains e820_nr entries.
+ */
+ u32 e820;
+ u32 e820_nr;
+} PACKED;
+
+static void validate_info(struct xen_seabios_info *t)
+{
+ if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) )
+ panic("Bad Xen info signature\n");
+
+ if ( t->length < sizeof(struct xen_seabios_info) )
+ panic("Bad Xen info length\n");
+
+ if (checksum(t, t->length) != 0)
+ panic("Bad Xen info checksum\n");
+}
+
+void xen_preinit(void)
+{
+ u32 base, eax, ebx, ecx, edx;
+ char signature[13];
+
+ if (!CONFIG_XEN)
+ return;
+
+ for (base = 0x40000000; base < 0x40010000; base += 0x100) {
+ cpuid(base, &eax, &ebx, &ecx, &edx);
+ memcpy(signature + 0, &ebx, 4);
+ memcpy(signature + 4, &ecx, 4);
+ memcpy(signature + 8, &edx, 4);
+ signature[12] = 0;
+
+ dprintf(9, "Found hypervisor signature \"%s\" at %x\n",
+ signature, base);
+ if (strcmp(signature, "XenVMMXenVMM") == 0) {
+ /* Set debug_io_port first, so the following messages work. */
+ DebugOutputPort = 0xe9;
+ dprintf(1, "SeaBIOS (version %s)\n\n", VERSION);
+ dprintf(1, "Found Xen hypervisor signature at %x\n", base);
+ if ((eax - base) < 2)
+ panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
+ eax, base);
+ xen_cpuid_base = base;
+ break;
+ }
+ }
+ if (!xen_cpuid_base) {
+ dprintf(1, "No Xen hypervisor found.\n");
+ return;
+ }
+ PlatformRunningOn = PF_QEMU|PF_XEN;
+}
+
+static int hypercall_xen_version( int cmd, void *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+/* Fill in hypercall transfer pages. */
+void xen_hypercall_setup(void)
+{
+ u32 eax, ebx, ecx, edx;
+ xen_extraversion_t extraversion;
+ unsigned long i;
+
+ if (!runningOnXen())
+ return;
+
+ cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
+
+ xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE);
+ if (!xen_hypercall_page)
+ panic("unable to allocate Xen hypercall page\n");
+
+ dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page);
+ for ( i = 0; i < eax; i++ )
+ wrmsr(ebx, xen_hypercall_page + (i << 12) + i);
+
+ /* Print version information. */
+ cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
+ hypercall_xen_version(XENVER_extraversion, extraversion);
+ dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
+}
+
+void xen_biostable_setup(void)
+{
+ struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
+ void **tables = (void*)info->tables;
+ int i;
+
+ dprintf(1, "xen: copy BIOS tables...\n");
+ for (i=0; i<info->tables_nr; i++)
+ copy_table(tables[i]);
+
+ find_acpi_features();
+}
+
+void xen_ramsize_preinit(void)
+{
+ int i;
+ struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
+ struct e820entry *e820 = (struct e820entry *)info->e820;
+ validate_info(info);
+
+ dprintf(1, "xen: copy e820...\n");
+
+ for (i = 0; i < info->e820_nr; i++) {
+ struct e820entry *e = &e820[i];
+ add_e820(e->start, e->size, e->type);
+ }
+}
--- /dev/null
+#ifndef __XEN_H
+#define __XEN_H
+
+void xen_preinit(void);
+void xen_ramsize_preinit(void);
+void xen_hypercall_setup(void);
+void xen_biostable_setup(void);
+
+extern unsigned long xen_hypercall_page;
+
+#define _hypercall0(type, name) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res) \
+ : "0" (__hentry) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res, __ign1; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res), "=b" (__ign1) \
+ : "0" (__hentry), "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
+ : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4) \
+ : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
+ long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
+ asm volatile ( \
+ "call *%%eax" \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
+ : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)), \
+ "5" ((long)(a5)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+/******************************************************************************
+ *
+ * The following interface definitions are taken from Xen and have the
+ * following license:
+ *
+ * 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.
+ */
+
+/* xen.h */
+
+#define __HYPERVISOR_xen_version 17
+
+/* version.h */
+
+/* arg == xen_extraversion_t. */
+#define XENVER_extraversion 1
+typedef char xen_extraversion_t[16];
+#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+
+#endif
#include "pci_regs.h" // PCI_VENDOR_ID
#include "boot.h" // bootprio_find_scsi_device
#include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
+#include "fw/paravirt.h" // runningOnQEMU
#include "disk.h"
#define ESP_TCLO 0x00
#include "pci_regs.h" // PCI_VENDOR_ID
#include "boot.h" // bootprio_find_scsi_device
#include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
+#include "fw/paravirt.h" // runningOnQEMU
#include "disk.h"
#define LSI_REG_DSTAT 0x0c
+++ /dev/null
-/*
- LzmaDecode.c
- LZMA Decoder (optimized for Speed version)
-
- LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
- http://www.7-zip.org/
-
- LZMA SDK is licensed under two licenses:
- 1) GNU Lesser General Public License (GNU LGPL)
- 2) Common Public License (CPL)
- It means that you can select one of these two licenses and
- follow rules of that license.
-
- SPECIAL EXCEPTION:
- Igor Pavlov, as the author of this Code, expressly permits you to
- statically or dynamically link your Code (or bind by name) to the
- interfaces of this file without subjecting your linked Code to the
- terms of the CPL or GNU LGPL. Any modifications or additions
- to this file, however, are subject to the LGPL or CPL terms.
-*/
-
-#include "lzmadecode.h"
-
-#define kNumTopBits 24
-#define kTopValue ((UInt32)1 << kNumTopBits)
-
-#define kNumBitModelTotalBits 11
-#define kBitModelTotal (1 << kNumBitModelTotalBits)
-#define kNumMoveBits 5
-
-#define RC_READ_BYTE (*Buffer++)
-
-#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
- { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
-
-
-#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
-
-#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
-
-
-#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
-
-#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
-#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
-#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
-
-#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
- { UpdateBit0(p); mi <<= 1; A0; } else \
- { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
-
-#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
-
-#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
- { int i = numLevels; res = 1; \
- do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
- res -= (1 << numLevels); }
-
-
-#define kNumPosBitsMax 4
-#define kNumPosStatesMax (1 << kNumPosBitsMax)
-
-#define kLenNumLowBits 3
-#define kLenNumLowSymbols (1 << kLenNumLowBits)
-#define kLenNumMidBits 3
-#define kLenNumMidSymbols (1 << kLenNumMidBits)
-#define kLenNumHighBits 8
-#define kLenNumHighSymbols (1 << kLenNumHighBits)
-
-#define LenChoice 0
-#define LenChoice2 (LenChoice + 1)
-#define LenLow (LenChoice2 + 1)
-#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
-#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
-#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
-
-
-#define kNumStates 12
-#define kNumLitStates 7
-
-#define kStartPosModelIndex 4
-#define kEndPosModelIndex 14
-#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
-
-#define kNumPosSlotBits 6
-#define kNumLenToPosStates 4
-
-#define kNumAlignBits 4
-#define kAlignTableSize (1 << kNumAlignBits)
-
-#define kMatchMinLen 2
-
-#define IsMatch 0
-#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
-#define IsRepG0 (IsRep + kNumStates)
-#define IsRepG1 (IsRepG0 + kNumStates)
-#define IsRepG2 (IsRepG1 + kNumStates)
-#define IsRep0Long (IsRepG2 + kNumStates)
-#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
-#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
-#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
-#define LenCoder (Align + kAlignTableSize)
-#define RepLenCoder (LenCoder + kNumLenProbs)
-#define Literal (RepLenCoder + kNumLenProbs)
-
-#if Literal != LZMA_BASE_SIZE
-StopCompilingDueBUG
-#endif
-
-int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
-{
- unsigned char prop0;
- if (size < LZMA_PROPERTIES_SIZE)
- return LZMA_RESULT_DATA_ERROR;
- prop0 = propsData[0];
- if (prop0 >= (9 * 5 * 5))
- return LZMA_RESULT_DATA_ERROR;
- {
- for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
- for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
- propsRes->lc = prop0;
- /*
- unsigned char remainder = (unsigned char)(prop0 / 9);
- propsRes->lc = prop0 % 9;
- propsRes->pb = remainder / 5;
- propsRes->lp = remainder % 5;
- */
- }
-
- return LZMA_RESULT_OK;
-}
-
-#define kLzmaStreamWasFinishedId (-1)
-
-int LzmaDecode(CLzmaDecoderState *vs,
- const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
- unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
-{
- CProb *p = vs->Probs;
- SizeT nowPos = 0;
- Byte previousByte = 0;
- UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
- UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
- int lc = vs->Properties.lc;
-
-
- int state = 0;
- UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
- int len = 0;
- const Byte *Buffer;
- const Byte *BufferLim;
- UInt32 Range;
- UInt32 Code;
-
- *inSizeProcessed = 0;
- *outSizeProcessed = 0;
-
- {
- UInt32 i;
- UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
- for (i = 0; i < numProbs; i++)
- p[i] = kBitModelTotal >> 1;
- }
-
- RC_INIT(inStream, inSize);
-
-
- while(nowPos < outSize)
- {
- CProb *prob;
- UInt32 bound;
- int posState = (int)(
- (nowPos
- )
- & posStateMask);
-
- prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
- IfBit0(prob)
- {
- int symbol = 1;
- UpdateBit0(prob)
- prob = p + Literal + (LZMA_LIT_SIZE *
- (((
- (nowPos
- )
- & literalPosMask) << lc) + (previousByte >> (8 - lc))));
-
- if (state >= kNumLitStates)
- {
- int matchByte;
- matchByte = outStream[nowPos - rep0];
- do
- {
- int bit;
- CProb *probLit;
- matchByte <<= 1;
- bit = (matchByte & 0x100);
- probLit = prob + 0x100 + bit + symbol;
- RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
- }
- while (symbol < 0x100);
- }
- while (symbol < 0x100)
- {
- CProb *probLit = prob + symbol;
- RC_GET_BIT(probLit, symbol)
- }
- previousByte = (Byte)symbol;
-
- outStream[nowPos++] = previousByte;
- if (state < 4) state = 0;
- else if (state < 10) state -= 3;
- else state -= 6;
- }
- else
- {
- UpdateBit1(prob);
- prob = p + IsRep + state;
- IfBit0(prob)
- {
- UpdateBit0(prob);
- rep3 = rep2;
- rep2 = rep1;
- rep1 = rep0;
- state = state < kNumLitStates ? 0 : 3;
- prob = p + LenCoder;
- }
- else
- {
- UpdateBit1(prob);
- prob = p + IsRepG0 + state;
- IfBit0(prob)
- {
- UpdateBit0(prob);
- prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
- IfBit0(prob)
- {
- UpdateBit0(prob);
-
- if (nowPos == 0)
- return LZMA_RESULT_DATA_ERROR;
-
- state = state < kNumLitStates ? 9 : 11;
- previousByte = outStream[nowPos - rep0];
- outStream[nowPos++] = previousByte;
-
- continue;
- }
- else
- {
- UpdateBit1(prob);
- }
- }
- else
- {
- UInt32 distance;
- UpdateBit1(prob);
- prob = p + IsRepG1 + state;
- IfBit0(prob)
- {
- UpdateBit0(prob);
- distance = rep1;
- }
- else
- {
- UpdateBit1(prob);
- prob = p + IsRepG2 + state;
- IfBit0(prob)
- {
- UpdateBit0(prob);
- distance = rep2;
- }
- else
- {
- UpdateBit1(prob);
- distance = rep3;
- rep3 = rep2;
- }
- rep2 = rep1;
- }
- rep1 = rep0;
- rep0 = distance;
- }
- state = state < kNumLitStates ? 8 : 11;
- prob = p + RepLenCoder;
- }
- {
- int numBits, offset;
- CProb *probLen = prob + LenChoice;
- IfBit0(probLen)
- {
- UpdateBit0(probLen);
- probLen = prob + LenLow + (posState << kLenNumLowBits);
- offset = 0;
- numBits = kLenNumLowBits;
- }
- else
- {
- UpdateBit1(probLen);
- probLen = prob + LenChoice2;
- IfBit0(probLen)
- {
- UpdateBit0(probLen);
- probLen = prob + LenMid + (posState << kLenNumMidBits);
- offset = kLenNumLowSymbols;
- numBits = kLenNumMidBits;
- }
- else
- {
- UpdateBit1(probLen);
- probLen = prob + LenHigh;
- offset = kLenNumLowSymbols + kLenNumMidSymbols;
- numBits = kLenNumHighBits;
- }
- }
- RangeDecoderBitTreeDecode(probLen, numBits, len);
- len += offset;
- }
-
- if (state < 4)
- {
- int posSlot;
- state += kNumLitStates;
- prob = p + PosSlot +
- ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
- kNumPosSlotBits);
- RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
- if (posSlot >= kStartPosModelIndex)
- {
- int numDirectBits = ((posSlot >> 1) - 1);
- rep0 = (2 | ((UInt32)posSlot & 1));
- if (posSlot < kEndPosModelIndex)
- {
- rep0 <<= numDirectBits;
- prob = p + SpecPos + rep0 - posSlot - 1;
- }
- else
- {
- numDirectBits -= kNumAlignBits;
- do
- {
- RC_NORMALIZE
- Range >>= 1;
- rep0 <<= 1;
- if (Code >= Range)
- {
- Code -= Range;
- rep0 |= 1;
- }
- }
- while (--numDirectBits != 0);
- prob = p + Align;
- rep0 <<= kNumAlignBits;
- numDirectBits = kNumAlignBits;
- }
- {
- int i = 1;
- int mi = 1;
- do
- {
- CProb *prob3 = prob + mi;
- RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
- i <<= 1;
- }
- while(--numDirectBits != 0);
- }
- }
- else
- rep0 = posSlot;
- if (++rep0 == (UInt32)(0))
- {
- /* it's for stream version */
- len = kLzmaStreamWasFinishedId;
- break;
- }
- }
-
- len += kMatchMinLen;
- if (rep0 > nowPos)
- return LZMA_RESULT_DATA_ERROR;
-
-
- do
- {
- previousByte = outStream[nowPos - rep0];
- len--;
- outStream[nowPos++] = previousByte;
- }
- while(len != 0 && nowPos < outSize);
- }
- }
- RC_NORMALIZE;
-
-
- *inSizeProcessed = (SizeT)(Buffer - inStream);
- *outSizeProcessed = nowPos;
- return LZMA_RESULT_OK;
-}
+++ /dev/null
-/*
- LzmaDecode.h
- LZMA Decoder interface
-
- LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
- http://www.7-zip.org/
-
- LZMA SDK is licensed under two licenses:
- 1) GNU Lesser General Public License (GNU LGPL)
- 2) Common Public License (CPL)
- It means that you can select one of these two licenses and
- follow rules of that license.
-
- SPECIAL EXCEPTION:
- Igor Pavlov, as the author of this code, expressly permits you to
- statically or dynamically link your code (or bind by name) to the
- interfaces of this file without subjecting your linked code to the
- terms of the CPL or GNU LGPL. Any modifications or additions
- to this file, however, are subject to the LGPL or CPL terms.
-*/
-
-#ifndef __LZMADECODE_H
-#define __LZMADECODE_H
-
-typedef unsigned char Byte;
-typedef unsigned short UInt16;
-typedef unsigned int UInt32;
-typedef UInt32 SizeT;
-
-#define CProb UInt16
-
-#define LZMA_RESULT_OK 0
-#define LZMA_RESULT_DATA_ERROR 1
-
-
-#define LZMA_BASE_SIZE 1846
-#define LZMA_LIT_SIZE 768
-
-#define LZMA_PROPERTIES_SIZE 5
-
-typedef struct _CLzmaProperties
-{
- int lc;
- int lp;
- int pb;
-}CLzmaProperties;
-
-int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
-
-#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
-
-#define kLzmaNeedInitId (-2)
-
-typedef struct _CLzmaDecoderState
-{
- CLzmaProperties Properties;
- CProb *Probs;
-
-
-} CLzmaDecoderState;
-
-
-int LzmaDecode(CLzmaDecoderState *vs,
- const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
- unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
-
-#endif
+++ /dev/null
-// MPTable generation (on emulators)
-//
-// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "mptable.h" // MPTABLE_SIGNATURE
-#include "hw/pci.h"
-#include "hw/pci_regs.h"
-
-void
-mptable_setup(void)
-{
- if (! CONFIG_MPTABLE)
- return;
-
- dprintf(3, "init MPTable\n");
-
- // Config structure in temp area.
- struct mptable_config_s *config = malloc_tmp(32*1024);
- if (!config) {
- warn_noalloc();
- return;
- }
- memset(config, 0, sizeof(*config));
- config->signature = MPCONFIG_SIGNATURE;
- config->spec = 4;
- memcpy(config->oemid, BUILD_CPUNAME8, sizeof(config->oemid));
- memcpy(config->productid, "0.1 ", sizeof(config->productid));
- config->lapic = BUILD_APIC_ADDR;
-
- // Detect cpu info
- u32 cpuid_signature, ebx, ecx, cpuid_features;
- cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
- if (! cpuid_signature) {
- // Use default values.
- cpuid_signature = 0x600;
- cpuid_features = 0x201;
- }
- int pkgcpus = 1;
- if (cpuid_features & (1 << 28)) {
- /* Only populate the MPS tables with the first logical CPU in
- each package */
- pkgcpus = (ebx >> 16) & 0xff;
- pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */
- }
- u8 apic_version = readl((u8*)BUILD_APIC_ADDR + 0x30) & 0xff;
-
- // CPU definitions.
- struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus;
- int i;
- for (i = 0; i < MaxCountCPUs; i+=pkgcpus) {
- memset(cpu, 0, sizeof(*cpu));
- cpu->type = MPT_TYPE_CPU;
- cpu->apicid = i;
- cpu->apicver = apic_version;
- /* cpu flags: enabled, bootstrap cpu */
- cpu->cpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00);
- cpu->cpusignature = cpuid_signature;
- cpu->featureflag = cpuid_features;
- cpu++;
- }
- int entrycount = cpu - cpus;
-
- // PCI bus
- struct mpt_bus *buses = (void*)cpu, *bus = buses;
- if (!hlist_empty(&PCIDevices)) {
- memset(bus, 0, sizeof(*bus));
- bus->type = MPT_TYPE_BUS;
- bus->busid = 0;
- memcpy(bus->bustype, "PCI ", sizeof(bus->bustype));
- bus++;
- entrycount++;
- }
-
- /* isa bus */
- int isabusid = bus - buses;
- memset(bus, 0, sizeof(*bus));
- bus->type = MPT_TYPE_BUS;
- bus->busid = isabusid;
- memcpy(bus->bustype, "ISA ", sizeof(bus->bustype));
- bus++;
- entrycount++;
-
- /* ioapic */
- u8 ioapic_id = BUILD_IOAPIC_ID;
- struct mpt_ioapic *ioapic = (void*)bus;
- memset(ioapic, 0, sizeof(*ioapic));
- ioapic->type = MPT_TYPE_IOAPIC;
- ioapic->apicid = ioapic_id;
- ioapic->apicver = 0x11;
- ioapic->flags = 1; // enable
- ioapic->apicaddr = BUILD_IOAPIC_ADDR;
- entrycount++;
-
- /* irqs */
- struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs;
- int dev = -1;
- unsigned short pinmask = 0;
-
- struct pci_device *pci;
- foreachpci(pci) {
- u16 bdf = pci->bdf;
- if (pci_bdf_to_bus(bdf) != 0)
- break;
- int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
- int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
- if (pin == 0)
- continue;
- if (dev != pci_bdf_to_busdev(bdf)) {
- dev = pci_bdf_to_busdev(bdf);
- pinmask = 0;
- }
- if (pinmask & (1 << pin)) /* pin was seen already */
- continue;
- pinmask |= (1 << pin);
- memset(intsrc, 0, sizeof(*intsrc));
- intsrc->type = MPT_TYPE_INTSRC;
- intsrc->irqtype = 0; /* INT */
- intsrc->irqflag = 1; /* active high */
- intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */
- intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1);
- intsrc->dstapic = ioapic_id;
- intsrc->dstirq = irq;
- intsrc++;
- }
-
- int irq0_override = romfile_loadint("etc/irq0-override", 0);
- for (i = 0; i < 16; i++) {
- memset(intsrc, 0, sizeof(*intsrc));
- if (BUILD_PCI_IRQS & (1 << i))
- continue;
- intsrc->type = MPT_TYPE_INTSRC;
- intsrc->irqtype = 0; /* INT */
- intsrc->irqflag = 0; /* conform to bus spec */
- intsrc->srcbus = isabusid; /* ISA bus */
- intsrc->srcbusirq = i;
- intsrc->dstapic = ioapic_id;
- intsrc->dstirq = i;
- if (irq0_override) {
- /* Destination 2 is covered by irq0->inti2 override (i ==
- 0). Source IRQ 2 is unused */
- if (i == 0)
- intsrc->dstirq = 2;
- else if (i == 2)
- intsrc--;
- }
- intsrc++;
- }
-
- /* Local interrupt assignment */
- intsrc->type = MPT_TYPE_LOCAL_INT;
- intsrc->irqtype = 3; /* ExtINT */
- intsrc->irqflag = 0; /* PO, EL default */
- intsrc->srcbus = isabusid; /* ISA */
- intsrc->srcbusirq = 0;
- intsrc->dstapic = 0; /* BSP == APIC #0 */
- intsrc->dstirq = 0; /* LINTIN0 */
- intsrc++;
-
- intsrc->type = MPT_TYPE_LOCAL_INT;
- intsrc->irqtype = 1; /* NMI */
- intsrc->irqflag = 0; /* PO, EL default */
- intsrc->srcbus = isabusid; /* ISA */
- intsrc->srcbusirq = 0;
- intsrc->dstapic = 0xff; /* to all local APICs */
- intsrc->dstirq = 1; /* LINTIN1 */
- intsrc++;
- entrycount += intsrc - intsrcs;
-
- // Finalize config structure.
- int length = (void*)intsrc - (void*)config;
- config->entrycount = entrycount;
- config->length = length;
- config->checksum -= checksum(config, length);
-
- // Allocate final memory locations. (In theory the config
- // structure can go in high memory, but Linux kernels before
- // v2.6.30 crash with that.)
- struct mptable_config_s *finalconfig = malloc_fseg(length);
- struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
- if (!finalconfig || !floating) {
- warn_noalloc();
- free(config);
- free(finalconfig);
- free(floating);
- return;
- }
- memcpy(finalconfig, config, length);
- free(config);
-
- /* floating pointer structure */
- memset(floating, 0, sizeof(*floating));
- floating->signature = MPTABLE_SIGNATURE;
- floating->physaddr = (u32)finalconfig;
- floating->length = 1;
- floating->spec_rev = 4;
- floating->checksum -= checksum(floating, sizeof(*floating));
-
- dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
- floating, finalconfig, length);
-}
+++ /dev/null
-#ifndef __MPTABLE_H
-#define __MPTABLE_H
-
-#include "types.h" // u32
-
-#define MPTABLE_SIGNATURE 0x5f504d5f // "_MP_"
-
-struct mptable_floating_s {
- u32 signature;
- u32 physaddr;
- u8 length;
- u8 spec_rev;
- u8 checksum;
- u8 feature1;
- u8 feature2;
- u8 reserved[3];
-};
-
-#define MPCONFIG_SIGNATURE 0x504d4350 // "PCMP"
-
-struct mptable_config_s {
- u32 signature;
- u16 length;
- u8 spec;
- u8 checksum;
- char oemid[8];
- char productid[12];
- u32 oemptr;
- u16 oemsize;
- u16 entrycount;
- u32 lapic;
- u16 exttable_length;
- u8 exttable_checksum;
- u8 reserved;
-} PACKED;
-
-#define MPT_TYPE_CPU 0
-#define MPT_TYPE_BUS 1
-#define MPT_TYPE_IOAPIC 2
-#define MPT_TYPE_INTSRC 3
-#define MPT_TYPE_LOCAL_INT 4
-
-struct mpt_cpu {
- u8 type;
- u8 apicid;
- u8 apicver;
- u8 cpuflag;
- u32 cpusignature;
- u32 featureflag;
- u32 reserved[2];
-} PACKED;
-
-struct mpt_bus {
- u8 type;
- u8 busid;
- char bustype[6];
-} PACKED;
-
-struct mpt_ioapic {
- u8 type;
- u8 apicid;
- u8 apicver;
- u8 flags;
- u32 apicaddr;
-} PACKED;
-
-struct mpt_intsrc {
- u8 type;
- u8 irqtype;
- u16 irqflag;
- u8 srcbus;
- u8 srcbusirq;
- u8 dstapic;
- u8 dstirq;
-} PACKED;
-
-// mptable.c
-void mptable_setup(void);
-
-#endif // mptable.h
+++ /dev/null
-// Initialize MTRRs - mostly useful on KVM.
-//
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "hw/pci.h" // pcimem_start
-#include "paravirt.h" // RamSize
-
-#define MSR_MTRRcap 0x000000fe
-#define MSR_MTRRfix64K_00000 0x00000250
-#define MSR_MTRRfix16K_80000 0x00000258
-#define MSR_MTRRfix16K_A0000 0x00000259
-#define MSR_MTRRfix4K_C0000 0x00000268
-#define MSR_MTRRfix4K_C8000 0x00000269
-#define MSR_MTRRfix4K_D0000 0x0000026a
-#define MSR_MTRRfix4K_D8000 0x0000026b
-#define MSR_MTRRfix4K_E0000 0x0000026c
-#define MSR_MTRRfix4K_E8000 0x0000026d
-#define MSR_MTRRfix4K_F0000 0x0000026e
-#define MSR_MTRRfix4K_F8000 0x0000026f
-#define MSR_MTRRdefType 0x000002ff
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-#define MTRR_MEMTYPE_UC 0
-#define MTRR_MEMTYPE_WC 1
-#define MTRR_MEMTYPE_WT 4
-#define MTRR_MEMTYPE_WP 5
-#define MTRR_MEMTYPE_WB 6
-
-void mtrr_setup(void)
-{
- if (!CONFIG_MTRR_INIT)
- return;
-
- u32 eax, ebx, ecx, edx, cpuid_features;
- cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
- if (!(cpuid_features & CPUID_MTRR))
- return;
- if (!(cpuid_features & CPUID_MSR))
- return;
-
- dprintf(3, "init mtrr\n");
-
- u32 mtrr_cap = rdmsr(MSR_MTRRcap);
- int vcnt = mtrr_cap & 0xff;
- int fix = mtrr_cap & 0x100;
- if (!vcnt || !fix)
- return;
-
- // Disable MTRRs
- wrmsr_smp(MSR_MTRRdefType, 0);
-
- // Set fixed MTRRs
- union u64b {
- u8 valb[8];
- u64 val;
- } u;
- u.val = 0;
- int i;
- for (i = 0; i < 8; i++)
- if (RamSize >= 65536 * (i + 1))
- u.valb[i] = MTRR_MEMTYPE_WB;
- wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
- u.val = 0;
- for (i = 0; i < 8; i++)
- if (RamSize >= 0x80000 + 16384 * (i + 1))
- u.valb[i] = MTRR_MEMTYPE_WB;
- wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
- wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached
- int j;
- for (j = 0; j < 8; j++) {
- u.val = 0;
- for (i = 0; i < 8; i++)
- if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
- u.valb[i] = MTRR_MEMTYPE_WP;
- wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
- }
-
- // Set variable MTRRs
- int phys_bits = 36;
- cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
- if (eax >= 0x80000008) {
- /* Get physical bits from leaf 0x80000008 (if available) */
- cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
- phys_bits = eax & 0xff;
- }
- u64 phys_mask = ((1ull << phys_bits) - 1);
- for (i=0; i<vcnt; i++) {
- wrmsr_smp(MTRRphysBase_MSR(i), 0);
- wrmsr_smp(MTRRphysMask_MSR(i), 0);
- }
- /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
- wrmsr_smp(MTRRphysBase_MSR(0), pcimem_start | MTRR_MEMTYPE_UC);
- wrmsr_smp(MTRRphysMask_MSR(0)
- , (-((1ull<<32)-pcimem_start) & phys_mask) | 0x800);
-
- // Enable fixed and variable MTRRs; set default type.
- wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);
-}
#include "bregs.h" // struct bregs
#include "config.h" // CONFIG_*
#include "biosvar.h" // GET_GLOBAL
-#include "paravirt.h" // PlatformRunningOn
+#include "fw/paravirt.h" // PlatformRunningOn
struct putcinfo {
void (*func)(struct putcinfo *info, char c);
+++ /dev/null
-// Paravirtualization support.
-//
-// Copyright (C) 2013 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2009 Red Hat Inc.
-//
-// Authors:
-// Gleb Natapov <gnatapov@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h" // CONFIG_QEMU
-#include "util.h" // dprintf
-#include "byteorder.h" // be32_to_cpu
-#include "ioport.h" // outw
-#include "paravirt.h" // qemu_cfg_preinit
-#include "smbios.h" // smbios_setup
-#include "memmap.h" // add_e820
-#include "hw/cmos.h" // CMOS_*
-#include "acpi.h" // acpi_setup
-#include "mptable.h" // mptable_setup
-#include "hw/pci.h" // create_pirtable
-#include "xen.h" // xen_biostable_setup
-
-// Amount of continuous ram under 4Gig
-u32 RamSize;
-// Amount of continuous ram >4Gig
-u64 RamSizeOver4G;
-// Type of emulator platform.
-int PlatformRunningOn VARFSEG;
-
-/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
- * should be used to determine that a VM is running under KVM.
- */
-#define KVM_CPUID_SIGNATURE 0x40000000
-
-static void kvm_preinit(void)
-{
- if (!CONFIG_QEMU)
- return;
- unsigned int eax, ebx, ecx, edx;
- char signature[13];
-
- cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
- memcpy(signature + 0, &ebx, 4);
- memcpy(signature + 4, &ecx, 4);
- memcpy(signature + 8, &edx, 4);
- signature[12] = 0;
-
- if (strcmp(signature, "KVMKVMKVM") == 0) {
- dprintf(1, "Running on KVM\n");
- PlatformRunningOn |= PF_KVM;
- }
-}
-
-void
-qemu_preinit(void)
-{
- if (!CONFIG_QEMU)
- return;
-
- if (runningOnXen()) {
- xen_ramsize_preinit();
- return;
- }
-
- PlatformRunningOn = PF_QEMU;
- kvm_preinit();
-
- // On emulators, get memory size from nvram.
- u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
- | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24));
- if (rs)
- rs += 16 * 1024 * 1024;
- else
- rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10)
- | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18))
- + 1 * 1024 * 1024);
- RamSize = rs;
- add_e820(0, rs, E820_RAM);
-
- // Check for memory over 4Gig
- u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16)
- | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24)
- | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32));
- RamSizeOver4G = high;
- add_e820(0x100000000ull, high, E820_RAM);
-
- /* reserve 256KB BIOS area at the end of 4 GB */
- add_e820(0xfffc0000, 256*1024, E820_RESERVED);
-
- dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G);
-}
-
-void
-qemu_platform_setup(void)
-{
- if (!CONFIG_QEMU)
- return;
-
- if (runningOnXen()) {
- pci_probe_devices();
- xen_hypercall_setup();
- xen_biostable_setup();
- return;
- }
-
- // Initialize pci
- pci_setup();
- smm_device_setup();
- smm_setup();
-
- // Initialize mtrr and smp
- mtrr_setup();
- smp_setup();
-
- // Create bios tables
- pirtable_setup();
- mptable_setup();
- smbios_setup();
- acpi_setup();
-}
-
-
-/****************************************************************
- * QEMU firmware config (fw_cfg) interface
- ****************************************************************/
-
-// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content
-// should be passed via the fw_cfg "file" interface.)
-#define QEMU_CFG_SIGNATURE 0x00
-#define QEMU_CFG_ID 0x01
-#define QEMU_CFG_UUID 0x02
-#define QEMU_CFG_NUMA 0x0d
-#define QEMU_CFG_BOOT_MENU 0x0e
-#define QEMU_CFG_MAX_CPUS 0x0f
-#define QEMU_CFG_FILE_DIR 0x19
-#define QEMU_CFG_ARCH_LOCAL 0x8000
-#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
-#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
-#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
-#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
-
-static void
-qemu_cfg_select(u16 f)
-{
- outw(f, PORT_QEMU_CFG_CTL);
-}
-
-static void
-qemu_cfg_read(void *buf, int len)
-{
- insb(PORT_QEMU_CFG_DATA, buf, len);
-}
-
-static void
-qemu_cfg_skip(int len)
-{
- while (len--)
- inb(PORT_QEMU_CFG_DATA);
-}
-
-static void
-qemu_cfg_read_entry(void *buf, int e, int len)
-{
- qemu_cfg_select(e);
- qemu_cfg_read(buf, len);
-}
-
-struct qemu_romfile_s {
- struct romfile_s file;
- int select, skip;
-};
-
-static int
-qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
-{
- if (file->size > maxlen)
- return -1;
- struct qemu_romfile_s *qfile;
- qfile = container_of(file, struct qemu_romfile_s, file);
- qemu_cfg_select(qfile->select);
- qemu_cfg_skip(qfile->skip);
- qemu_cfg_read(dst, file->size);
- return file->size;
-}
-
-static void
-qemu_romfile_add(char *name, int select, int skip, int size)
-{
- struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile));
- if (!qfile) {
- warn_noalloc();
- return;
- }
- memset(qfile, 0, sizeof(*qfile));
- strtcpy(qfile->file.name, name, sizeof(qfile->file.name));
- qfile->file.size = size;
- qfile->select = select;
- qfile->skip = skip;
- qfile->file.copy = qemu_cfg_read_file;
- romfile_add(&qfile->file);
-}
-
-struct e820_reservation {
- u64 address;
- u64 length;
- u32 type;
-};
-
-#define SMBIOS_FIELD_ENTRY 0
-#define SMBIOS_TABLE_ENTRY 1
-
-struct qemu_smbios_header {
- u16 length;
- u8 headertype;
- u8 tabletype;
- u16 fieldoffset;
-} PACKED;
-
-// Populate romfile entries for legacy fw_cfg ports (that predate the
-// "file" interface).
-static void
-qemu_cfg_legacy(void)
-{
- if (!CONFIG_QEMU)
- return;
-
- // Misc config items.
- qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2);
- qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);
- qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
-
- // NUMA data
- u64 numacount;
- qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount));
- int max_cpu = romfile_loadint("etc/max-cpus", 0);
- qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount)
- , max_cpu*sizeof(u64));
- qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA
- , sizeof(numacount) + max_cpu*sizeof(u64)
- , numacount*sizeof(u64));
-
- // e820 data
- u32 count32;
- qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));
- if (count32) {
- struct e820_reservation entry;
- int i;
- for (i = 0; i < count32; i++) {
- qemu_cfg_read(&entry, sizeof(entry));
- add_e820(entry.address, entry.length, entry.type);
- }
- } else if (runningOnKVM()) {
- // Backwards compatibility - provide hard coded range.
- // 4 pages before the bios, 3 pages for vmx tss pages, the
- // other page for EPT real mode pagetable
- add_e820(0xfffbc000, 4*4096, E820_RESERVED);
- }
-
- // ACPI tables
- char name[128];
- u16 cnt;
- qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
- int i, offset = sizeof(cnt);
- for (i = 0; i < cnt; i++) {
- u16 len;
- qemu_cfg_read(&len, sizeof(len));
- offset += sizeof(len);
- snprintf(name, sizeof(name), "acpi/table%d", i);
- qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
- qemu_cfg_skip(len);
- offset += len;
- }
-
- // SMBIOS info
- qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
- offset = sizeof(cnt);
- for (i = 0; i < cnt; i++) {
- struct qemu_smbios_header header;
- qemu_cfg_read(&header, sizeof(header));
- if (header.headertype == SMBIOS_FIELD_ENTRY) {
- snprintf(name, sizeof(name), "smbios/field%d-%d"
- , header.tabletype, header.fieldoffset);
- qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
- , offset + sizeof(header)
- , header.length - sizeof(header));
- } else {
- snprintf(name, sizeof(name), "smbios/table%d-%d"
- , header.tabletype, i);
- qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
- , offset + 3, header.length - 3);
- }
- qemu_cfg_skip(header.length - sizeof(header));
- offset += header.length;
- }
-}
-
-struct QemuCfgFile {
- u32 size; /* file size */
- u16 select; /* write this to 0x510 to read it */
- u16 reserved;
- char name[56];
-};
-
-void qemu_cfg_init(void)
-{
- if (!runningOnQEMU())
- return;
-
- // Detect fw_cfg interface.
- qemu_cfg_select(QEMU_CFG_SIGNATURE);
- char *sig = "QEMU";
- int i;
- for (i = 0; i < 4; i++)
- if (inb(PORT_QEMU_CFG_DATA) != sig[i])
- return;
- dprintf(1, "Found QEMU fw_cfg\n");
-
- // Populate romfiles for legacy fw_cfg entries
- qemu_cfg_legacy();
-
- // Load files found in the fw_cfg file directory
- u32 count;
- qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
- count = be32_to_cpu(count);
- u32 e;
- for (e = 0; e < count; e++) {
- struct QemuCfgFile qfile;
- qemu_cfg_read(&qfile, sizeof(qfile));
- qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
- , 0, be32_to_cpu(qfile.size));
- }
-}
+++ /dev/null
-#ifndef __PV_H
-#define __PV_H
-
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-
-// Types of paravirtualized platforms.
-#define PF_QEMU (1<<0)
-#define PF_XEN (1<<1)
-#define PF_KVM (1<<2)
-
-extern u32 RamSize;
-extern u64 RamSizeOver4G;
-extern int PlatformRunningOn;
-
-static inline int runningOnQEMU(void) {
- return CONFIG_QEMU || (
- CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU);
-}
-static inline int runningOnXen(void) {
- return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN;
-}
-static inline int runningOnKVM(void) {
- return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM;
-}
-
-void qemu_preinit(void);
-void qemu_platform_setup(void);
-void qemu_cfg_init(void);
-
-#endif
+++ /dev/null
-// Initialize PCI devices (on emulators)
-//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "hw/pci.h" // pci_config_readl
-#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "hw/pci_regs.h" // PCI_COMMAND
-#include "ioport.h" // PORT_ATA1_CMD_BASE
-#include "config.h" // CONFIG_*
-#include "memmap.h" // add_e820
-#include "paravirt.h" // RamSize
-#include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR
-#include "list.h" // struct hlist_node
-#include "acpi.h" // acpi_pm1a_cnt
-
-#define PCI_DEVICE_MEM_MIN 0x1000
-#define PCI_BRIDGE_IO_MIN 0x1000
-#define PCI_BRIDGE_MEM_MIN 0x100000
-
-enum pci_region_type {
- PCI_REGION_TYPE_IO,
- PCI_REGION_TYPE_MEM,
- PCI_REGION_TYPE_PREFMEM,
- PCI_REGION_TYPE_COUNT,
-};
-
-static const char *region_type_name[] = {
- [ PCI_REGION_TYPE_IO ] = "io",
- [ PCI_REGION_TYPE_MEM ] = "mem",
- [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
-};
-
-u64 pcimem_start = BUILD_PCIMEM_START;
-u64 pcimem_end = BUILD_PCIMEM_END;
-u64 pcimem64_start = BUILD_PCIMEM64_START;
-u64 pcimem64_end = BUILD_PCIMEM64_END;
-
-struct pci_region_entry {
- struct pci_device *dev;
- int bar;
- u64 size;
- u64 align;
- int is64;
- enum pci_region_type type;
- struct hlist_node node;
-};
-
-struct pci_region {
- /* pci region assignments */
- u64 base;
- struct hlist_head list;
-};
-
-struct pci_bus {
- struct pci_region r[PCI_REGION_TYPE_COUNT];
- struct pci_device *bus_dev;
-};
-
-static u32 pci_bar(struct pci_device *pci, int region_num)
-{
- if (region_num != PCI_ROM_SLOT) {
- return PCI_BASE_ADDRESS_0 + region_num * 4;
- }
-
-#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
- u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
- return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
-}
-
-static void
-pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64)
-{
- u32 ofs = pci_bar(pci, bar);
- pci_config_writel(pci->bdf, ofs, addr);
- if (is64)
- pci_config_writel(pci->bdf, ofs + 4, addr >> 32);
-}
-
-
-/****************************************************************
- * Misc. device init
- ****************************************************************/
-
-/* host irqs corresponding to PCI irqs A-D */
-const u8 pci_irqs[4] = {
- 10, 10, 11, 11
-};
-
-static int dummy_pci_slot_get_irq(struct pci_device *pci, int pin)
-{
- dprintf(1, "pci_slot_get_irq called with unknown routing\n");
-
- return 0xff; /* PCI defined "unknown" or "no connection" for x86 */
-}
-
-static int (*pci_slot_get_irq)(struct pci_device *pci, int pin) =
- dummy_pci_slot_get_irq;
-
-// Return the global irq number corresponding to a host bus device irq pin.
-static int piix_pci_slot_get_irq(struct pci_device *pci, int pin)
-{
- int slot_addend = 0;
-
- while (pci->parent != NULL) {
- slot_addend += pci_bdf_to_dev(pci->bdf);
- pci = pci->parent;
- }
- slot_addend += pci_bdf_to_dev(pci->bdf) - 1;
- return pci_irqs[(pin - 1 + slot_addend) & 3];
-}
-
-static int mch_pci_slot_get_irq(struct pci_device *pci, int pin)
-{
- int irq, slot, pin_addend = 0;
-
- while (pci->parent != NULL) {
- pin_addend += pci_bdf_to_dev(pci->bdf);
- pci = pci->parent;
- }
- slot = pci_bdf_to_dev(pci->bdf);
-
- switch (slot) {
- /* Slots 0-24 rotate slot:pin mapping similar to piix above, but
- with a different starting index - see q35-acpi-dsdt.dsl */
- case 0 ... 24:
- irq = pci_irqs[(pin - 1 + pin_addend + slot) & 3];
- break;
- /* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */
- case 25 ... 31:
- irq = pci_irqs[(pin - 1 + pin_addend) & 3];
- break;
- }
-
- return irq;
-}
-
-/* PIIX3/PIIX4 PCI to ISA bridge */
-static void piix_isa_bridge_setup(struct pci_device *pci, void *arg)
-{
- int i, irq;
- u8 elcr[2];
-
- elcr[0] = 0x00;
- elcr[1] = 0x00;
- for (i = 0; i < 4; i++) {
- irq = pci_irqs[i];
- /* set to trigger level */
- elcr[irq >> 3] |= (1 << (irq & 7));
- /* activate irq remapping in PIIX */
- pci_config_writeb(pci->bdf, 0x60 + i, irq);
- }
- outb(elcr[0], 0x4d0);
- outb(elcr[1], 0x4d1);
- dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
-}
-
-/* ICH9 LPC PCI to ISA bridge */
-/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
-void mch_isa_bridge_setup(struct pci_device *dev, void *arg)
-{
- u16 bdf = dev->bdf;
- int i, irq;
- u8 elcr[2];
-
- elcr[0] = 0x00;
- elcr[1] = 0x00;
-
- for (i = 0; i < 4; i++) {
- irq = pci_irqs[i];
- /* set to trigger level */
- elcr[irq >> 3] |= (1 << (irq & 7));
-
- /* activate irq remapping in LPC */
-
- /* PIRQ[A-D] routing */
- pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i, irq);
- /* PIRQ[E-H] routing */
- pci_config_writeb(bdf, ICH9_LPC_PIRQE_ROUT + i, irq);
- }
- outb(elcr[0], ICH9_LPC_PORT_ELCR1);
- outb(elcr[1], ICH9_LPC_PORT_ELCR2);
- dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]);
-
- /* pm io base */
- pci_config_writel(bdf, ICH9_LPC_PMBASE,
- PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE);
-
- /* acpi enable, SCI: IRQ9 000b = irq9*/
- pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
-
- acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
- pmtimer_setup(PORT_ACPI_PM_BASE + 0x08);
-}
-
-static void storage_ide_setup(struct pci_device *pci, void *arg)
-{
- /* IDE: we map it as in ISA mode */
- pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0);
- pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0);
- pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0);
- pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0);
-}
-
-/* PIIX3/PIIX4 IDE */
-static void piix_ide_setup(struct pci_device *pci, void *arg)
-{
- u16 bdf = pci->bdf;
- pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
- pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
-}
-
-static void pic_ibm_setup(struct pci_device *pci, void *arg)
-{
- /* PIC, IBM, MPIC & MPIC2 */
- pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0);
-}
-
-static void apple_macio_setup(struct pci_device *pci, void *arg)
-{
- /* macio bridge */
- pci_set_io_region_addr(pci, 0, 0x80800000, 0);
-}
-
-/* PIIX4 Power Management device (for ACPI) */
-static void piix4_pm_setup(struct pci_device *pci, void *arg)
-{
- u16 bdf = pci->bdf;
- // acpi sci is hardwired to 9
- pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
-
- pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
- pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
- pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
- pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
-
- acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
- pmtimer_setup(PORT_ACPI_PM_BASE + 0x08);
-}
-
-/* ICH9 SMBUS */
-/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */
-void ich9_smbus_setup(struct pci_device *dev, void *arg)
-{
- u16 bdf = dev->bdf;
- /* map smbus into io space */
- pci_config_writel(bdf, ICH9_SMB_SMB_BASE,
- PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO);
-
- /* enable SMBus */
- pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
-}
-
-static const struct pci_device_id pci_device_tbl[] = {
- /* PIIX3/PIIX4 PCI to ISA bridge */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
- piix_isa_bridge_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
- piix_isa_bridge_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
- mch_isa_bridge_setup),
-
- /* STORAGE IDE */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
- PCI_CLASS_STORAGE_IDE, piix_ide_setup),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
- PCI_CLASS_STORAGE_IDE, piix_ide_setup),
- PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
- storage_ide_setup),
-
- /* PIC, IBM, MIPC & MPIC2 */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
- pic_ibm_setup),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
- pic_ibm_setup),
-
- /* PIIX4 Power Management device (for ACPI) */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
- piix4_pm_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS,
- ich9_smbus_setup),
-
- /* 0xff00 */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup),
-
- PCI_DEVICE_END,
-};
-
-static void pci_bios_init_device(struct pci_device *pci)
-{
- u16 bdf = pci->bdf;
- dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n"
- , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
- , pci->vendor, pci->device);
-
- /* map the interrupt */
- int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
- if (pin != 0)
- pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
-
- pci_init_device(pci_device_tbl, pci, NULL);
-
- /* enable memory mappings */
- pci_config_maskw(bdf, PCI_COMMAND, 0,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR);
-}
-
-static void pci_bios_init_devices(void)
-{
- struct pci_device *pci;
- foreachpci(pci) {
- pci_bios_init_device(pci);
- }
-}
-
-static void pci_enable_default_vga(void)
-{
- struct pci_device *pci;
-
- foreachpci(pci) {
- if (is_pci_vga(pci)) {
- dprintf(1, "PCI: Using %02x:%02x.%x for primary VGA\n",
- pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
- pci_bdf_to_fn(pci->bdf));
- return;
- }
- }
-
- pci = pci_find_class(PCI_CLASS_DISPLAY_VGA);
- if (!pci) {
- dprintf(1, "PCI: No VGA devices found\n");
- return;
- }
-
- dprintf(1, "PCI: Enabling %02x:%02x.%x for primary VGA\n",
- pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
- pci_bdf_to_fn(pci->bdf));
-
- pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
- while (pci->parent) {
- pci = pci->parent;
-
- dprintf(1, "PCI: Setting VGA enable on bridge %02x:%02x.%x\n",
- pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
- pci_bdf_to_fn(pci->bdf));
-
- pci_config_maskw(pci->bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_VGA);
- pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- }
-}
-
-/****************************************************************
- * Platform device initialization
- ****************************************************************/
-
-void i440fx_mem_addr_setup(struct pci_device *dev, void *arg)
-{
- if (RamSize <= 0x80000000)
- pcimem_start = 0x80000000;
- else if (RamSize <= 0xc0000000)
- pcimem_start = 0xc0000000;
-
- pci_slot_get_irq = piix_pci_slot_get_irq;
-}
-
-void mch_mem_addr_setup(struct pci_device *dev, void *arg)
-{
- u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
- u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE;
-
- /* setup mmconfig */
- u16 bdf = dev->bdf;
- u32 upper = addr >> 32;
- u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
- pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
- pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
- pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
- add_e820(addr, size, E820_RESERVED);
-
- /* setup pci i/o window (above mmconfig) */
- pcimem_start = addr + size;
-
- pci_slot_get_irq = mch_pci_slot_get_irq;
-}
-
-static const struct pci_device_id pci_platform_tbl[] = {
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
- i440fx_mem_addr_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH,
- mch_mem_addr_setup),
- PCI_DEVICE_END
-};
-
-static void pci_bios_init_platform(void)
-{
- struct pci_device *pci;
- foreachpci(pci) {
- pci_init_device(pci_platform_tbl, pci, NULL);
- }
-}
-
-
-/****************************************************************
- * Bus initialization
- ****************************************************************/
-
-static void
-pci_bios_init_bus_rec(int bus, u8 *pci_bus)
-{
- int bdf;
- u16 class;
-
- dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
-
- /* prevent accidental access to unintended devices */
- foreachbdf(bdf, bus) {
- class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
- if (class == PCI_CLASS_BRIDGE_PCI) {
- pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
- pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
- }
- }
-
- foreachbdf(bdf, bus) {
- class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
- if (class != PCI_CLASS_BRIDGE_PCI) {
- continue;
- }
- dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
-
- u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
- if (pribus != bus) {
- dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
- pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
- } else {
- dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
- }
-
- u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
- (*pci_bus)++;
- if (*pci_bus != secbus) {
- dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
- secbus, *pci_bus);
- secbus = *pci_bus;
- pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
- } else {
- dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
- }
-
- /* set to max for access to all subordinate buses.
- later set it to accurate value */
- u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
- pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
-
- pci_bios_init_bus_rec(secbus, pci_bus);
-
- if (subbus != *pci_bus) {
- dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
- subbus, *pci_bus);
- subbus = *pci_bus;
- } else {
- dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
- }
- pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
- }
-}
-
-static void
-pci_bios_init_bus(void)
-{
- u8 pci_bus = 0;
- pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
-}
-
-
-/****************************************************************
- * Bus sizing
- ****************************************************************/
-
-static void
-pci_bios_get_bar(struct pci_device *pci, int bar,
- int *ptype, u64 *psize, int *pis64)
-{
- u32 ofs = pci_bar(pci, bar);
- u16 bdf = pci->bdf;
- u32 old = pci_config_readl(bdf, ofs);
- int is64 = 0, type = PCI_REGION_TYPE_MEM;
- u64 mask;
-
- if (bar == PCI_ROM_SLOT) {
- mask = PCI_ROM_ADDRESS_MASK;
- pci_config_writel(bdf, ofs, mask);
- } else {
- if (old & PCI_BASE_ADDRESS_SPACE_IO) {
- mask = PCI_BASE_ADDRESS_IO_MASK;
- type = PCI_REGION_TYPE_IO;
- } else {
- mask = PCI_BASE_ADDRESS_MEM_MASK;
- if (old & PCI_BASE_ADDRESS_MEM_PREFETCH)
- type = PCI_REGION_TYPE_PREFMEM;
- is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
- == PCI_BASE_ADDRESS_MEM_TYPE_64);
- }
- pci_config_writel(bdf, ofs, ~0);
- }
- u64 val = pci_config_readl(bdf, ofs);
- pci_config_writel(bdf, ofs, old);
- if (is64) {
- u32 hold = pci_config_readl(bdf, ofs + 4);
- pci_config_writel(bdf, ofs + 4, ~0);
- u32 high = pci_config_readl(bdf, ofs + 4);
- pci_config_writel(bdf, ofs + 4, hold);
- val |= ((u64)high << 32);
- mask |= ((u64)0xffffffff << 32);
- *psize = (~(val & mask)) + 1;
- } else {
- *psize = ((~(val & mask)) + 1) & 0xffffffff;
- }
- *ptype = type;
- *pis64 = is64;
-}
-
-static int pci_bios_bridge_region_is64(struct pci_region *r,
- struct pci_device *pci, int type)
-{
- if (type != PCI_REGION_TYPE_PREFMEM)
- return 0;
- u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
- if (!pmem) {
- pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0);
- pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
- pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0);
- }
- if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64)
- return 0;
- struct pci_region_entry *entry;
- hlist_for_each_entry(entry, &r->list, node) {
- if (!entry->is64)
- return 0;
- }
- return 1;
-}
-
-static u64 pci_region_align(struct pci_region *r)
-{
- struct pci_region_entry *entry;
- hlist_for_each_entry(entry, &r->list, node) {
- // The first entry in the sorted list has the largest alignment
- return entry->align;
- }
- return 1;
-}
-
-static u64 pci_region_sum(struct pci_region *r)
-{
- u64 sum = 0;
- struct pci_region_entry *entry;
- hlist_for_each_entry(entry, &r->list, node) {
- sum += entry->size;
- }
- return sum;
-}
-
-static void pci_region_migrate_64bit_entries(struct pci_region *from,
- struct pci_region *to)
-{
- struct hlist_node *n, **last = &to->list.first;
- struct pci_region_entry *entry;
- hlist_for_each_entry_safe(entry, n, &from->list, node) {
- if (!entry->is64)
- continue;
- // Move from source list to destination list.
- hlist_del(&entry->node);
- hlist_add(&entry->node, last);
- }
-}
-
-static struct pci_region_entry *
-pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
- int bar, u64 size, u64 align, int type, int is64)
-{
- struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
- if (!entry) {
- warn_noalloc();
- return NULL;
- }
- memset(entry, 0, sizeof(*entry));
- entry->dev = dev;
- entry->bar = bar;
- entry->size = size;
- entry->align = align;
- entry->is64 = is64;
- entry->type = type;
- // Insert into list in sorted order.
- struct hlist_node **pprev;
- struct pci_region_entry *pos;
- hlist_for_each_entry_pprev(pos, pprev, &bus->r[type].list, node) {
- if (pos->align < align || (pos->align == align && pos->size < size))
- break;
- }
- hlist_add(&entry->node, pprev);
- return entry;
-}
-
-static int pci_bios_check_devices(struct pci_bus *busses)
-{
- dprintf(1, "PCI: check devices\n");
-
- // Calculate resources needed for regular (non-bus) devices.
- struct pci_device *pci;
- foreachpci(pci) {
- if (pci->class == PCI_CLASS_BRIDGE_PCI)
- busses[pci->secondary_bus].bus_dev = pci;
-
- struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)];
- int i;
- for (i = 0; i < PCI_NUM_REGIONS; i++) {
- if ((pci->class == PCI_CLASS_BRIDGE_PCI) &&
- (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT))
- continue;
- int type, is64;
- u64 size;
- pci_bios_get_bar(pci, i, &type, &size, &is64);
- if (size == 0)
- continue;
-
- if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN)
- size = PCI_DEVICE_MEM_MIN;
- struct pci_region_entry *entry = pci_region_create_entry(
- bus, pci, i, size, size, type, is64);
- if (!entry)
- return -1;
-
- if (is64)
- i++;
- }
- }
-
- // Propagate required bus resources to parent busses.
- int secondary_bus;
- for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) {
- struct pci_bus *s = &busses[secondary_bus];
- if (!s->bus_dev)
- continue;
- struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
- int type;
- for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
- u64 align = (type == PCI_REGION_TYPE_IO) ?
- PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
- if (pci_region_align(&s->r[type]) > align)
- align = pci_region_align(&s->r[type]);
- u64 sum = pci_region_sum(&s->r[type]);
- u64 size = ALIGN(sum, align);
- int is64 = pci_bios_bridge_region_is64(&s->r[type],
- s->bus_dev, type);
- // entry->bar is -1 if the entry represents a bridge region
- struct pci_region_entry *entry = pci_region_create_entry(
- parent, s->bus_dev, -1, size, align, type, is64);
- if (!entry)
- return -1;
- dprintf(1, "PCI: secondary bus %d size %08llx type %s\n",
- entry->dev->secondary_bus, size,
- region_type_name[entry->type]);
- }
- }
- return 0;
-}
-
-
-/****************************************************************
- * BAR assignment
- ****************************************************************/
-
-// Setup region bases (given the regions' size and alignment)
-static int pci_bios_init_root_regions(struct pci_bus *bus)
-{
- bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
-
- struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
- struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
-
- if (pci_region_align(r_start) < pci_region_align(r_end)) {
- // Swap regions to improve alignment.
- r_end = r_start;
- r_start = &bus->r[PCI_REGION_TYPE_PREFMEM];
- }
- u64 sum = pci_region_sum(r_end);
- u64 align = pci_region_align(r_end);
- r_end->base = ALIGN_DOWN((pcimem_end - sum), align);
- sum = pci_region_sum(r_start);
- align = pci_region_align(r_start);
- r_start->base = ALIGN_DOWN((r_end->base - sum), align);
-
- if ((r_start->base < pcimem_start) ||
- (r_start->base > pcimem_end))
- // Memory range requested is larger than available.
- return -1;
- return 0;
-}
-
-#define PCI_IO_SHIFT 8
-#define PCI_MEMORY_SHIFT 16
-#define PCI_PREF_MEMORY_SHIFT 16
-
-static void
-pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr)
-{
- u16 bdf = entry->dev->bdf;
- if (entry->bar >= 0) {
- dprintf(1, "PCI: map device bdf=%02x:%02x.%x"
- " bar %d, addr %08llx, size %08llx [%s]\n",
- pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
- entry->bar, addr, entry->size, region_type_name[entry->type]);
-
- pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64);
- return;
- }
-
- u64 limit = addr + entry->size - 1;
- if (entry->type == PCI_REGION_TYPE_IO) {
- pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT);
- pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
- pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
- pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
- }
- if (entry->type == PCI_REGION_TYPE_MEM) {
- pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT);
- pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
- }
- if (entry->type == PCI_REGION_TYPE_PREFMEM) {
- pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT);
- pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT);
- pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32);
- pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32);
- }
-}
-
-static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
-{
- struct hlist_node *n;
- struct pci_region_entry *entry;
- hlist_for_each_entry_safe(entry, n, &r->list, node) {
- u64 addr = r->base;
- r->base += entry->size;
- if (entry->bar == -1)
- // Update bus base address if entry is a bridge region
- busses[entry->dev->secondary_bus].r[entry->type].base = addr;
- pci_region_map_one_entry(entry, addr);
- hlist_del(&entry->node);
- free(entry);
- }
-}
-
-static void pci_bios_map_devices(struct pci_bus *busses)
-{
- if (pci_bios_init_root_regions(busses)) {
- struct pci_region r64_mem, r64_pref;
- r64_mem.list.first = NULL;
- r64_pref.list.first = NULL;
- pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
- &r64_mem);
- pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
- &r64_pref);
-
- if (pci_bios_init_root_regions(busses))
- panic("PCI: out of 32bit address space\n");
-
- u64 sum_mem = pci_region_sum(&r64_mem);
- u64 sum_pref = pci_region_sum(&r64_pref);
- u64 align_mem = pci_region_align(&r64_mem);
- u64 align_pref = pci_region_align(&r64_pref);
-
- r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem);
- r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref);
- pcimem64_start = r64_mem.base;
- pcimem64_end = r64_pref.base + sum_pref;
-
- pci_region_map_entries(busses, &r64_mem);
- pci_region_map_entries(busses, &r64_pref);
- } else {
- // no bars mapped high -> drop 64bit window (see dsdt)
- pcimem64_start = 0;
- }
- // Map regions on each device.
- int bus;
- for (bus = 0; bus<=MaxPCIBus; bus++) {
- int type;
- for (type = 0; type < PCI_REGION_TYPE_COUNT; type++)
- pci_region_map_entries(busses, &busses[bus].r[type]);
- }
-}
-
-
-/****************************************************************
- * Main setup code
- ****************************************************************/
-
-void
-pci_setup(void)
-{
- if (!CONFIG_QEMU)
- return;
-
- dprintf(3, "pci setup\n");
-
- dprintf(1, "=== PCI bus & bridge init ===\n");
- if (pci_probe_host() != 0) {
- return;
- }
- pci_bios_init_bus();
-
- dprintf(1, "=== PCI device probing ===\n");
- pci_probe_devices();
-
- pcimem_start = RamSize;
- pci_bios_init_platform();
-
- dprintf(1, "=== PCI new allocation pass #1 ===\n");
- struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1));
- if (!busses) {
- warn_noalloc();
- return;
- }
- memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
- if (pci_bios_check_devices(busses))
- return;
-
- dprintf(1, "=== PCI new allocation pass #2 ===\n");
- pci_bios_map_devices(busses);
-
- pci_bios_init_devices();
-
- free(busses);
-
- pci_enable_default_vga();
-}
+++ /dev/null
-// PIR table generation (for emulators)
-//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "hw/pci.h" // struct pir_header
-#include "config.h" // CONFIG_*
-#include "util.h" // checksum
-
-struct pir_header *PirAddr VARFSEG;
-
-struct pir_table {
- struct pir_header pir;
- struct pir_slot slots[6];
-} PACKED;
-
-extern struct pir_table PIR_TABLE;
-#if CONFIG_PIRTABLE
-struct pir_table PIR_TABLE __aligned(16) VARFSEG = {
- .pir = {
- .version = 0x0100,
- .size = sizeof(struct pir_table),
- .router_devfunc = 0x08,
- .compatible_devid = 0x122e8086,
- },
- .slots = {
- {
- // first slot entry PCI-to-ISA (embedded)
- .dev = 1<<3,
- .links = {
- {.link = 0x60, .bitmap = 0xdef8}, // INTA#
- {.link = 0x61, .bitmap = 0xdef8}, // INTB#
- {.link = 0x62, .bitmap = 0xdef8}, // INTC#
- {.link = 0x63, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 0, // embedded
- }, {
- // second slot entry: 1st PCI slot
- .dev = 2<<3,
- .links = {
- {.link = 0x61, .bitmap = 0xdef8}, // INTA#
- {.link = 0x62, .bitmap = 0xdef8}, // INTB#
- {.link = 0x63, .bitmap = 0xdef8}, // INTC#
- {.link = 0x60, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 1,
- }, {
- // third slot entry: 2nd PCI slot
- .dev = 3<<3,
- .links = {
- {.link = 0x62, .bitmap = 0xdef8}, // INTA#
- {.link = 0x63, .bitmap = 0xdef8}, // INTB#
- {.link = 0x60, .bitmap = 0xdef8}, // INTC#
- {.link = 0x61, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 2,
- }, {
- // 4th slot entry: 3rd PCI slot
- .dev = 4<<3,
- .links = {
- {.link = 0x63, .bitmap = 0xdef8}, // INTA#
- {.link = 0x60, .bitmap = 0xdef8}, // INTB#
- {.link = 0x61, .bitmap = 0xdef8}, // INTC#
- {.link = 0x62, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 3,
- }, {
- // 5th slot entry: 4rd PCI slot
- .dev = 5<<3,
- .links = {
- {.link = 0x60, .bitmap = 0xdef8}, // INTA#
- {.link = 0x61, .bitmap = 0xdef8}, // INTB#
- {.link = 0x62, .bitmap = 0xdef8}, // INTC#
- {.link = 0x63, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 4,
- }, {
- // 6th slot entry: 5rd PCI slot
- .dev = 6<<3,
- .links = {
- {.link = 0x61, .bitmap = 0xdef8}, // INTA#
- {.link = 0x62, .bitmap = 0xdef8}, // INTB#
- {.link = 0x63, .bitmap = 0xdef8}, // INTC#
- {.link = 0x60, .bitmap = 0xdef8}, // INTD#
- },
- .slot_nr = 5,
- },
- }
-};
-#endif // CONFIG_PIRTABLE
-
-void
-pirtable_setup(void)
-{
- if (! CONFIG_PIRTABLE)
- return;
-
- dprintf(3, "init PIR table\n");
-
- PIR_TABLE.pir.signature = PIR_SIGNATURE;
- PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE));
- PirAddr = &PIR_TABLE.pir;
-}
#include "bregs.h" // struct bregs
#include "boot.h" // boot_init
#include "hw/usb.h" // usb_setup
-#include "paravirt.h" // qemu_cfg_preinit
-#include "xen.h" // xen_preinit
+#include "fw/paravirt.h" // qemu_cfg_preinit
+#include "fw/xen.h" // xen_preinit
#include "hw/ps2port.h" // ps2port_setup
#include "hw/virtio-blk.h" // virtio_blk_setup
#include "hw/virtio-scsi.h" // virtio_scsi_setup
+++ /dev/null
-/*
- * Bochs/QEMU ACPI DSDT ASL definition
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-/*
- * Copyright (c) 2010 Isaku Yamahata
- * yamahata at valinux co jp
- * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
- */
-
-DefinitionBlock (
- "q35-acpi-dsdt.aml",// Output Filename
- "DSDT", // Signature
- 0x01, // DSDT Compliance Revision
- "BXPC", // OEMID
- "BXDSDT", // TABLE ID
- 0x2 // OEM Revision
- )
-{
-
-#include "acpi-dsdt-dbug.dsl"
-
- Scope(\_SB) {
- OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
- OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
- Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
- PCIB, 8,
- }
- }
-
-
-/****************************************************************
- * PCI Bus definition
- ****************************************************************/
-
- Scope(\_SB) {
- Device(PCI0) {
- Name(_HID, EisaId("PNP0A08"))
- Name(_CID, EisaId("PNP0A03"))
- Name(_ADR, 0x00)
- Name(_UID, 1)
-
- // _OSC: based on sample of ACPI3.0b spec
- Name(SUPP, 0) // PCI _OSC Support Field value
- Name(CTRL, 0) // PCI _OSC Control Field value
- Method(_OSC, 4) {
- // Create DWORD-addressable fields from the Capabilities Buffer
- CreateDWordField(Arg3, 0, CDW1)
-
- // Check for proper UUID
- If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
- // Create DWORD-addressable fields from the Capabilities Buffer
- CreateDWordField(Arg3, 4, CDW2)
- CreateDWordField(Arg3, 8, CDW3)
-
- // Save Capabilities DWORD2 & 3
- Store(CDW2, SUPP)
- Store(CDW3, CTRL)
-
- // Always allow native PME, AER (no dependencies)
- // Never allow SHPC (no SHPC controller in this system)
- And(CTRL, 0x1D, CTRL)
-
-#if 0 // For now, nothing to do
- If (Not(And(CDW1, 1))) { // Query flag clear?
- // Disable GPEs for features granted native control.
- If (And(CTRL, 0x01)) { // Hot plug control granted?
- Store(0, HPCE) // clear the hot plug SCI enable bit
- Store(1, HPCS) // clear the hot plug SCI status bit
- }
- If (And(CTRL, 0x04)) { // PME control granted?
- Store(0, PMCE) // clear the PME SCI enable bit
- Store(1, PMCS) // clear the PME SCI status bit
- }
- If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
- // Set status to not restore PCI Express cap structure
- // upon resume from S3
- Store(1, S3CR)
- }
- }
-#endif
- If (LNotEqual(Arg1, One)) {
- // Unknown revision
- Or(CDW1, 0x08, CDW1)
- }
- If (LNotEqual(CDW3, CTRL)) {
- // Capabilities bits were masked
- Or(CDW1, 0x10, CDW1)
- }
- // Update DWORD3 in the buffer
- Store(CTRL, CDW3)
- } Else {
- Or(CDW1, 4, CDW1) // Unrecognized UUID
- }
- Return (Arg3)
- }
- }
- }
-
-#include "acpi-dsdt-pci-crs.dsl"
-#include "acpi-dsdt-hpet.dsl"
-
-
-/****************************************************************
- * VGA
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- Device(VGA) {
- Name(_ADR, 0x00010000)
- Method(_S1D, 0, NotSerialized) {
- Return (0x00)
- }
- Method(_S2D, 0, NotSerialized) {
- Return (0x00)
- }
- Method(_S3D, 0, NotSerialized) {
- Return (0x00)
- }
- }
- }
-
-
-/****************************************************************
- * LPC ISA bridge
- ****************************************************************/
-
- Scope(\_SB.PCI0) {
- /* PCI D31:f0 LPC ISA bridge */
- Device(ISA) {
- /* PCI D31:f0 */
- Name(_ADR, 0x001f0000)
-
- /* ICH9 PCI to ISA irq remapping */
- OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
-
- OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
- Field(LPCD, AnyAcc, NoLock, Preserve) {
- COMA, 3,
- , 1,
- COMB, 3,
-
- Offset(0x01),
- LPTD, 2,
- , 2,
- FDCD, 2
- }
- OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
- Field(LPCE, AnyAcc, NoLock, Preserve) {
- CAEN, 1,
- CBEN, 1,
- LPEN, 1,
- FDEN, 1
- }
- }
- }
-
-#include "acpi-dsdt-isa.dsl"
-
-
-/****************************************************************
- * PCI IRQs
- ****************************************************************/
-
- /* Zero => PIC mode, One => APIC Mode */
- Name(\PICF, Zero)
- Method(\_PIC, 1, NotSerialized) {
- Store(Arg0, \PICF)
- }
-
- Scope(\_SB) {
- Scope(PCI0) {
-#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \
- Package() { nr##ffff, 0, lnk0, 0 }, \
- Package() { nr##ffff, 1, lnk1, 0 }, \
- Package() { nr##ffff, 2, lnk2, 0 }, \
- Package() { nr##ffff, 3, lnk3, 0 }
-
-#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
-#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
-#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
-#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
-
-#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
-#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
-#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
-#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
-
- Name(PRTP, package() {
- prt_slot_lnkE(0x0000),
- prt_slot_lnkF(0x0001),
- prt_slot_lnkG(0x0002),
- prt_slot_lnkH(0x0003),
- prt_slot_lnkE(0x0004),
- prt_slot_lnkF(0x0005),
- prt_slot_lnkG(0x0006),
- prt_slot_lnkH(0x0007),
- prt_slot_lnkE(0x0008),
- prt_slot_lnkF(0x0009),
- prt_slot_lnkG(0x000a),
- prt_slot_lnkH(0x000b),
- prt_slot_lnkE(0x000c),
- prt_slot_lnkF(0x000d),
- prt_slot_lnkG(0x000e),
- prt_slot_lnkH(0x000f),
- prt_slot_lnkE(0x0010),
- prt_slot_lnkF(0x0011),
- prt_slot_lnkG(0x0012),
- prt_slot_lnkH(0x0013),
- prt_slot_lnkE(0x0014),
- prt_slot_lnkF(0x0015),
- prt_slot_lnkG(0x0016),
- prt_slot_lnkH(0x0017),
- prt_slot_lnkE(0x0018),
-
- /* INTA -> PIRQA for slot 25 - 31
- see the default value of D<N>IR */
- prt_slot_lnkA(0x0019),
- prt_slot_lnkA(0x001a),
- prt_slot_lnkA(0x001b),
- prt_slot_lnkA(0x001c),
- prt_slot_lnkA(0x001d),
-
- /* PCIe->PCI bridge. use PIRQ[E-H] */
- prt_slot_lnkE(0x001e),
-
- prt_slot_lnkA(0x001f)
- })
-
-#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \
- Package() { nr##ffff, 0, gsi0, 0 }, \
- Package() { nr##ffff, 1, gsi1, 0 }, \
- Package() { nr##ffff, 2, gsi2, 0 }, \
- Package() { nr##ffff, 3, gsi3, 0 }
-
-#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
-#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
-#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
-#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
-
-#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
-#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
-#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
-#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
-
- Name(PRTA, package() {
- prt_slot_gsiE(0x0000),
- prt_slot_gsiF(0x0001),
- prt_slot_gsiG(0x0002),
- prt_slot_gsiH(0x0003),
- prt_slot_gsiE(0x0004),
- prt_slot_gsiF(0x0005),
- prt_slot_gsiG(0x0006),
- prt_slot_gsiH(0x0007),
- prt_slot_gsiE(0x0008),
- prt_slot_gsiF(0x0009),
- prt_slot_gsiG(0x000a),
- prt_slot_gsiH(0x000b),
- prt_slot_gsiE(0x000c),
- prt_slot_gsiF(0x000d),
- prt_slot_gsiG(0x000e),
- prt_slot_gsiH(0x000f),
- prt_slot_gsiE(0x0010),
- prt_slot_gsiF(0x0011),
- prt_slot_gsiG(0x0012),
- prt_slot_gsiH(0x0013),
- prt_slot_gsiE(0x0014),
- prt_slot_gsiF(0x0015),
- prt_slot_gsiG(0x0016),
- prt_slot_gsiH(0x0017),
- prt_slot_gsiE(0x0018),
-
- /* INTA -> PIRQA for slot 25 - 31, but 30
- see the default value of D<N>IR */
- prt_slot_gsiA(0x0019),
- prt_slot_gsiA(0x001a),
- prt_slot_gsiA(0x001b),
- prt_slot_gsiA(0x001c),
- prt_slot_gsiA(0x001d),
-
- /* PCIe->PCI bridge. use PIRQ[E-H] */
- prt_slot_gsiE(0x001e),
-
- prt_slot_gsiA(0x001f)
- })
-
- Method(_PRT, 0, NotSerialized) {
- /* PCI IRQ routing table, example from ACPI 2.0a specification,
- section 6.2.8.1 */
- /* Note: we provide the same info as the PCI routing
- table of the Bochs BIOS */
- If (LEqual(\PICF, Zero)) {
- Return (PRTP)
- } Else {
- Return (PRTA)
- }
- }
- }
-
- Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
- PRQA, 8,
- PRQB, 8,
- PRQC, 8,
- PRQD, 8,
-
- Offset(0x08),
- PRQE, 8,
- PRQF, 8,
- PRQG, 8,
- PRQH, 8
- }
-
- Method(IQST, 1, NotSerialized) {
- // _STA method - get status
- If (And(0x80, Arg0)) {
- Return (0x09)
- }
- Return (0x0B)
- }
- Method(IQCR, 1, NotSerialized) {
- // _CRS method - get current settings
- Name(PRR0, ResourceTemplate() {
- Interrupt(, Level, ActiveHigh, Shared) { 0 }
- })
- CreateDWordField(PRR0, 0x05, PRRI)
- Store(And(Arg0, 0x0F), PRRI)
- Return (PRR0)
- }
-
-#define define_link(link, uid, reg) \
- Device(link) { \
- Name(_HID, EISAID("PNP0C0F")) \
- Name(_UID, uid) \
- Name(_PRS, ResourceTemplate() { \
- Interrupt(, Level, ActiveHigh, Shared) { \
- 5, 10, 11 \
- } \
- }) \
- Method(_STA, 0, NotSerialized) { \
- Return (IQST(reg)) \
- } \
- Method(_DIS, 0, NotSerialized) { \
- Or(reg, 0x80, reg) \
- } \
- Method(_CRS, 0, NotSerialized) { \
- Return (IQCR(reg)) \
- } \
- Method(_SRS, 1, NotSerialized) { \
- CreateDWordField(Arg0, 0x05, PRRI) \
- Store(PRRI, reg) \
- } \
- }
-
- define_link(LNKA, 0, PRQA)
- define_link(LNKB, 1, PRQB)
- define_link(LNKC, 2, PRQC)
- define_link(LNKD, 3, PRQD)
- define_link(LNKE, 4, PRQE)
- define_link(LNKF, 5, PRQF)
- define_link(LNKG, 6, PRQG)
- define_link(LNKH, 7, PRQH)
-
-#define define_gsi_link(link, uid, gsi) \
- Device(link) { \
- Name(_HID, EISAID("PNP0C0F")) \
- Name(_UID, uid) \
- Name(_PRS, ResourceTemplate() { \
- Interrupt(, Level, ActiveHigh, Shared) { \
- gsi \
- } \
- }) \
- Name(_CRS, ResourceTemplate() { \
- Interrupt(, Level, ActiveHigh, Shared) { \
- gsi \
- } \
- }) \
- Method(_SRS, 1, NotSerialized) { \
- } \
- }
-
- define_gsi_link(GSIA, 0, 0x10)
- define_gsi_link(GSIB, 0, 0x11)
- define_gsi_link(GSIC, 0, 0x12)
- define_gsi_link(GSID, 0, 0x13)
- define_gsi_link(GSIE, 0, 0x14)
- define_gsi_link(GSIF, 0, 0x15)
- define_gsi_link(GSIG, 0, 0x16)
- define_gsi_link(GSIH, 0, 0x17)
- }
-
-#include "acpi-dsdt-cpu-hotplug.dsl"
-
-
-/****************************************************************
- * General purpose events
- ****************************************************************/
-
- Scope(\_GPE) {
- Name(_HID, "ACPI0006")
-
- Method(_L00) {
- }
- Method(_L01) {
- // CPU hotplug event
- \_SB.PRSC()
- }
- Method(_L02) {
- }
- Method(_L03) {
- }
- Method(_L04) {
- }
- Method(_L05) {
- }
- Method(_L06) {
- }
- Method(_L07) {
- }
- Method(_L08) {
- }
- Method(_L09) {
- }
- Method(_L0A) {
- }
- Method(_L0B) {
- }
- Method(_L0C) {
- }
- Method(_L0D) {
- }
- Method(_L0E) {
- }
- Method(_L0F) {
- }
- }
-}
#include "hw/pic.h" // pic_eoi2
#include "biosvar.h" // struct bios_data_area_s
#include "bregs.h" // struct bregs
-#include "acpi.h" // find_resume_vector
+#include "fw/acpi.h" // find_resume_vector
#include "hw/ps2port.h" // i8042_reboot
#include "hw/pci.h" // pci_reboot
#include "hw/cmos.h" // inb_cmos
+++ /dev/null
-// Support for enabling/disabling BIOS ram shadowing.
-//
-// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // memcpy
-#include "hw/pci.h" // pci_config_writeb
-#include "config.h" // CONFIG_*
-#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "hw/pci_regs.h" // PCI_VENDOR_ID
-#include "paravirt.h" // runningOnXen
-#include "dev-q35.h" // PCI_VENDOR_ID_INTEL
-
-// On the emulators, the bios at 0xf0000 is also at 0xffff0000
-#define BIOS_SRC_OFFSET 0xfff00000
-
-#define I440FX_PAM0 0x59
-
-// Enable shadowing and copy bios.
-static void
-__make_bios_writable_intel(u16 bdf, u32 pam0)
-{
- // Make ram from 0xc0000-0xf0000 writable
- int clear = 0;
- int i;
- for (i=0; i<6; i++) {
- u32 pam = pam0 + 1 + i;
- int reg = pci_config_readb(bdf, pam);
- if (CONFIG_OPTIONROMS_DEPLOYED && (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, pam, 0x33);
- memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
- clear = 1;
- } else {
- pci_config_writeb(bdf, pam, 0x33);
- }
- }
- if (clear)
- memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
-
- // Make ram from 0xf0000-0x100000 writable
- int reg = pci_config_readb(bdf, pam0);
- pci_config_writeb(bdf, pam0, 0x30);
- if (reg & 0x10)
- // Ram already present.
- return;
-
- // Copy bios.
- extern u8 code32flat_start[], code32flat_end[];
- memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
- , code32flat_end - code32flat_start);
-}
-
-static void
-make_bios_writable_intel(u16 bdf, u32 pam0)
-{
- int reg = pci_config_readb(bdf, pam0);
- if (!(reg & 0x10)) {
- // QEMU doesn't fully implement the piix shadow capabilities -
- // if ram isn't backing the bios segment when shadowing is
- // disabled, the code itself wont be in memory. So, run the
- // code from the high-memory flash location.
- u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
- void (*func)(u16 bdf, u32 pam0) = (void*)pos;
- func(bdf, pam0);
- return;
- }
- // Ram already present - just enable writes
- __make_bios_writable_intel(bdf, pam0);
-}
-
-static void
-make_bios_readonly_intel(u16 bdf, u32 pam0)
-{
- // Flush any pending writes before locking memory.
- wbinvd();
-
- // Write protect roms from 0xc0000-0xf0000
- u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
- if (CONFIG_WRITABLE_UPPERMEMORY)
- romlast = rom_get_last();
- if (CONFIG_MALLOC_UPPERMEMORY)
- rommax = rom_get_max();
- int i;
- for (i=0; i<6; i++) {
- u32 mem = BUILD_ROM_START + i * 32*1024;
- u32 pam = pam0 + 1 + i;
- if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
- if (romlast >= mem && rommax >= mem + 16*1024)
- pci_config_writeb(bdf, pam, 0x31);
- break;
- }
- pci_config_writeb(bdf, pam, 0x11);
- }
-
- // Write protect 0xf0000-0x100000
- pci_config_writeb(bdf, pam0, 0x10);
-}
-
-static int ShadowBDF = -1;
-
-// Make the 0xc0000-0x100000 area read/writable.
-void
-make_bios_writable(void)
-{
- if (!CONFIG_QEMU || runningOnXen())
- return;
-
- dprintf(3, "enabling shadow ram\n");
-
- // At this point, statically allocated variables can't be written,
- // so do this search manually.
- int bdf;
- foreachbdf(bdf, 0) {
- u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
- u16 vendor = vendev & 0xffff, device = vendev >> 16;
- if (vendor == PCI_VENDOR_ID_INTEL
- && device == PCI_DEVICE_ID_INTEL_82441) {
- make_bios_writable_intel(bdf, I440FX_PAM0);
- ShadowBDF = bdf;
- return;
- }
- if (vendor == PCI_VENDOR_ID_INTEL
- && device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
- make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0);
- ShadowBDF = bdf;
- return;
- }
- }
- dprintf(1, "Unable to unlock ram - bridge not found\n");
-}
-
-// Make the BIOS code segment area (0xf0000) read-only.
-void
-make_bios_readonly(void)
-{
- if (!CONFIG_QEMU || runningOnXen())
- return;
- dprintf(3, "locking shadow ram\n");
-
- if (ShadowBDF < 0) {
- dprintf(1, "Unable to lock ram - bridge not found\n");
- return;
- }
-
- u16 device = pci_config_readw(ShadowBDF, PCI_DEVICE_ID);
- if (device == PCI_DEVICE_ID_INTEL_82441)
- make_bios_readonly_intel(ShadowBDF, I440FX_PAM0);
- else
- make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0);
-}
-
-void
-qemu_prep_reset(void)
-{
- if (!CONFIG_QEMU || runningOnXen())
- return;
- // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
- // reset, so do that manually before invoking a hard reset.
- make_bios_writable();
- extern u8 code32flat_start[], code32flat_end[];
- memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
- , code32flat_end - code32flat_start);
-}
+++ /dev/null
-// smbios table generation (on emulators)
-//
-// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "paravirt.h" // RamSize
-#include "smbios.h" // struct smbios_entry_point
-
-struct smbios_entry_point *SMBiosAddr;
-
-static void
-smbios_entry_point_setup(u16 max_structure_size,
- u16 structure_table_length,
- void *structure_table_address,
- u16 number_of_structures)
-{
- struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep));
- void *finaltable;
- if (structure_table_length <= BUILD_MAX_SMBIOS_FSEG)
- // Table is small enough for f-seg - allocate there. This
- // works around a bug in JunOS (at least for small SMBIOS tables).
- finaltable = malloc_fseg(structure_table_length);
- else
- finaltable = malloc_high(structure_table_length);
- if (!ep || !finaltable) {
- warn_noalloc();
- free(ep);
- free(finaltable);
- return;
- }
- memcpy(finaltable, structure_table_address, structure_table_length);
-
- memcpy(ep->anchor_string, "_SM_", 4);
- ep->length = 0x1f;
- ep->smbios_major_version = 2;
- ep->smbios_minor_version = 4;
- ep->max_structure_size = max_structure_size;
- ep->entry_point_revision = 0;
- memset(ep->formatted_area, 0, 5);
- memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
-
- ep->structure_table_length = structure_table_length;
- ep->structure_table_address = (u32)finaltable;
- ep->number_of_structures = number_of_structures;
- ep->smbios_bcd_revision = 0x24;
-
- ep->checksum -= checksum(ep, 0x10);
-
- ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10);
-
- SMBiosAddr = ep;
- dprintf(1, "SMBIOS ptr=%p table=%p size=%d\n"
- , ep, finaltable, structure_table_length);
-}
-
-static int
-get_field(int type, int offset, void *dest)
-{
- char name[128];
- snprintf(name, sizeof(name), "smbios/field%d-%d", type, offset);
- struct romfile_s *file = romfile_find(name);
- if (!file)
- return 0;
- file->copy(file, dest, file->size);
- return file->size;
-}
-
-static int
-get_external(int type, char **p, unsigned *nr_structs,
- unsigned *max_struct_size, char *end)
-{
- static u64 used_bitmap[4] = { 0 };
- char *start = *p;
-
- /* Check if we've already reported these tables */
- if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
- return 1;
-
- /* Don't introduce spurious end markers */
- if (type == 127)
- return 0;
-
- char prefix[128];
- snprintf(prefix, sizeof(prefix), "smbios/table%d-", type);
- struct romfile_s *file = NULL;
- for (;;) {
- file = romfile_findprefix(prefix, file);
- if (!file)
- break;
-
- if (end - *p < file->size) {
- warn_noalloc();
- break;
- }
-
- struct smbios_structure_header *header = (void*)*p;
- file->copy(file, header, file->size);
- *p += file->size;
-
- /* Entries end with a double NULL char, if there's a string at
- * the end (length is greater than formatted length), the string
- * terminator provides the first NULL. */
- *((u8*)*p) = 0;
- (*p)++;
- if (header->length >= file->size) {
- *((u8*)*p) = 0;
- (*p)++;
- }
-
- (*nr_structs)++;
- if (*p - (char*)header > *max_struct_size)
- *max_struct_size = *p - (char*)header;
- }
-
- if (start == *p)
- return 0;
-
- /* Mark that we've reported on this type */
- used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
- return 1;
-}
-
-#define load_str_field_with_default(type, field, def) \
- do { \
- size = get_field(type, offsetof(struct smbios_type_##type, \
- field), end); \
- if (size > 0) { \
- end += size; \
- } else { \
- memcpy(end, def, sizeof(def)); \
- end += sizeof(def); \
- } \
- p->field = ++str_index; \
- } while (0)
-
-#define load_str_field_or_skip(type, field) \
- do { \
- size = get_field(type, offsetof(struct smbios_type_##type, \
- field), end); \
- if (size > 0) { \
- end += size; \
- p->field = ++str_index; \
- } else { \
- p->field = 0; \
- } \
- } while (0)
-
-#define set_field_with_default(type, field, def) \
- do { \
- if (!get_field(type, offsetof(struct smbios_type_##type, \
- field), &p->field)) { \
- p->field = def; \
- } \
- } while (0)
-
-/* Type 0 -- BIOS Information */
-#define RELEASE_DATE_STR "01/01/2011"
-static void *
-smbios_init_type_0(void *start)
-{
- struct smbios_type_0 *p = (struct smbios_type_0 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_0);
- size_t size;
- int str_index = 0;
-
- p->header.type = 0;
- p->header.length = sizeof(struct smbios_type_0);
- p->header.handle = 0;
-
- load_str_field_with_default(0, vendor_str, BUILD_APPNAME);
- load_str_field_with_default(0, bios_version_str, BUILD_APPNAME);
-
- p->bios_starting_address_segment = 0xe800;
-
- load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
-
- p->bios_rom_size = 0; /* FIXME */
-
- if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics),
- &p->bios_characteristics)) {
- memset(p->bios_characteristics, 0, 8);
- /* BIOS characteristics not supported */
- p->bios_characteristics[0] = 0x08;
- }
-
- if (!get_field(0, offsetof(struct smbios_type_0,
- bios_characteristics_extension_bytes),
- &p->bios_characteristics_extension_bytes)) {
- p->bios_characteristics_extension_bytes[0] = 0;
- /* Enable targeted content distribution. Needed for SVVP */
- p->bios_characteristics_extension_bytes[1] = 4;
- }
-
- set_field_with_default(0, system_bios_major_release, 1);
- set_field_with_default(0, system_bios_minor_release, 0);
- set_field_with_default(0, embedded_controller_major_release, 0xff);
- set_field_with_default(0, embedded_controller_minor_release, 0xff);
-
- *end = 0;
- end++;
-
- return end;
-}
-
-/* Type 1 -- System Information */
-static void *
-smbios_init_type_1(void *start)
-{
- struct smbios_type_1 *p = (struct smbios_type_1 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_1);
- size_t size;
- int str_index = 0;
-
- p->header.type = 1;
- p->header.length = sizeof(struct smbios_type_1);
- p->header.handle = 0x100;
-
- load_str_field_with_default(1, manufacturer_str, BUILD_APPNAME);
- load_str_field_with_default(1, product_name_str, BUILD_APPNAME);
- load_str_field_or_skip(1, version_str);
- load_str_field_or_skip(1, serial_number_str);
-
- if (!get_field(1, offsetof(struct smbios_type_1, uuid), &p->uuid))
- memset(p->uuid, 0, 16);
-
- set_field_with_default(1, wake_up_type, 0x06); /* power switch */
-
- load_str_field_or_skip(1, sku_number_str);
- load_str_field_or_skip(1, family_str);
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-/* Type 3 -- System Enclosure */
-static void *
-smbios_init_type_3(void *start)
-{
- struct smbios_type_3 *p = (struct smbios_type_3 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_3);
- size_t size;
- int str_index = 0;
-
- p->header.type = 3;
- p->header.length = sizeof(struct smbios_type_3);
- p->header.handle = 0x300;
-
- load_str_field_with_default(3, manufacturer_str, BUILD_APPNAME);
- set_field_with_default(3, type, 0x01); /* other */
-
- load_str_field_or_skip(3, version_str);
- load_str_field_or_skip(3, serial_number_str);
- load_str_field_or_skip(3, asset_tag_number_str);
-
- set_field_with_default(3, boot_up_state, 0x03); /* safe */
- set_field_with_default(3, power_supply_state, 0x03); /* safe */
- set_field_with_default(3, thermal_state, 0x03); /* safe */
- set_field_with_default(3, security_status, 0x02); /* unknown */
-
- set_field_with_default(3, oem_defined, 0);
- set_field_with_default(3, height, 0);
- set_field_with_default(3, number_of_power_cords, 0);
- set_field_with_default(3, contained_element_count, 0);
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-/* Type 4 -- Processor Information */
-static void *
-smbios_init_type_4(void *start, unsigned int cpu_number)
-{
- struct smbios_type_4 *p = (struct smbios_type_4 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_4);
- size_t size;
- int str_index = 0;
- char name[1024];
-
- p->header.type = 4;
- p->header.length = sizeof(struct smbios_type_4);
- p->header.handle = 0x400 + cpu_number;
-
- size = get_field(4, offsetof(struct smbios_type_4, socket_designation_str),
- name);
- if (size)
- snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number);
- else
- snprintf(name, sizeof(name), "CPU%2x", cpu_number);
-
- memcpy(end, name, strlen(name) + 1);
- end += strlen(name) + 1;
- p->socket_designation_str = ++str_index;
-
- set_field_with_default(4, processor_type, 0x03); /* CPU */
- set_field_with_default(4, processor_family, 0x01); /* other */
-
- load_str_field_with_default(4, processor_manufacturer_str, BUILD_APPNAME);
-
- if (!get_field(4, offsetof(struct smbios_type_4, processor_id)
- , p->processor_id)) {
- u32 cpuid_signature, ebx, ecx, cpuid_features;
- cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
- p->processor_id[0] = cpuid_signature;
- p->processor_id[1] = cpuid_features;
- }
-
- load_str_field_or_skip(4, processor_version_str);
- set_field_with_default(4, voltage, 0);
- set_field_with_default(4, external_clock, 0);
-
- set_field_with_default(4, max_speed, 2000);
- set_field_with_default(4, current_speed, 2000);
-
- set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */
- set_field_with_default(4, processor_upgrade, 0x01); /* other */
-
- /* cache information structure not provided */
- p->l1_cache_handle = 0xffff;
- p->l2_cache_handle = 0xffff;
- p->l3_cache_handle = 0xffff;
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-/* Type 16 -- Physical Memory Array */
-static void *
-smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
-{
- struct smbios_type_16 *p = (struct smbios_type_16*)start;
-
- p->header.type = 16;
- p->header.length = sizeof(struct smbios_type_16);
- p->header.handle = 0x1000;
-
- set_field_with_default(16, location, 0x01); /* other */
- set_field_with_default(16, use, 0x03); /* system memory */
- /* Multi-bit ECC to make Microsoft happy */
- set_field_with_default(16, error_correction, 0x06);
- /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */
- p->maximum_capacity = memory_size_mb < 2 << 20 ?
- memory_size_mb << 10 : 0x80000000;
- p->memory_error_information_handle = 0xfffe; /* none provided */
- p->number_of_memory_devices = nr_mem_devs;
-
- start += sizeof(struct smbios_type_16);
- *((u16 *)start) = 0;
-
- return start + 2;
-}
-
-/* Type 17 -- Memory Device */
-static void *
-smbios_init_type_17(void *start, u32 size_mb, int instance)
-{
- struct smbios_type_17 *p = (struct smbios_type_17 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_17);
- size_t size;
- int str_index = 0;
- char name[1024];
-
- p->header.type = 17;
- p->header.length = sizeof(struct smbios_type_17);
- p->header.handle = 0x1100 + instance;
-
- p->physical_memory_array_handle = 0x1000;
- set_field_with_default(17, total_width, 64);
- set_field_with_default(17, data_width, 64);
-/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
- p->size = size_mb;
- set_field_with_default(17, form_factor, 0x09); /* DIMM */
- p->device_set = 0;
-
- size = get_field(17, offsetof(struct smbios_type_17, device_locator_str),
- name);
- if (size)
- snprintf(name + size - 1, sizeof(name) - size, "%d", instance);
- else
- snprintf(name, sizeof(name), "DIMM %d", instance);
-
- memcpy(end, name, strlen(name) + 1);
- end += strlen(name) + 1;
- p->device_locator_str = ++str_index;
-
- load_str_field_or_skip(17, bank_locator_str);
- set_field_with_default(17, memory_type, 0x07); /* RAM */
- set_field_with_default(17, type_detail, 0);
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-/* Type 19 -- Memory Array Mapped Address */
-static void *
-smbios_init_type_19(void *start, u32 start_mb, u32 size_mb, int instance)
-{
- struct smbios_type_19 *p = (struct smbios_type_19 *)start;
-
- p->header.type = 19;
- p->header.length = sizeof(struct smbios_type_19);
- p->header.handle = 0x1300 + instance;
-
- p->starting_address = start_mb << 10;
- p->ending_address = p->starting_address + (size_mb << 10) - 1;
- p->memory_array_handle = 0x1000;
- p->partition_width = 1;
-
- start += sizeof(struct smbios_type_19);
- *((u16 *)start) = 0;
-
- return start + 2;
-}
-
-/* Type 20 -- Memory Device Mapped Address */
-static void *
-smbios_init_type_20(void *start, u32 start_mb, u32 size_mb, int instance,
- int dev_handle, int array_handle)
-{
- struct smbios_type_20 *p = (struct smbios_type_20 *)start;
-
- p->header.type = 20;
- p->header.length = sizeof(struct smbios_type_20);
- p->header.handle = 0x1400 + instance;
-
- p->starting_address = start_mb << 10;
- p->ending_address = p->starting_address + (size_mb << 10) - 1;
- p->memory_device_handle = 0x1100 + dev_handle;
- p->memory_array_mapped_address_handle = 0x1300 + array_handle;
- p->partition_row_position = 1;
- p->interleave_position = 0;
- p->interleaved_data_depth = 0;
-
- start += sizeof(struct smbios_type_20);
-
- *((u16 *)start) = 0;
- return start+2;
-}
-
-/* Type 32 -- System Boot Information */
-static void *
-smbios_init_type_32(void *start)
-{
- struct smbios_type_32 *p = (struct smbios_type_32 *)start;
-
- p->header.type = 32;
- p->header.length = sizeof(struct smbios_type_32);
- p->header.handle = 0x2000;
- memset(p->reserved, 0, 6);
- set_field_with_default(32, boot_status, 0); /* no errors detected */
-
- start += sizeof(struct smbios_type_32);
- *((u16 *)start) = 0;
-
- return start+2;
-}
-
-/* Type 127 -- End of Table */
-static void *
-smbios_init_type_127(void *start)
-{
- struct smbios_type_127 *p = (struct smbios_type_127 *)start;
-
- p->header.type = 127;
- p->header.length = sizeof(struct smbios_type_127);
- p->header.handle = 0x7f00;
-
- start += sizeof(struct smbios_type_127);
- *((u16 *)start) = 0;
-
- return start + 2;
-}
-
-#define TEMPSMBIOSSIZE (32 * 1024)
-
-void
-smbios_setup(void)
-{
- if (! CONFIG_SMBIOS)
- return;
-
- dprintf(3, "init SMBIOS tables\n");
-
- char *start = malloc_tmphigh(TEMPSMBIOSSIZE);
- if (! start) {
- warn_noalloc();
- return;
- }
-
- u32 nr_structs = 0, max_struct_size = 0;
- char *q, *p = start;
- char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127);
-
-#define add_struct(type, args...) \
- do { \
- if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \
- q = smbios_init_type_##type(args); \
- nr_structs++; \
- if ((q - p) > max_struct_size) \
- max_struct_size = q - p; \
- p = q; \
- } \
- } while (0)
-
- add_struct(0, p);
- add_struct(1, p);
- add_struct(3, p);
-
- int cpu_num;
- for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
- add_struct(4, p, cpu_num);
-
- int ram_mb = (RamSize + RamSizeOver4G) >> 20;
- int nr_mem_devs = (ram_mb + 0x3fff) >> 14;
- add_struct(16, p, ram_mb, nr_mem_devs);
-
- int i, j;
- for (i = 0; i < nr_mem_devs; i++) {
- u32 dev_mb = ((i == (nr_mem_devs - 1))
- ? (((ram_mb - 1) & 0x3fff) + 1)
- : 16384);
- add_struct(17, p, dev_mb, i);
- }
-
- add_struct(19, p, 0, RamSize >> 20, 0);
- if (RamSizeOver4G)
- add_struct(19, p, 4096, RamSizeOver4G >> 20, 1);
-
- add_struct(20, p, 0, RamSize >> 20, 0, 0, 0);
- if (RamSizeOver4G) {
- u32 start_mb = 4096;
- for (j = 1, i = 0; i < nr_mem_devs; i++, j++) {
- u32 dev_mb = ((i == (nr_mem_devs - 1))
- ? (((ram_mb - 1) & 0x3fff) + 1)
- : 16384);
- if (i == 0)
- dev_mb -= RamSize >> 20;
-
- add_struct(20, p, start_mb, dev_mb, j, i, 1);
- start_mb += dev_mb;
- }
- }
-
- add_struct(32, p);
- /* Add any remaining provided entries before the end marker */
- for (i = 0; i < 256; i++)
- get_external(i, &p, &nr_structs, &max_struct_size, end);
- add_struct(127, p);
-
-#undef add_struct
-
- smbios_entry_point_setup(max_struct_size, p - start, start, nr_structs);
- free(start);
-}
-
-void
-display_uuid(void)
-{
- u32 addr, end;
- u8 *uuid;
- u8 empty_uuid[16] = { 0 };
-
- if (SMBiosAddr == NULL)
- return;
-
- addr = SMBiosAddr->structure_table_address;
- end = addr + SMBiosAddr->structure_table_length;
-
- /* the following takes care of any initial wraparound too */
- while (addr < end) {
- const struct smbios_structure_header *hdr;
-
- /* partial structure header */
- if (end - addr < sizeof(struct smbios_structure_header))
- return;
-
- hdr = (struct smbios_structure_header *)addr;
-
- /* partial structure */
- if (end - addr < hdr->length)
- return;
-
- /* any Type 1 structure version will do that has the UUID */
- if (hdr->type == 1 &&
- hdr->length >= offsetof(struct smbios_type_1, uuid) + 16)
- break;
-
- /* done with formatted area, skip string-set */
- addr += hdr->length;
-
- while (end - addr >= 2 &&
- (*(u8 *)addr != '\0' ||
- *(u8 *)(addr+1) != '\0'))
- ++addr;
-
- /* structure terminator not found */
- if (end - addr < 2)
- return;
-
- addr += 2;
- }
-
- /* parsing finished or skipped entirely, UUID not found */
- if (addr >= end)
- return;
-
- uuid = (u8 *)(addr + offsetof(struct smbios_type_1, uuid));
- if (memcmp(uuid, empty_uuid, sizeof empty_uuid) == 0)
- return;
-
- printf("Machine UUID"
- " %02x%02x%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x%02x%02x%02x%02x\n"
- , uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3]
- , uuid[ 4], uuid[ 5]
- , uuid[ 6], uuid[ 7]
- , uuid[ 8], uuid[ 9]
- , uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
-}
+++ /dev/null
-#ifndef __SMBIOS_H
-#define __SMBIOS_H
-
-// smbios.c
-void smbios_setup(void);
-
-/* SMBIOS entry point -- must be written to a 16-bit aligned address
- between 0xf0000 and 0xfffff.
- */
-struct smbios_entry_point {
- char anchor_string[4];
- u8 checksum;
- u8 length;
- u8 smbios_major_version;
- u8 smbios_minor_version;
- u16 max_structure_size;
- u8 entry_point_revision;
- u8 formatted_area[5];
- char intermediate_anchor_string[5];
- u8 intermediate_checksum;
- u16 structure_table_length;
- u32 structure_table_address;
- u16 number_of_structures;
- u8 smbios_bcd_revision;
-} PACKED;
-
-extern struct smbios_entry_point *SMBiosAddr;
-
-/* This goes at the beginning of every SMBIOS structure. */
-struct smbios_structure_header {
- u8 type;
- u8 length;
- u16 handle;
-} PACKED;
-
-/* SMBIOS type 0 - BIOS Information */
-struct smbios_type_0 {
- struct smbios_structure_header header;
- u8 vendor_str;
- u8 bios_version_str;
- u16 bios_starting_address_segment;
- u8 bios_release_date_str;
- u8 bios_rom_size;
- u8 bios_characteristics[8];
- u8 bios_characteristics_extension_bytes[2];
- u8 system_bios_major_release;
- u8 system_bios_minor_release;
- u8 embedded_controller_major_release;
- u8 embedded_controller_minor_release;
-} PACKED;
-
-/* SMBIOS type 1 - System Information */
-struct smbios_type_1 {
- struct smbios_structure_header header;
- u8 manufacturer_str;
- u8 product_name_str;
- u8 version_str;
- u8 serial_number_str;
- u8 uuid[16];
- u8 wake_up_type;
- u8 sku_number_str;
- u8 family_str;
-} PACKED;
-
-/* SMBIOS type 3 - System Enclosure (v2.3) */
-struct smbios_type_3 {
- struct smbios_structure_header header;
- u8 manufacturer_str;
- u8 type;
- u8 version_str;
- u8 serial_number_str;
- u8 asset_tag_number_str;
- u8 boot_up_state;
- u8 power_supply_state;
- u8 thermal_state;
- u8 security_status;
- u32 oem_defined;
- u8 height;
- u8 number_of_power_cords;
- u8 contained_element_count;
- // contained elements follow
-} PACKED;
-
-/* SMBIOS type 4 - Processor Information (v2.0) */
-struct smbios_type_4 {
- struct smbios_structure_header header;
- u8 socket_designation_str;
- u8 processor_type;
- u8 processor_family;
- u8 processor_manufacturer_str;
- u32 processor_id[2];
- u8 processor_version_str;
- u8 voltage;
- u16 external_clock;
- u16 max_speed;
- u16 current_speed;
- u8 status;
- u8 processor_upgrade;
- u16 l1_cache_handle;
- u16 l2_cache_handle;
- u16 l3_cache_handle;
-} PACKED;
-
-/* SMBIOS type 16 - Physical Memory Array
- * Associated with one type 17 (Memory Device).
- */
-struct smbios_type_16 {
- struct smbios_structure_header header;
- u8 location;
- u8 use;
- u8 error_correction;
- u32 maximum_capacity;
- u16 memory_error_information_handle;
- u16 number_of_memory_devices;
-} PACKED;
-
-/* SMBIOS type 17 - Memory Device
- * Associated with one type 19
- */
-struct smbios_type_17 {
- struct smbios_structure_header header;
- u16 physical_memory_array_handle;
- u16 memory_error_information_handle;
- u16 total_width;
- u16 data_width;
- u16 size;
- u8 form_factor;
- u8 device_set;
- u8 device_locator_str;
- u8 bank_locator_str;
- u8 memory_type;
- u16 type_detail;
-} PACKED;
-
-/* SMBIOS type 19 - Memory Array Mapped Address */
-struct smbios_type_19 {
- struct smbios_structure_header header;
- u32 starting_address;
- u32 ending_address;
- u16 memory_array_handle;
- u8 partition_width;
-} PACKED;
-
-/* SMBIOS type 20 - Memory Device Mapped Address */
-struct smbios_type_20 {
- struct smbios_structure_header header;
- u32 starting_address;
- u32 ending_address;
- u16 memory_device_handle;
- u16 memory_array_mapped_address_handle;
- u8 partition_row_position;
- u8 interleave_position;
- u8 interleaved_data_depth;
-} PACKED;
-
-/* SMBIOS type 32 - System Boot Information */
-struct smbios_type_32 {
- struct smbios_structure_header header;
- u8 reserved[6];
- u8 boot_status;
-} PACKED;
-
-/* SMBIOS type 127 -- End-of-table */
-struct smbios_type_127 {
- struct smbios_structure_header header;
-} PACKED;
-
-void display_uuid(void);
-#endif // smbios.h
+++ /dev/null
-// System Management Mode support (on emulators)
-//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "hw/pci.h" // pci_config_writel
-#include "hw/pci_regs.h" // PCI_DEVICE_ID
-#include "util.h" // wbinvd
-#include "config.h" // CONFIG_*
-#include "ioport.h" // outb
-#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "dev-q35.h"
-
-extern u8 smm_relocation_start, smm_relocation_end;
-ASM32FLAT(
- ".global smm_relocation_start, smm_relocation_end\n"
- " .code16gcc\n"
-
- /* code to relocate SMBASE to 0xa0000 */
- "smm_relocation_start:\n"
- " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n"
- " addr32 movb (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */
- " cmpb $0x64, %al\n"
- " je 1f\n"
- " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n"
- " jmp 2f\n"
- "1:\n"
- " movl $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n"
- "2:\n"
- " movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n"
- " addr32 movl %eax, (%ebx)\n"
- /* indicate to the BIOS that the SMM code was executed */
- " movb $0x00, %al\n"
- " movw $" __stringify(PORT_SMI_STATUS) ", %dx\n"
- " outb %al, %dx\n"
- " rsm\n"
- "smm_relocation_end:\n"
- " .code32\n"
- );
-
-extern u8 smm_code_start, smm_code_end;
-ASM32FLAT(
- /* minimal SMM code to enable or disable ACPI */
- ".global smm_code_start, smm_code_end\n"
- " .code16gcc\n"
- "smm_code_start:\n"
- " movw $" __stringify(PORT_SMI_CMD) ", %dx\n"
- " inb %dx, %al\n"
- " cmpb $0xf0, %al\n"
- " jne 1f\n"
-
- /* ACPI disable */
- " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
- " inw %dx, %ax\n"
- " andw $~1, %ax\n"
- " outw %ax, %dx\n"
-
- " jmp 2f\n"
-
- "1:\n"
- " cmpb $0xf1, %al\n"
- " jne 2f\n"
-
- /* ACPI enable */
- " movw $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
- " inw %dx, %ax\n"
- " orw $1, %ax\n"
- " outw %ax, %dx\n"
-
- "2:\n"
- " rsm\n"
- "smm_code_end:\n"
- " .code32\n"
- );
-
-static void
-smm_save_and_copy(void)
-{
- /* save original memory content */
- memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
-
- /* copy the SMM relocation code */
- memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
- &smm_relocation_end - &smm_relocation_start);
-}
-
-static void
-smm_relocate_and_restore(void)
-{
- /* init APM status port */
- outb(0x01, PORT_SMI_STATUS);
-
- /* raise an SMI interrupt */
- outb(0x00, PORT_SMI_CMD);
-
- /* wait until SMM code executed */
- while (inb(PORT_SMI_STATUS) != 0x00)
- ;
-
- /* restore original memory content */
- memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);
-
- /* copy the SMM code */
- memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
- , &smm_code_end - &smm_code_start);
- wbinvd();
-}
-
-#define I440FX_SMRAM 0x72
-#define PIIX_DEVACTB 0x58
-#define PIIX_APMC_EN (1 << 25)
-
-// This code is hardcoded for PIIX4 Power Management device.
-static void piix4_apmc_smm_setup(int isabdf, int i440_bdf)
-{
- /* check if SMM init is already done */
- u32 value = pci_config_readl(isabdf, PIIX_DEVACTB);
- if (value & PIIX_APMC_EN)
- return;
-
- /* enable the SMM memory window */
- pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48);
-
- smm_save_and_copy();
-
- /* enable SMI generation when writing to the APMC register */
- pci_config_writel(isabdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
-
- smm_relocate_and_restore();
-
- /* close the SMM memory window and enable normal SMM */
- pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08);
-}
-
-/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
-void ich9_lpc_apmc_smm_setup(int isabdf, int mch_bdf)
-{
- /* check if SMM init is already done */
- u32 value = inl(PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN);
- if (value & ICH9_PMIO_SMI_EN_APMC_EN)
- return;
-
- /* enable the SMM memory window */
- pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x48);
-
- smm_save_and_copy();
-
- /* enable SMI generation when writing to the APMC register */
- outl(value | ICH9_PMIO_SMI_EN_APMC_EN,
- PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN);
-
- smm_relocate_and_restore();
-
- /* close the SMM memory window and enable normal SMM */
- pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x08);
-}
-
-static int SMMISADeviceBDF = -1, SMMPMDeviceBDF = -1;
-
-void
-smm_device_setup(void)
-{
- if (!CONFIG_USE_SMM)
- return;
-
- struct pci_device *isapci, *pmpci;
- isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3);
- pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
- if (isapci && pmpci) {
- SMMISADeviceBDF = isapci->bdf;
- SMMPMDeviceBDF = pmpci->bdf;
- return;
- }
- isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC);
- pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH);
- if (isapci && pmpci) {
- SMMISADeviceBDF = isapci->bdf;
- SMMPMDeviceBDF = pmpci->bdf;
- }
-}
-
-void
-smm_setup(void)
-{
- if (!CONFIG_USE_SMM || SMMISADeviceBDF < 0)
- return;
-
- dprintf(3, "init smm\n");
- u16 device = pci_config_readw(SMMISADeviceBDF, PCI_DEVICE_ID);
- if (device == PCI_DEVICE_ID_INTEL_82371AB_3)
- piix4_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
- else
- ich9_lpc_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
-}
+++ /dev/null
-// CPU count detection
-//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "hw/cmos.h" // CMOS_BIOS_SMP_COUNT
-
-#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
-#define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0)
-#define APIC_LINT0 ((u8*)BUILD_APIC_ADDR + 0x350)
-#define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360)
-
-#define APIC_ENABLED 0x0100
-
-struct { u32 ecx, eax, edx; } smp_mtrr[32] VARFSEG;
-u32 smp_mtrr_count VARFSEG;
-
-void
-wrmsr_smp(u32 index, u64 val)
-{
- wrmsr(index, val);
- if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr)) {
- warn_noalloc();
- return;
- }
- smp_mtrr[smp_mtrr_count].ecx = index;
- smp_mtrr[smp_mtrr_count].eax = val;
- smp_mtrr[smp_mtrr_count].edx = val >> 32;
- smp_mtrr_count++;
-}
-
-u32 CountCPUs VARFSEG;
-u32 MaxCountCPUs;
-// 256 bits for the found APIC IDs
-u32 FoundAPICIDs[256/32] VARFSEG;
-extern void smp_ap_boot_code(void);
-ASM16(
- " .global smp_ap_boot_code\n"
- "smp_ap_boot_code:\n"
-
- // Setup data segment
- " movw $" __stringify(SEG_BIOS) ", %ax\n"
- " movw %ax, %ds\n"
-
- // MTRR setup
- " movl $smp_mtrr, %esi\n"
- " movl smp_mtrr_count, %ebx\n"
- "1:testl %ebx, %ebx\n"
- " jz 2f\n"
- " movl 0(%esi), %ecx\n"
- " movl 4(%esi), %eax\n"
- " movl 8(%esi), %edx\n"
- " wrmsr\n"
- " addl $12, %esi\n"
- " decl %ebx\n"
- " jmp 1b\n"
- "2:\n"
-
- // get apic ID on EBX, set bit on FoundAPICIDs
- " movl $1, %eax\n"
- " cpuid\n"
- " shrl $24, %ebx\n"
- " lock btsl %ebx, FoundAPICIDs\n"
-
- // Increment the cpu counter
- " lock incl CountCPUs\n"
-
- // Halt the processor.
- "1:hlt\n"
- " jmp 1b\n"
- );
-
-int apic_id_is_present(u8 apic_id)
-{
- return !!(FoundAPICIDs[apic_id/32] & (1ul << (apic_id % 32)));
-}
-
-// find and initialize the CPUs by launching a SIPI to them
-void
-smp_setup(void)
-{
- if (!CONFIG_QEMU)
- return;
-
- ASSERT32FLAT();
- u32 eax, ebx, ecx, cpuid_features;
- cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
- if (eax < 1 || !(cpuid_features & CPUID_APIC)) {
- // No apic - only the main cpu is present.
- dprintf(1, "No apic - only the main cpu is present.\n");
- CountCPUs= 1;
- MaxCountCPUs = 1;
- return;
- }
-
- // mark the BSP initial APIC ID as found, too:
- u8 apic_id = ebx>>24;
- FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32));
-
- // Init the counter.
- writel(&CountCPUs, 1);
-
- // Setup jump trampoline to counter code.
- u64 old = *(u64*)BUILD_AP_BOOT_ADDR;
- // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR)
- u64 new = (0xea | ((u64)SEG_BIOS<<24)
- | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8));
- *(u64*)BUILD_AP_BOOT_ADDR = new;
-
- // enable local APIC
- u32 val = readl(APIC_SVR);
- writel(APIC_SVR, val | APIC_ENABLED);
-
- /* Set LINT0 as Ext_INT, level triggered */
- writel(APIC_LINT0, 0x8700);
-
- /* Set LINT1 as NMI, level triggered */
- writel(APIC_LINT1, 0x8400);
-
- // broadcast SIPI
- barrier();
- writel(APIC_ICR_LOW, 0x000C4500);
- u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
- writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
-
- // Wait for other CPUs to process the SIPI.
- u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
- while (cmos_smp_count + 1 != readl(&CountCPUs))
- yield();
-
- // Restore memory.
- *(u64*)BUILD_AP_BOOT_ADDR = old;
-
- MaxCountCPUs = romfile_loadint("etc/max-cpus", 0);
- if (!MaxCountCPUs || MaxCountCPUs < CountCPUs)
- MaxCountCPUs = CountCPUs;
-
- dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", readl(&CountCPUs),
- MaxCountCPUs);
-}
+++ /dev/null
-ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
-
-DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
-{
-
-/****************************************************************
- * PCI memory ranges
- ****************************************************************/
-
- Scope(\) {
- ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
- Name(P0S, 0x12345678)
- ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
- Name(P0E, 0x12345678)
- ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
- Name(P1V, 0x12)
- ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
- Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
- ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
- Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
- ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
- Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
- }
-
-
-/****************************************************************
- * Suspend
- ****************************************************************/
-
- Scope(\) {
- /*
- * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
- * must match piix4 emulation.
- */
-
- ACPI_EXTRACT_NAME_STRING acpi_s3_name
- Name(_S3, Package(0x04) {
- One, /* PM1a_CNT.SLP_TYP */
- One, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- ACPI_EXTRACT_NAME_STRING acpi_s4_name
- ACPI_EXTRACT_PKG_START acpi_s4_pkg
- Name(_S4, Package(0x04) {
- 0x2, /* PM1a_CNT.SLP_TYP */
- 0x2, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name(_S5, Package(0x04) {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- }
-
- External(\_SB.PCI0, DeviceObj)
- External(\_SB.PCI0.ISA, DeviceObj)
-
- Scope(\_SB.PCI0.ISA) {
- Device(PEVT) {
- Name(_HID, "QEMU0001")
- /* PEST will be patched to be Zero if no such device */
- ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
- Name(PEST, 0xFFFF)
- OperationRegion(PEOR, SystemIO, PEST, 0x01)
- Field(PEOR, ByteAcc, NoLock, Preserve) {
- PEPT, 8,
- }
-
- Method(_STA, 0, NotSerialized) {
- Store(PEST, Local0)
- If (LEqual(Local0, Zero)) {
- Return (0x00)
- } Else {
- Return (0x0F)
- }
- }
-
- Method(RDPT, 0, NotSerialized) {
- Store(PEPT, Local0)
- Return (Local0)
- }
-
- Method(WRPT, 1, NotSerialized) {
- Store(Arg0, PEPT)
- }
-
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
- })
-
- CreateWordField(_CRS, IO._MIN, IOMN)
- CreateWordField(_CRS, IO._MAX, IOMX)
-
- Method(_INI, 0, NotSerialized) {
- Store(PEST, IOMN)
- Store(PEST, IOMX)
- }
- }
- }
-}
+++ /dev/null
-ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
-
-DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
-{
-
-/****************************************************************
- * PCI hotplug
- ****************************************************************/
-
- /* Objects supplied by DSDT */
- External(\_SB.PCI0, DeviceObj)
- External(\_SB.PCI0.PCEJ, MethodObj)
-
- Scope(\_SB.PCI0) {
-
- /* Bulk generated PCI hotplug devices */
- ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
- ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
- ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
-
- // Method _EJ0 can be patched by BIOS to EJ0_
- // at runtime, if the slot is detected to not support hotplug.
- // Extract the offset of the address dword and the
- // _EJ0 name to allow this patching.
- Device(SAA) {
- ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
- Name(_SUN, 0xAA)
- ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
- Name(_ADR, 0xAA0000)
- ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
- Method(_EJ0, 1) {
- Return (PCEJ(_SUN))
- }
- }
- }
-}
+++ /dev/null
-/* This file is the basis for the ssdt table generated in src/acpi.c.
- * It defines the contents of the per-cpu Processor() object. At
- * runtime, a dynamically generated SSDT will contain one copy of this
- * AML snippet for every possible cpu in the system. The objects will
- * be placed in the \_SB_ namespace.
- *
- * In addition to the aml code generated from this file, the
- * src/acpi.c file creates a NTFY method with an entry for each cpu:
- * Method(NTFY, 2) {
- * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
- * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
- * ...
- * }
- * and a CPON array with the list of active and inactive cpus:
- * Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
- */
-
-ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
-
-DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
-{
- ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
- ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
- ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
- Processor(CPAA, 0xAA, 0x0000b010, 0x06) {
- ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
- Name(ID, 0xAA)
-/*
- * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
- * CPAA and 0xAA with the appropriate CPU id (see
- * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without
- * also updating the C code.
- */
- Name(_HID, "ACPI0007")
- External(CPMA, MethodObj)
- External(CPST, MethodObj)
- External(CPEJ, MethodObj)
- Method(_MAT, 0) {
- Return (CPMA(ID))
- }
- Method(_STA, 0) {
- Return (CPST(ID))
- }
- Method(_EJ0, 1, NotSerialized) {
- CPEJ(ID, Arg0)
- }
- }
-}
void handle_1ab1(struct bregs *regs);
void bios32_init(void);
-// shadow.c
+// fw/shadow.c
void make_bios_writable(void);
void make_bios_readonly(void);
void qemu_prep_reset(void);
-// pciinit.c
+// fw/pciinit.c
extern const u8 pci_irqs[4];
void pci_setup(void);
-// smm.c
+// fw/smm.c
void smm_device_setup(void);
void smm_setup(void);
-// smp.c
+// fw/smp.c
extern u32 CountCPUs;
extern u32 MaxCountCPUs;
void wrmsr_smp(u32 index, u64 val);
void smp_setup(void);
int apic_id_is_present(u8 apic_id);
-// coreboot.c
+// fw/coreboot.c
extern const char *CBvendor, *CBpart;
struct cbfs_file;
void debug_cbmem(char c);
void coreboot_preinit(void);
void coreboot_cbfs_init(void);
-// biostable.c
+// fw/biostable.c
void copy_smbios(void *pos);
void copy_table(void *pos);
pmm_free(data);
}
-// mtrr.c
+// fw/mtrr.c
void mtrr_setup(void);
// romfile.c
+++ /dev/null
-// Xen HVM support
-//
-// Copyright (C) 2011 Citrix Systems.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h"
-#include "xen.h"
-#include "paravirt.h" // PlatformRunningOn
-#include "memmap.h" // add_e820
-#include "types.h" // ASM32FLAT
-#include "util.h" // copy_acpi_rsdp
-#include "acpi.h" // find_acpi_features
-
-#define INFO_PHYSICAL_ADDRESS 0x00001000
-
-u32 xen_cpuid_base = 0;
-unsigned long xen_hypercall_page = 0;
-
-struct xen_seabios_info {
- char signature[14]; /* XenHVMSeaBIOS\0 */
- u8 length; /* Length of this struct */
- u8 checksum; /* Set such that the sum over bytes 0..length == 0 */
- /*
- * Physical address of an array of tables_nr elements.
- *
- * Each element is a 32 bit value contianing the physical address
- * of a BIOS table.
- */
- u32 tables;
- u32 tables_nr;
- /*
- * Physical address of the e820 table, contains e820_nr entries.
- */
- u32 e820;
- u32 e820_nr;
-} PACKED;
-
-static void validate_info(struct xen_seabios_info *t)
-{
- if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) )
- panic("Bad Xen info signature\n");
-
- if ( t->length < sizeof(struct xen_seabios_info) )
- panic("Bad Xen info length\n");
-
- if (checksum(t, t->length) != 0)
- panic("Bad Xen info checksum\n");
-}
-
-void xen_preinit(void)
-{
- u32 base, eax, ebx, ecx, edx;
- char signature[13];
-
- if (!CONFIG_XEN)
- return;
-
- for (base = 0x40000000; base < 0x40010000; base += 0x100) {
- cpuid(base, &eax, &ebx, &ecx, &edx);
- memcpy(signature + 0, &ebx, 4);
- memcpy(signature + 4, &ecx, 4);
- memcpy(signature + 8, &edx, 4);
- signature[12] = 0;
-
- dprintf(9, "Found hypervisor signature \"%s\" at %x\n",
- signature, base);
- if (strcmp(signature, "XenVMMXenVMM") == 0) {
- /* Set debug_io_port first, so the following messages work. */
- DebugOutputPort = 0xe9;
- dprintf(1, "SeaBIOS (version %s)\n\n", VERSION);
- dprintf(1, "Found Xen hypervisor signature at %x\n", base);
- if ((eax - base) < 2)
- panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
- eax, base);
- xen_cpuid_base = base;
- break;
- }
- }
- if (!xen_cpuid_base) {
- dprintf(1, "No Xen hypervisor found.\n");
- return;
- }
- PlatformRunningOn = PF_QEMU|PF_XEN;
-}
-
-static int hypercall_xen_version( int cmd, void *arg)
-{
- return _hypercall2(int, xen_version, cmd, arg);
-}
-
-/* Fill in hypercall transfer pages. */
-void xen_hypercall_setup(void)
-{
- u32 eax, ebx, ecx, edx;
- xen_extraversion_t extraversion;
- unsigned long i;
-
- if (!runningOnXen())
- return;
-
- cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
-
- xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE);
- if (!xen_hypercall_page)
- panic("unable to allocate Xen hypercall page\n");
-
- dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page);
- for ( i = 0; i < eax; i++ )
- wrmsr(ebx, xen_hypercall_page + (i << 12) + i);
-
- /* Print version information. */
- cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
- hypercall_xen_version(XENVER_extraversion, extraversion);
- dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
-}
-
-void xen_biostable_setup(void)
-{
- struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
- void **tables = (void*)info->tables;
- int i;
-
- dprintf(1, "xen: copy BIOS tables...\n");
- for (i=0; i<info->tables_nr; i++)
- copy_table(tables[i]);
-
- find_acpi_features();
-}
-
-void xen_ramsize_preinit(void)
-{
- int i;
- struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
- struct e820entry *e820 = (struct e820entry *)info->e820;
- validate_info(info);
-
- dprintf(1, "xen: copy e820...\n");
-
- for (i = 0; i < info->e820_nr; i++) {
- struct e820entry *e = &e820[i];
- add_e820(e->start, e->size, e->type);
- }
-}
+++ /dev/null
-#ifndef __XEN_H
-#define __XEN_H
-
-void xen_preinit(void);
-void xen_ramsize_preinit(void);
-void xen_hypercall_setup(void);
-void xen_biostable_setup(void);
-
-extern unsigned long xen_hypercall_page;
-
-#define _hypercall0(type, name) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res) \
- : "0" (__hentry) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall1(type, name, a1) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res, __ign1; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res), "=b" (__ign1) \
- : "0" (__hentry), "1" ((long)(a1)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall2(type, name, a1, a2) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res, __ign1, __ign2; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
- : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall3(type, name, a1, a2, a3) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res, __ign1, __ign2, __ign3; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3) \
- : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall4(type, name, a1, a2, a3, a4) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res, __ign1, __ign2, __ign3, __ign4; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3), "=S" (__ign4) \
- : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "4" ((long)(a4)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
-({ \
- unsigned long __hentry = xen_hypercall_page+__HYPERVISOR_##name*32; \
- long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
- asm volatile ( \
- "call *%%eax" \
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
- : "0" (__hentry), "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "4" ((long)(a4)), \
- "5" ((long)(a5)) \
- : "memory" ); \
- (type)__res; \
-})
-
-/******************************************************************************
- *
- * The following interface definitions are taken from Xen and have the
- * following license:
- *
- * 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.
- */
-
-/* xen.h */
-
-#define __HYPERVISOR_xen_version 17
-
-/* version.h */
-
-/* arg == xen_extraversion_t. */
-#define XENVER_extraversion 1
-typedef char xen_extraversion_t[16];
-#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
-
-#endif