/** Checks if the given GUID is a zero GUID. This function checks whether the given GUID is a zero GUID. If the GUID is identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. If Guid is NULL, then ASSERT(). @param Guid The pointer to a 128 bit GUID. @retval TRUE Guid is a zero GUID. @retval FALSE Guid is not a zero GUID. **/ BOOLEAN EFIAPI IsZeroGuid ( IN CONST GUID *Guid ) { UINT64 LowPartOfGuid; UINT64 HighPartOfGuid; LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); }
/** Compares two GUIDs. This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. If there are any bit differences in the two GUIDs, then FALSE is returned. If Guid1 is NULL, then ASSERT(). If Guid2 is NULL, then ASSERT(). @param Guid1 A pointer to a 128 bit GUID. @param Guid2 A pointer to a 128 bit GUID. @retval TRUE Guid1 and Guid2 are identical. @retval FALSE Guid1 and Guid2 are not identical. **/ BOOLEAN EFIAPI GlueCompareGuid ( IN CONST GUID *Guid1, IN CONST GUID *Guid2 ) { return (BOOLEAN)( ReadUnaligned64 ((CONST UINT64*)Guid1) == ReadUnaligned64 ((CONST UINT64*)Guid2) && ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) ); }
EFIAPI CopyGuid ( OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid ) { WriteUnaligned64 ( (UINT64*)DestinationGuid, ReadUnaligned64 ((CONST UINT64*)SourceGuid) ); WriteUnaligned64 ( (UINT64*)DestinationGuid + 1, ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) ); return DestinationGuid; }
/** Write Nvm Express admin completion queue base address register. @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. @param Acq The buffer used to store the content to be written into admin completion queue base address register. @return EFI_SUCCESS Successfully write data into the admin completion queue base address register. @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register. **/ EFI_STATUS WriteNvmeAdminCompletionQueueBaseAddress ( IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_ACQ *Acq ) { EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; UINT64 Data; PciIo = Private->PciIo; Data = ReadUnaligned64 ((UINT64*)Acq); Status = PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_ACQ_OFFSET, 2, &Data ); if (EFI_ERROR(Status)) { return Status; } DEBUG ((EFI_D_INFO, "Acq: %lxh\n", *Acq)); return EFI_SUCCESS; }
/** Override function for SDHCI capability bits @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. @param[in] ControllerHandle The EFI_HANDLE of the controller. @param[in] Slot The 0 based slot index. @param[in,out] SdMmcHcSlotCapability The SDHCI capability structure. @retval EFI_SUCCESS The override function completed successfully. @retval EFI_NOT_FOUND The specified controller or slot does not exist. @retval EFI_INVALID_PARAMETER SdMmcHcSlotCapability is NULL **/ STATIC EFI_STATUS EFIAPI SynQuacerSdMmcCapability ( IN EFI_HANDLE ControllerHandle, IN UINT8 Slot, IN OUT VOID *SdMmcHcSlotCapability ) { UINT64 Capability; if (ControllerHandle != mSdMmcControllerHandle) { return EFI_SUCCESS; } ASSERT (Slot == 0); // // Clear the SDR104 capability bit. This avoids the need for a HS200 tuning // quirk that is difficult to support using the generic driver. // Clear the DDR50 bit as well to work around an issue with the Kingston // EMMC08G-M325-A52 part that was fitted on 96board DeveloperBox samples. // Capability = ReadUnaligned64 (SdMmcHcSlotCapability); Capability &= ~(UINT64)(SD_HC_CAP_SDR104 | SD_HC_CAP_DDR50); WriteUnaligned64 (SdMmcHcSlotCapability, Capability); return EFI_SUCCESS; }
/** Retrieves an 64-bit value for a given PCD token. Retrieves the current 64-bits value for a PCD token number. If the TokenNumber is invalid, the results are unpredictable. @param[in] TokenNumber The PCD token number. @return The UINT64 value. **/ UINT64 EFIAPI DxePcdGet64 ( IN UINTN TokenNumber ) { return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64))); }
/** Retrieves an 64-bit value for a given PCD token. Retrieves the 64-bit value of a particular PCD token. If the TokenNumber is invalid or the token space specified by Guid does not exist, the results are unpredictable. @param[in] Guid The token space for the token number. @param[in] ExTokenNumber The PCD token number. @return The size 64-bit value for the PCD token. **/ UINT64 EFIAPI DxePcdGet64Ex ( IN CONST EFI_GUID *Guid, IN UINTN ExTokenNumber ) { return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64))); }
/** Compares two GUIDs. This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. If there are any bit differences in the two GUIDs, then FALSE is returned. If Guid1 is NULL, then ASSERT(). If Guid2 is NULL, then ASSERT(). @param Guid1 A pointer to a 128 bit GUID. @param Guid2 A pointer to a 128 bit GUID. @retval TRUE Guid1 and Guid2 are identical. @retval FALSE Guid1 and Guid2 are not identical. **/ BOOLEAN EFIAPI CompareGuid ( IN CONST GUID *Guid1, IN CONST GUID *Guid2 ) { UINT64 LowPartOfGuid1; UINT64 LowPartOfGuid2; UINT64 HighPartOfGuid1; UINT64 HighPartOfGuid2; LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); }
/** Writes memory-mapped registers. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Width The width of the access. Enumerated in bytes. @param[in] Address The physical address of the access. @param[in] Count The number of accesses to perform. @param[in] Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this EFI system. **/ EFI_STATUS EFIAPI CpuMemoryServiceWrite ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN EFI_PEI_CPU_IO_PPI_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth; BOOLEAN Aligned; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // InStride = mInStride[Width]; OutStride = mOutStride[Width]; OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03); Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00); for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiPeiCpuIoWidthUint8) { MmioWrite8 ((UINTN)Address, *Uint8Buffer); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else { MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else { MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint64) { if (Aligned) { MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); } else { MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer)); } } } return EFI_SUCCESS; }
VOID ArmPlatformGetGlobalVariable ( IN UINTN VariableOffset, IN UINTN VariableSize, OUT VOID* Variable ) { UINTN GlobalVariableBase; // Ensure the Global Variable Size have been initialized ASSERT (VariableOffset < PcdGet32 (PcdSecGlobalVariableSize)); GlobalVariableBase = PcdGet32 (PcdCPUCoresSecStackBase) + PcdGet32 (PcdCPUCoreSecPrimaryStackSize) - PcdGet32 (PcdSecGlobalVariableSize); if (VariableSize == 4) { *(UINT32*)Variable = ReadUnaligned32 ((CONST UINT32*)(GlobalVariableBase + VariableOffset)); } else if (VariableSize == 8) { *(UINT64*)Variable = ReadUnaligned64 ((CONST UINT64*)(GlobalVariableBase + VariableOffset)); } else { CopyMem (Variable, (VOID*)(GlobalVariableBase + VariableOffset), VariableSize); } }
/** Get the fixed loadding address from image header assigned by build tool. This function only be called when Loading module at Fixed address feature enabled. @param ImageContext Pointer to the image context structure that describes the PE/COFF image that needs to be examined by this function. @param Private Pointer to the private data passed in from caller @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . @retval EFI_NOT_FOUND The image has no assigned fixed loadding address. **/ EFI_STATUS GetPeCoffImageFixLoadingAssignedAddress( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, IN PEI_CORE_INSTANCE *Private ) { UINTN SectionHeaderOffset; EFI_STATUS Status; EFI_IMAGE_SECTION_HEADER SectionHeader; EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; EFI_PHYSICAL_ADDRESS FixLoaddingAddress; UINT16 Index; UINTN Size; UINT16 NumberOfSections; UINT64 ValueInSectionHeader; FixLoaddingAddress = 0; Status = EFI_NOT_FOUND; // // Get PeHeader pointer // ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); if (ImageContext->IsTeImage) { // // for TE image, the fix loadding address is saved in first section header that doesn't point // to code section. // SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER); NumberOfSections = ImgHdr->Te.NumberOfSections; } else { SectionHeaderOffset = (UINTN)( ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader ); NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; } // // Get base address from the first section header that doesn't point to code section. // for (Index = 0; Index < NumberOfSections; Index++) { // // Read section header from file // Size = sizeof (EFI_IMAGE_SECTION_HEADER); Status = ImageContext->ImageRead ( ImageContext->Handle, SectionHeaderOffset, &Size, &SectionHeader ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_NOT_FOUND; if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { // // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or // else, these 2 fileds should be set to Zero // ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); if (ValueInSectionHeader != 0) { // // Found first section header that doesn't point to code section. // if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) { // // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field // hold the absolute address of image base runing in memory // FixLoaddingAddress = ValueInSectionHeader; } else { // // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field // hold the offset relative to a platform-specific top address. // FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader); } // // Check if the memory range is avaliable. // Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoaddingAddress, (UINT32) ImageContext->ImageSize); if (!EFI_ERROR(Status)) { // // The assigned address is valid. Return the specified loadding address // ImageContext->ImageAddress = FixLoaddingAddress; } } break; } SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); } DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoaddingAddress, Status)); return Status; }
/** Get the fixed loadding address from image header assigned by build tool. This function only be called when Loading module at Fixed address feature enabled. @param ImageContext Pointer to the image context structure that describes the PE/COFF image that needs to be examined by this function. @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . @retval EFI_NOT_FOUND The image has no assigned fixed loadding address. **/ EFI_STATUS GetPeCoffImageFixLoadingAssignedAddress( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { UINTN SectionHeaderOffset; EFI_STATUS Status; EFI_IMAGE_SECTION_HEADER SectionHeader; EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; EFI_PHYSICAL_ADDRESS FixLoaddingAddress; UINT16 Index; UINTN Size; UINT16 NumberOfSections; UINT64 ValueInSectionHeader; FixLoaddingAddress = 0; Status = EFI_NOT_FOUND; // // Get PeHeader pointer // ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); SectionHeaderOffset = (UINTN)( ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader ); NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; // // Get base address from the first section header that doesn't point to code section. // for (Index = 0; Index < NumberOfSections; Index++) { // // Read section header from file // Size = sizeof (EFI_IMAGE_SECTION_HEADER); Status = ImageContext->ImageRead ( ImageContext->Handle, SectionHeaderOffset, &Size, &SectionHeader ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_NOT_FOUND; if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { // // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled, // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields // should not be Zero, or else, these 2 fileds should be set to Zero // ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); if (ValueInSectionHeader != 0) { // // Found first section header that doesn't point to code section in which uild tool saves the // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields // FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader); // // Check if the memory range is avaliable. // Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment)); if (!EFI_ERROR(Status)) { // // The assigned address is valid. Return the specified loadding address // ImageContext->ImageAddress = FixLoaddingAddress; } } break; } SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); } DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status)); return Status; }
EFI_STATUS NorFlashPlatformGetDevices ( OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions, OUT UINT32 *Count ) { FDT_CLIENT_PROTOCOL *FdtClient; INT32 Node; EFI_STATUS Status; EFI_STATUS FindNodeStatus; CONST UINT32 *Reg; UINT32 PropSize; UINT32 Num; UINT64 Base; UINT64 Size; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Num = 0; for (FindNodeStatus = FdtClient->FindCompatibleNode (FdtClient, "cfi-flash", &Node); !EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS; FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient, "cfi-flash", Node, &Node)) { Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", (CONST VOID **)&Reg, &PropSize); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: GetNodeProperty () failed (Status == %r)\n", __FUNCTION__, Status)); continue; } ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0); while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) { Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0])); Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2])); Reg += 4; PropSize -= 4 * sizeof (UINT32); // // Disregard any flash devices that overlap with the primary FV. // The firmware is not updatable from inside the guest anyway. // if ((PcdGet64 (PcdFvBaseAddress) + PcdGet32 (PcdFvSize) > Base) && (Base + Size) > PcdGet64 (PcdFvBaseAddress)) { continue; } mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base; mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base; mNorFlashDevices[Num].Size = (UINTN)Size; mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE; Num++; } } *NorFlashDescriptions = mNorFlashDevices; *Count = Num; return EFI_SUCCESS; }
/** Initialize the system (or sometimes called permanent) memory This memory is generally represented by the DRAM. This function is called from InitializeMemory() in MemoryInitPeim, in the PEI phase. **/ VOID ArmPlatformInitializeSystemMemory ( VOID ) { VOID *DeviceTreeBase; INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize; CONST CHAR8 *Type; INT32 Len; CONST UINT64 *RegProp; NewBase = 0; NewSize = 0; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL); // // Make sure we have a valid device tree blob // ASSERT (fdt_check_header (DeviceTreeBase) == 0); // // Look for a memory node // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } // // Check for memory node // Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len); if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) { // // Get the 'reg' property of this node. For now, we will assume // two 8 byte quantities for base and size, respectively. // RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (RegProp != 0 && Len == (2 * sizeof (UINT64))) { NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1)); // // Make sure the start of DRAM matches our expectation // ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase); PcdSet64 (PcdSystemMemorySize, NewSize); DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n", __FUNCTION__, NewBase, NewBase + NewSize - 1)); } else { DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); } break; } } // // We need to make sure that the machine we are running on has at least // 128 MB of memory configured, and is currently executing this binary from // NOR flash. This prevents a device tree image in DRAM from getting // clobbered when our caller installs permanent PEI RAM, before we have a // chance of marking its location as reserved or copy it to a freshly // allocated block in the permanent PEI RAM in the platform PEIM. // ASSERT (NewSize >= SIZE_128MB); ASSERT ( (((UINT64)PcdGet64 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) || ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize))); }
STATIC UINT64 SerialPortGetBaseAddress ( VOID ) { UINT64 BaudRate; UINT32 ReceiveFifoDepth; EFI_PARITY_TYPE Parity; UINT8 DataBits; EFI_STOP_BITS_TYPE StopBits; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 Len; CONST CHAR8 *Compatible; CONST CHAR8 *NodeStatus; CONST CHAR8 *CompatibleItem; CONST UINT64 *RegProperty; UINTN UartBase; RETURN_STATUS Status; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { return 0; } // // Enumerate all FDT nodes looking for a PL011 and capture its base address // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); if (Compatible == NULL) { continue; } // // Iterate over the NULL-separated items in the compatible string // for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len; CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) { if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) { NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len); if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) { continue; } RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (Len != 16) { return 0; } UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty)); BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate); ReceiveFifoDepth = 0; // Use the default value for Fifo depth Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits); Status = PL011UartInitializePort ( UartBase, FixedPcdGet32 (PL011UartClkInHz), &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits ); if (!EFI_ERROR (Status)) { return UartBase; } } } } return 0; }
/** Execute READ CAPACITY 16 bytes command to request information regarding the capacity of the installed medium of the device. This function executes READ CAPACITY 16 bytes command to get the capacity of the USB mass storage media, including the presence, block size, and last block number. @param UsbMass The device to retireve disk gemotric. @retval EFI_SUCCESS The disk geometry is successfully retrieved. @retval EFI_NOT_READY The returned block size is zero. @retval Other READ CAPACITY 16 bytes command execution failed. **/ EFI_STATUS UsbBootReadCapacity16 ( IN USB_MASS_DEVICE *UsbMass ) { UINT8 CapacityCmd[16]; EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; UINT32 BlockSize; Media = &UsbMass->BlockIoMedia; Media->MediaPresent = FALSE; Media->LastBlock = 0; Media->BlockSize = 0; ZeroMem (CapacityCmd, sizeof (CapacityCmd)); ZeroMem (&CapacityData, sizeof (CapacityData)); CapacityCmd[0] = EFI_SCSI_OP_READ_CAPACITY16; CapacityCmd[1] = 0x10; // // Partial medium indicator, set the bytes 2 ~ 9 of the Cdb as ZERO. // ZeroMem ((CapacityCmd + 2), 8); CapacityCmd[13] = sizeof (CapacityData); Status = UsbBootExecCmdWithRetry ( UsbMass, CapacityCmd, (UINT8) sizeof (CapacityCmd), EfiUsbDataIn, &CapacityData, sizeof (CapacityData), USB_BOOT_GENERAL_CMD_TIMEOUT ); if (EFI_ERROR (Status)) { return Status; } // // Get the information on media presence, block size, and last block number // from READ CAPACITY data. // Media->MediaPresent = TRUE; Media->LastBlock = SwapBytes64 (ReadUnaligned64 ((CONST UINT64 *) &(CapacityData.LastLba7))); BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) &(CapacityData.BlockSize3))); Media->LowestAlignedLba = (CapacityData.LowestAlignLogic2 << 8) | CapacityData.LowestAlignLogic1; Media->LogicalBlocksPerPhysicalBlock = (1 << CapacityData.LogicPerPhysical); if (BlockSize == 0) { // // Get sense data // return UsbBootRequestSense (UsbMass); } else { Media->BlockSize = BlockSize; } return Status; }
/** Get the fixed loadding address from image header assigned by build tool. This function only be called when Loading module at Fixed address feature enabled. @param ImageContext Pointer to the image context structure that describes the PE/COFF image that needs to be examined by this function. @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . @retval EFI_NOT_FOUND The image has no assigned fixed loadding address. **/ EFI_STATUS GetPeCoffImageFixLoadingAssignedAddress( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { UINTN SectionHeaderOffset; EFI_STATUS Status; EFI_IMAGE_SECTION_HEADER SectionHeader; EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; EFI_PHYSICAL_ADDRESS FixLoaddingAddress; UINT16 Index; UINTN Size; UINT16 NumberOfSections; EFI_PHYSICAL_ADDRESS SmramBase; UINT64 SmmCodeSize; UINT64 ValueInSectionHeader; // // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber // SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber)); FixLoaddingAddress = 0; Status = EFI_NOT_FOUND; SmramBase = mCurrentSmramRange->CpuStart; // // Get PeHeader pointer // ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); SectionHeaderOffset = (UINTN)( ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader ); NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; // // Get base address from the first section header that doesn't point to code section. // for (Index = 0; Index < NumberOfSections; Index++) { // // Read section header from file // Size = sizeof (EFI_IMAGE_SECTION_HEADER); Status = ImageContext->ImageRead ( ImageContext->Handle, SectionHeaderOffset, &Size, &SectionHeader ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_NOT_FOUND; if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { // // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the // first section header that doesn't point to code section in image header. And there is an assumption that when the // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers // fields should NOT be Zero, or else, these 2 fileds should be set to Zero // ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); if (ValueInSectionHeader != 0) { // // Found first section header that doesn't point to code section in which uild tool saves the // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields // FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader); if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <= FixLoaddingAddress) { // // The assigned address is valid. Return the specified loadding address // ImageContext->ImageAddress = FixLoaddingAddress; Status = EFI_SUCCESS; } } break; } SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); } DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoaddingAddress, Status)); return Status; }