/** Configure RootPort for downstream PCIe NAND devices. @param[in] RpBase - PCIe configuration space address of this RootPort @param[in] BusNumber - Bus number @param[in] MemoryBase - Memory base address @param[in] MemoryLength - Memory size **/ VOID ConfigureRootPortForPcieNand ( IN UINTN RpBase, IN UINTN BusNumber, IN UINT32 MemoryBase, IN UINT32 MemoryLength ) { UINT32 MemoryLimit; DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n", BusNumber, MemoryBase, MemoryLength)); if (MemoryLength == 0) { MemoryLimit = MemoryBase; } else { MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M } /// /// Configue PCIE configuration space for RootPort /// PciWrite8 (RpBase + NVME_PCIE_BNUM + 1, (UINT8) BusNumber); // Secondary Bus Number registers PciWrite8 (RpBase + NVME_PCIE_BNUM + 2, (UINT8) BusNumber); // Subordinate Bus Number registers PciWrite8 (RpBase + NVME_PCIE_IOBL, 0xFF); // I/O Base registers PciWrite8 (RpBase + NVME_PCIE_IOBL + 1, 0x00); // I/O Limit registers PciWrite16 (RpBase + NVME_PCIE_MBL, (UINT16) RShiftU64 ((UINTN)MemoryBase, 16)); // Memory Base register PciWrite16 (RpBase + NVME_PCIE_MBL + 2, (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register PciWrite16 (RpBase + NVME_PCIE_PMBL, 0xFFFF); // Prefetchable Memory Base registers PciWrite16 (RpBase + NVME_PCIE_PMBL + 2, 0x0000); // Prefetchable Memory Limit registers PciWrite32 (RpBase + NVME_PCIE_PMBU32, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers PciWrite32 (RpBase + NVME_PCIE_PMLU32, 0x00000000); // Prefetchable Memory Upper Limit registers }
ACPI_STATUS AcpiOsWritePciConfiguration ( ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width) { UINT32 devfn = ((PciId->Device & 0x1f)<<3)|(PciId->Function & 0x07); switch (Width) { case 8: PciWrite8(PciId->Bus,devfn,Register,Value); break; case 16: PciWrite16(PciId->Bus,devfn,Register,Value); break; case 32: PciWrite32(PciId->Bus,devfn,Register,Value); break; default: dbgprintf("AcpiOsReadPciConfiguration unhandled value width: %u\n", Width); return AE_ERROR; } return (AE_OK); }
void PciDeviceWrite(PciDevice_t *Device, uint32_t Register, uint32_t Value, uint32_t Length) { if (Length == 1) PciWrite8(Device->PciBus, Device->Bus, Device->Device, Device->Function, Register, (uint8_t)(Value & 0xFF)); else if (Length == 2) PciWrite16(Device->PciBus, Device->Bus, Device->Device, Device->Function, Register, (uint16_t)(Value & 0xFFFFF)); else PciWrite32(Device->PciBus, Device->Bus, Device->Device, Device->Function, Register, Value); }
/** Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. Reads the 8-bit PCI configuration register specified by Address, performs a bitwise OR between the read result and the value specified by OrData, and writes the result to the 8-bit PCI configuration register specified by Address. The value written to the PCI configuration register is returned. This function must guarantee that all PCI read and write operations are serialized. If Address > 0x0FFFFFFF, then ASSERT(). @param Address The address that encodes the PCI Bus, Device, Function and Register. @param OrData The value to OR with the PCI configuration register. @return The value written back to the PCI configuration register. **/ UINT8 EFIAPI PciOr8 ( IN UINTN Address, IN UINT8 OrData ) { return PciWrite8 (Address, (UINT8) (PciRead8 (Address) | OrData)); }
/** Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. Reads the 8-bit PCI configuration register specified by Address, performs a bitwise AND between the read result and the value specified by AndData, and writes the result to the 8-bit PCI configuration register specified by Address. The value written to the PCI configuration register is returned. This function must guarantee that all PCI read and write operations are serialized. If Address > 0x0FFFFFFF, then ASSERT(). @param Address The address that encodes the PCI Bus, Device, Function and Register. @param AndData The value to AND with the PCI configuration register. @return The value written back to the PCI configuration register. **/ UINT8 EFIAPI PciAnd8 ( IN UINTN Address, IN UINT8 AndData ) { return PciWrite8 (Address, (UINT8) (PciRead8 (Address) & AndData)); }
/** Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. Reads the 8-bit PCI configuration register specified by Address, performs a bitwise OR between the read result and the value specified by OrData, and writes the result to the 8-bit PCI configuration register specified by Address. The value written to the PCI configuration register is returned. This function must guarantee that all PCI read and write operations are serialized. If any reserved bits in Address are set, then ASSERT(). @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. @param OrData The value to OR with the PCI configuration register. @return The value written to the PCI configuration register. **/ UINT8 EFIAPI PciSegmentOr8 ( IN UINT64 Address, IN UINT8 OrData ) { return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8) (PciSegmentRead8 (Address) | OrData)); }
/** Writes an 8-bit PCI configuration register and saves the value in the S3 script to be replayed on S3 resume. Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. Value is returned. This function must guarantee that all PCI read and write operations are serialized. If Address > 0x0FFFFFFF, then ASSERT(). @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Value The value to write. @return The value written to the PCI configuration register. **/ UINT8 EFIAPI S3PciWrite8 ( IN UINTN Address, IN UINT8 Value ) { return InternalSavePciWrite8ValueToBootScript (Address, PciWrite8 (Address, Value)); }
/** Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, followed a bitwise OR with another 8-bit value. Reads the 8-bit PCI configuration register specified by Address, performs a bitwise AND between the read result and the value specified by AndData, performs a bitwise OR between the result of the AND operation and the value specified by OrData, and writes the result to the 8-bit PCI configuration register specified by Address. The value written to the PCI configuration register is returned. This function must guarantee that all PCI read and write operations are serialized. If Address > 0x0FFFFFFF, then ASSERT(). @param Address The address that encodes the PCI Bus, Device, Function and Register. @param AndData The value to AND with the PCI configuration register. @param OrData The value to OR with the result of the AND operation. @return The value written back to the PCI configuration register. **/ UINT8 EFIAPI PciAndThenOr8 ( IN UINTN Address, IN UINT8 AndData, IN UINT8 OrData ) { return PciWrite8 (Address, (UINT8) ((PciRead8 (Address) & AndData) | OrData)); }
/** Writes an 8-bit PCI configuration register. Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. Value is returned. This function must guarantee that all PCI read and write operations are serialized. If any reserved bits in Address are set, then ASSERT(). @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. @param Value The value to write. @return The value written to the PCI configuration register. **/ UINT8 EFIAPI PciSegmentWrite8 ( IN UINT64 Address, IN UINT8 Value ) { ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); }
/** Write to a given location in the PCI configuration space. @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param This Pointer to local data for the interface. @param Width The width of the access. Enumerated in bytes. See EFI_PEI_PCI_CFG_PPI_WIDTH above. @param Address The physical address of the access. The format of the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. @param Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER The invalid access width. **/ EFI_STATUS EFIAPI PciCfg2Write ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_PCI_CFG2_PPI *This, IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, IN UINT64 Address, IN OUT VOID *Buffer ) { UINTN PciLibAddress; PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address); if (Width == EfiPeiPciCfgWidthUint8) { PciWrite8 (PciLibAddress, *((UINT8 *) Buffer)); } else if (Width == EfiPeiPciCfgWidthUint16) { if ((PciLibAddress & 0x01) == 0) { // // Aligned Pci address access // PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer)); } else { // // Unaligned Pci address access, break up the request into byte by byte. // PciWrite8 (PciLibAddress, *((UINT8 *) Buffer)); PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); } } else if (Width == EfiPeiPciCfgWidthUint32) { if ((PciLibAddress & 0x03) == 0) { // // Aligned Pci address access // PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer)); } else if ((PciLibAddress & 0x01) == 0) { // // Unaligned Pci address access, break up the request into word by word. // PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer)); PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1)); } else { // // Unaligned Pci address access, break up the request into byte by byte. // PciWrite8 (PciLibAddress, *((UINT8 *) Buffer)); PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2)); PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3)); } } else { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/* PciDeviceWrite * Writes a value of the given length to the given register * and this function takes care of the rest */ void PciDeviceWrite(PciDevice_t *Device, size_t Register, uint32_t Value, size_t Length) { if (Length == 1) { PciWrite8(Device->BusIo, Device->Bus, Device->Slot, Device->Function, Register, (uint8_t)(Value & 0xFF)); } else if (Length == 2) { PciWrite16(Device->BusIo, Device->Bus, Device->Slot, Device->Function, Register, (uint16_t)(Value & 0xFFFFF)); } else { PciWrite32(Device->BusIo, Device->Bus, Device->Slot, Device->Function, Register, Value); } }
/** Reads a bit field in an 8-bit PCI configuration register, performs a bitwise AND, and writes the result back to the bit field in the 8-bit register. Reads the 8-bit PCI configuration register specified by Address, performs a bitwise AND between the read result and the value specified by AndData, and writes the result to the 8-bit PCI configuration register specified by Address. The value written to the PCI configuration register is returned. This function must guarantee that all PCI read and write operations are serialized. Extra left bits in AndData are stripped. If Address > 0x0FFFFFFF, then ASSERT(). If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Address The PCI configuration register to write. @param StartBit The ordinal of the least significant bit in the bit field. Range 0..7. @param EndBit The ordinal of the most significant bit in the bit field. Range 0..7. @param AndData The value to AND with the PCI configuration register. @return The value written back to the PCI configuration register. **/ UINT8 EFIAPI PciBitFieldAnd8 ( IN UINTN Address, IN UINTN StartBit, IN UINTN EndBit, IN UINT8 AndData ) { return PciWrite8 ( Address, BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData) ); }
/** Writes a bit field to a PCI configuration register. Writes Value to the bit field of the PCI configuration register. The bit field is specified by the StartBit and the EndBit. All other bits in the destination PCI configuration register are preserved. The new value of the 8-bit register is returned. If Address > 0x0FFFFFFF, then ASSERT(). If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Address The PCI configuration register to write. @param StartBit The ordinal of the least significant bit in the bit field. Range 0..7. @param EndBit The ordinal of the most significant bit in the bit field. Range 0..7. @param Value The new value of the bit field. @return The value written back to the PCI configuration register. **/ UINT8 EFIAPI PciBitFieldWrite8 ( IN UINTN Address, IN UINTN StartBit, IN UINTN EndBit, IN UINT8 Value ) { return PciWrite8 ( Address, BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value) ); }
/** Copies the data in a caller supplied buffer to a specified range of PCI configuration space. Writes the range of PCI configuration registers specified by StartAddress and Size from the buffer specified by Buffer. This function only allows the PCI configuration registers from a single PCI function to be written. Size is returned. When possible 32-bit PCI configuration write cycles are used to write from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit and 16-bit PCI configuration write cycles may be used at the beginning and the end of the range. If StartAddress > 0x0FFFFFFF, then ASSERT(). If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). If Size > 0 and Buffer is NULL, then ASSERT(). @param StartAddress The starting address that encodes the PCI Bus, Device, Function and Register. @param Size The size in bytes of the transfer. @param Buffer The pointer to a buffer containing the data to write. @return Size written to StartAddress. **/ UINTN EFIAPI PciWriteBuffer ( IN UINTN StartAddress, IN UINTN Size, IN VOID *Buffer ) { UINTN ReturnValue; ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); if (Size == 0) { return 0; } ASSERT (Buffer != NULL); // // Save Size for return // ReturnValue = Size; if ((StartAddress & BIT0) != 0) { // // Write a byte if StartAddress is byte aligned // PciWrite8 (StartAddress, *(UINT8*)Buffer); StartAddress += sizeof (UINT8); Size -= sizeof (UINT8); Buffer = (UINT8*)Buffer + 1; } if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { // // Write a word if StartAddress is word aligned // PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } while (Size >= sizeof (UINT32)) { // // Write as many double words as possible // PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); StartAddress += sizeof (UINT32); Size -= sizeof (UINT32); Buffer = (UINT32*)Buffer + 1; } if (Size >= sizeof (UINT16)) { // // Write the last remaining word if exist // PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } if (Size >= sizeof (UINT8)) { // // Write the last remaining byte if exist // PciWrite8 (StartAddress, *(UINT8*)Buffer); } return ReturnValue; }
VOID PciInitialization ( ) { // // Bus 0, Device 0, Function 0 - Host to PCI Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00); // // Bus 0, Device 1, Function 0 - PCI to ISA Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target // // Bus 0, Device 1, Function 1 - IDE Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40); // // Bus 0, Device 1, Function 3 - Power Managment Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA // // Bus 0, Device 2, Function 0 - Video Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00); // // Bus 0, Device 3, Function 0 - Network Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a); PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC) // // Bus 0, Device 5, Function 0 - RAM Memory // PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b); PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA) }
/** Install the VBE Info and VBE Mode Info structures, and the VBE service handler routine in the C segment. Point the real-mode Int10h interrupt vector to the handler. The only advertised mode is 1024x768x32. @param[in] CardName Name of the video card to be exposed in the Product Name field of the VBE Info structure. The parameter must originate from a QEMU_VIDEO_CARD.Name field. @param[in] FrameBufferBase Guest-physical base address of the video card's frame buffer. **/ VOID InstallVbeShim ( IN CONST CHAR16 *CardName, IN EFI_PHYSICAL_ADDRESS FrameBufferBase ) { EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF; UINTN Segment0Pages; IVT_ENTRY *Int0x10; EFI_STATUS Status; UINTN Pam1Address; UINT8 Pam1; UINTN SegmentCPages; VBE_INFO *VbeInfoFull; VBE_INFO_BASE *VbeInfo; UINT8 *Ptr; UINTN Printed; VBE_MODE_INFO *VbeModeInfo; Segment0 = 0x00000; SegmentC = 0xC0000; SegmentF = 0xF0000; // // Attempt to cover the real mode IVT with an allocation. This is a UEFI // driver, hence the arch protocols have been installed previously. Among // those, the CPU arch protocol has configured the IDT, so we can overwrite // the IVT used in real mode. // // The allocation request may fail, eg. if LegacyBiosDxe has already run. // Segment0Pages = 1; Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10; Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, Segment0Pages, &Segment0); if (EFI_ERROR (Status)) { EFI_PHYSICAL_ADDRESS Handler; // // Check if a video BIOS handler has been installed previously -- we // shouldn't override a real video BIOS with our shim, nor our own shim if // it's already present. // Handler = (Int0x10->Segment << 4) + Int0x10->Offset; if (Handler >= SegmentC && Handler < SegmentF) { DEBUG ((EFI_D_VERBOSE, "%a: Video BIOS handler found at %04x:%04x\n", __FUNCTION__, Int0x10->Segment, Int0x10->Offset)); return; } // // Otherwise we'll overwrite the Int10h vector, even though we may not own // the page at zero. // DEBUG ((EFI_D_VERBOSE, "%a: failed to allocate page at zero: %r\n", __FUNCTION__, Status)); } else { // // We managed to allocate the page at zero. SVN r14218 guarantees that it // is NUL-filled. // ASSERT (Int0x10->Segment == 0x0000); ASSERT (Int0x10->Offset == 0x0000); } // // Put the shim in place first. // Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A); // // low nibble covers 0xC0000 to 0xC3FFF // high nibble covers 0xC4000 to 0xC7FFF // bit1 in each nibble is Write Enable // bit0 in each nibble is Read Enable // Pam1 = PciRead8 (Pam1Address); PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0)); // // We never added memory space durig PEI or DXE for the C segment, so we // don't need to (and can't) allocate from there. Also, guest operating // systems will see a hole in the UEFI memory map there. // SegmentCPages = 4; ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages)); CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim); // // Fill in the VBE INFO structure. // VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC; VbeInfo = &VbeInfoFull->Base; Ptr = VbeInfoFull->Buffer; CopyMem (VbeInfo->Signature, "VESA", 4); VbeInfo->VesaVersion = 0x0300; VbeInfo->OemNameAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); CopyMem (Ptr, "QEMU", 5); Ptr += 5; VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode VbeInfo->ModeListAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); *(UINT16*)Ptr = 0x00f1; // mode number Ptr += 2; *(UINT16*)Ptr = 0xFFFF; // mode list terminator Ptr += 2; VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536); VbeInfo->OemSoftwareVersion = 0x0000; VbeInfo->VendorNameAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); CopyMem (Ptr, "OVMF", 5); Ptr += 5; VbeInfo->ProductNameAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); Printed = AsciiSPrint ((CHAR8 *)Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s", CardName); Ptr += Printed + 1; VbeInfo->ProductRevAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); CopyMem (Ptr, mProductRevision, sizeof mProductRevision); Ptr += sizeof mProductRevision; ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer); ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer)); // // Fil in the VBE MODE INFO structure. // VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1); // // bit0: mode supported by present hardware configuration // bit1: optional information available (must be =1 for VBE v1.2+) // bit3: set if color, clear if monochrome // bit4: set if graphics mode, clear if text mode // bit5: mode is not VGA-compatible // bit7: linear framebuffer mode supported // VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0; // // bit0: exists // bit1: bit1: readable // bit2: writeable // VbeModeInfo->WindowAAttr = BIT2 | BIT1 | BIT0; VbeModeInfo->WindowBAttr = 0x00; VbeModeInfo->WindowGranularityKB = 0x0040; VbeModeInfo->WindowSizeKB = 0x0040; VbeModeInfo->WindowAStartSegment = 0xA000; VbeModeInfo->WindowBStartSegment = 0x0000; VbeModeInfo->WindowPositioningAddress = 0x0000; VbeModeInfo->BytesPerScanLine = 1024 * 4; VbeModeInfo->Width = 1024; VbeModeInfo->Height = 768; VbeModeInfo->CharCellWidth = 8; VbeModeInfo->CharCellHeight = 16; VbeModeInfo->NumPlanes = 1; VbeModeInfo->BitsPerPixel = 32; VbeModeInfo->NumBanks = 1; VbeModeInfo->MemoryModel = 6; // direct color VbeModeInfo->BankSizeKB = 0; VbeModeInfo->NumImagePagesLessOne = 0; VbeModeInfo->Vbe3 = 0x01; VbeModeInfo->RedMaskSize = 8; VbeModeInfo->RedMaskPos = 16; VbeModeInfo->GreenMaskSize = 8; VbeModeInfo->GreenMaskPos = 8; VbeModeInfo->BlueMaskSize = 8; VbeModeInfo->BlueMaskPos = 0; VbeModeInfo->ReservedMaskSize = 8; VbeModeInfo->ReservedMaskPos = 24; // // bit1: Bytes in reserved field may be used by application // VbeModeInfo->DirectColorModeInfo = BIT1; VbeModeInfo->LfbAddress = (UINT32)FrameBufferBase; VbeModeInfo->OffScreenAddress = 0; VbeModeInfo->OffScreenSizeKB = 0; VbeModeInfo->BytesPerScanLineLinear = 1024 * 4; VbeModeInfo->NumImagesLessOneBanked = 0; VbeModeInfo->NumImagesLessOneLinear = 0; VbeModeInfo->RedMaskSizeLinear = 8; VbeModeInfo->RedMaskPosLinear = 16; VbeModeInfo->GreenMaskSizeLinear = 8; VbeModeInfo->GreenMaskPosLinear = 8; VbeModeInfo->BlueMaskSizeLinear = 8; VbeModeInfo->BlueMaskPosLinear = 0; VbeModeInfo->ReservedMaskSizeLinear = 8; VbeModeInfo->ReservedMaskPosLinear = 24; VbeModeInfo->MaxPixelClockHz = 0; ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved); // // Clear Write Enable (bit1), keep Read Enable (bit0) set // PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0); // // Second, point the Int10h vector at the shim. // Int0x10->Segment = SegmentC >> 4; Int0x10->Offset = (EFI_PHYSICAL_ADDRESS)(UINTN)(VbeModeInfo + 1) - SegmentC; DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__)); }
/** Performs any early platform specific GPIO Controller manipulation. **/ VOID EFIAPI EarlyPlatformGpioCtrlerManipulation ( VOID ) { UINT32 IohGpioBase; UINT32 Data32; UINT32 Addr; UINT32 DevPcieAddr; UINT16 SaveCmdReg; UINT32 SaveBarReg; UINT16 PciVid; UINT16 PciDid; IohGpioBase = (UINT32) PcdGet64 (PcdIohGpioMmioBase); DevPcieAddr = PCI_LIB_ADDRESS ( PcdGet8 (PcdIohGpioBusNumber), PcdGet8 (PcdIohGpioDevNumber), PcdGet8 (PcdIohGpioFunctionNumber), 0 ); // // Do nothing if not a supported device. // PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET); PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET); if((PciVid != V_IOH_I2C_GPIO_VENDOR_ID) || (PciDid != V_IOH_I2C_GPIO_DEVICE_ID)) { return; } // // Save current settings for PCI CMD/BAR registers. // SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET); SaveBarReg = PciRead32 (DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)); // // Use predefined tempory memory resource. // PciWrite32 ( DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister), IohGpioBase); PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE); // // Gpio Controller Manipulation Tasks. // // // Reset Cypress Expander on Galileo Platform // Addr = IohGpioBase + GPIO_SWPORTA_DR; Data32 = *((volatile UINT32 *) (UINTN)(Addr)); Data32 |= BIT4; // Cypress Reset line controlled by GPIO<4> *((volatile UINT32 *) (UINTN)(Addr)) = Data32; Data32 = *((volatile UINT32 *) (UINTN)(Addr)); Data32 &= ~BIT4; // Cypress Reset line controlled by GPIO<4> *((volatile UINT32 *) (UINTN)(Addr)) = Data32; // // Restore settings for PCI CMD/BAR registers // PciWrite32 ((DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg); PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg); }
/** Dispatch function for a Software SMI handler. @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). @param[in] RegisterContext Points to an optional handler context which was specified when the handler was registered. @param[in, out] CommBuffer A pointer to a collection of Data in memory that will be conveyed from a non-SMM environment into an SMM environment. @param[in, out] CommBufferSize The Size of the CommBuffer. @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers should still be called. @retval Others Other execution results. **/ EFI_STATUS EFIAPI SmmUnlockOpalPassword ( IN EFI_HANDLE DispatchHandle, IN CONST VOID *RegisterContext, IN OUT VOID *CommBuffer, IN OUT UINTN *CommBufferSize ) { EFI_STATUS Status; OPAL_SMM_DEVICE *OpalDev; LIST_ENTRY *Entry; UINT8 BaseClassCode; UINT8 SubClassCode; UINT8 ProgInt; TCG_RESULT Result; UINT8 SataCmdSt; UINT8 *StorePcieConfDataList[16]; UINTN RpBase; UINTN MemoryBase; UINTN MemoryLength; OPAL_SESSION Session; BOOLEAN BlockSidSupport; ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList)); Status = EFI_DEVICE_ERROR; // // try to unlock all locked hdd disks. // for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) { OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link); RpBase = 0; SataCmdSt = 0; /// /// Configure RootPort for PCIe AHCI/NVME devices. /// if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { /// /// Save original RootPort configuration space to heap /// RpBase = SaveRestoreRootportConfSpace ( OpalDev, TRUE, StorePcieConfDataList ); MemoryBase = mNvmeContext.Nbar; MemoryLength = 0; ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength); /// /// Enable PCIE decode for RootPort /// SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD); PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6); } else { SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD)); PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6); } BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B)); SubClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A)); ProgInt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09)); if (BaseClassCode != PCI_CLASS_MASS_STORAGE) { Status = EFI_INVALID_PARAMETER; break; } Status = EFI_DEVICE_ERROR; if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) { if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) { Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status)); goto done; } Status = AhciModeInitialize ((UINT8)OpalDev->SataPort); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status)); goto done; } } else { DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n")); } } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) { if (ProgInt != PCI_IF_NVMHCI) { DEBUG ((DEBUG_ERROR, "PI not support, skipped\n")); Status = EFI_NOT_FOUND; goto done; } mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0); mNvmeContext.NvmeInitWaitTime = 0; mNvmeContext.Nsid = OpalDev->NvmeNamespaceId; Status = NvmeControllerInit (&mNvmeContext); } else { DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n")); } } else { DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n")); goto done; } Status = EFI_DEVICE_ERROR; BlockSidSupport = FALSE; if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) { ZeroMem(&Session, sizeof(Session)); Session.Sscp = &OpalDev->Sscp; Session.MediaId = 0; Session.OpalBaseComId = OpalDev->OpalBaseComId; Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL); if (Result == TcgResultSuccess) { Status = EFI_SUCCESS; } } if (mSendBlockSID && BlockSidSupport) { Result = OpalBlockSid (&Session, TRUE); if (Result != TcgResultSuccess) { break; } } if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) { Status = NvmeControllerExit (&mNvmeContext); } } done: if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { ASSERT (RpBase != 0); PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0); RpBase = SaveRestoreRootportConfSpace ( OpalDev, FALSE, // restore StorePcieConfDataList ); PciWrite8 (RpBase + NVME_PCIE_PCICMD, SataCmdSt); } else { PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt); } if (EFI_ERROR (Status)) { break; } } return Status; }
VOID PciInitialization ( ) { // // Bus 0, Device 0, Function 0 - Host to PCI Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00); // // Bus 0, Device 1, Function 0 - PCI to ISA Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09); // // Bus 0, Device 1, Function 1 - IDE Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40); // // Bus 0, Device 1, Function 3 - Power Managment Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // // Bus 0, Device 2, Function 0 - Video Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00); // // Bus 0, Device 3, Function 0 - Network Controller // PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b); PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // // Bus 0, Device 4, Function 0 - RAM Memory // PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09); PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01); }