EFIAPI DebugClearMemory ( OUT VOID *Buffer, IN UINTN Length ) { // // If Buffer is NULL, then ASSERT(). // ASSERT (Buffer != NULL); // // SetMem() checks for the the ASSERT() condition on Length and returns Buffer // return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); }
/** Function to walk the device path looking for a dumpable node. @param[in] MappingItem The Item to fill with data. @param[in] DevicePath The path of the item to get data on. @return EFI_SUCCESS Always returns success. **/ EFI_STATUS EFIAPI GetDeviceConsistMappingInfo ( IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { VOID (EFIAPI *SerialFun) (EFI_DEVICE_PATH_PROTOCOL *, DEVICE_CONSIST_MAPPING_INFO *); UINTN Index; ASSERT(DevicePath != NULL); ASSERT(MappingItem != NULL); SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0); while (!IsDevicePathEnd (DevicePath)) { // // Find the handler to dump this device path node // SerialFun = NULL; for (Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) { if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type && DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType ) { SerialFun = DevPathConsistMappingTable[Index].SerialFun; break; } } // // If not found, use a generic function // if (!SerialFun) { SerialFun = DevPathSerialDefault; } SerialFun (DevicePath, MappingItem); // // Next device path node // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); } return EFI_SUCCESS; }
void MemoryHeapManager::Free(void* i_ptr) { MessagedAssert(i_ptr != nullptr, "Cannot free nullptr!"); std::unique_lock<std::mutex> lk(_heapMutex); MemoryChunkHeader* pChunk = GetTheChunkContainsAddress(i_ptr); MessagedAssert(pChunk != nullptr, "You are trying to free some memory not on the boundry!"); if (pChunk == nullptr) { return; } //set the chunk unUsed. pChunk->SetUsed(false); MemoryChunkHeader* pPrevChunk = pChunk->GetPrevPtr(); MemoryChunkHeader* pNextChunk = pChunk->GetNextPtr(); // Be careful, we merge with the next chunk, then the previous chunk //if the next chunk is free chunk if (pNextChunk != nullptr && !pNextChunk->Used()) { //Because the last one will always be free (only except when there is no memeory): //when we point to the third last, but the second last is free //then, we will not be able to merge the last one because it is always free... //So, when checking the next chunk is free or not, we should also check the next chunk's next chunk. //By this, we will not forget the last chunk, which is always free(if there are memory left). if (pNextChunk->GetNextPtr() && pNextChunk->GetNextPtr() != nullptr && !pNextChunk->GetNextPtr()->Used()) { //Merge the chunk MergeTwoChunkHeaders(pNextChunk, pNextChunk->GetNextPtr()); } //Merge the chunk MergeTwoChunkHeaders(pChunk, pNextChunk); if (pChunk->GetAddress()) { SetMem((uint8_t*)(pChunk->GetAddress()), (size_t)pChunk->GetSize(), 0); } } if (pPrevChunk != nullptr && !pPrevChunk->Used())//if the prev chunk have been freed. { //Merge the chunk MergeTwoChunkHeaders(pPrevChunk, pChunk); if (pPrevChunk->GetAddress()) { // Implements::SetMem((char*)(pPrevChunk->GetAddress()), pPrevChunk->GetSize(), 0); } } }
EFI_STATUS EFIAPI iTpmMemoryDiscoveredPpiCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, IN VOID *InvokePpi ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS iTpmCommandBuffer; EFI_PHYSICAL_ADDRESS iTpmResponseBuffer; PSP_DEBUG ("Psp.iTpmPei.MemoryDiscoveredPpiCallback\n"); //Send PSP mailbox command to ensure Ctrl Area have been initialed Status = CheckITPMSupported (); if (Status == EFI_SUCCESS) { Status = (*PeiServices)->AllocatePages ( PeiServices, EfiBootServicesData, //EfiConventionalMemory EFI_SIZE_TO_PAGES (iTPM_COMMAND_BUFFER_SIZE + \ iTPM_RESPONSE_BUFFER_SIZE), &iTpmCommandBuffer ); if (EFI_ERROR (Status)) { PSP_DEBUG ("Allocate Memory fail\n"); return Status; } iTpmResponseBuffer = iTpmCommandBuffer + iTPM_COMMAND_BUFFER_SIZE; SetMem ((VOID *) (UINTN) iTpmCommandBuffer, iTPM_COMMAND_BUFFER_SIZE + iTPM_RESPONSE_BUFFER_SIZE, 0); Status = iTpmAssignMemory ( (UINTN)iTpmCommandBuffer, iTPM_COMMAND_BUFFER_SIZE, (UINTN)iTpmResponseBuffer, iTPM_RESPONSE_BUFFER_SIZE ); PSP_DEBUG ("\tAllocate CmdBuf:0x%x ResBuf:0x%x\n", iTpmCommandBuffer, iTpmResponseBuffer); } return Status; }
/** Initialize a local work space header. Since Signature and WriteQueueSize have been known, Crc can be calculated out, then the work space header will be fixed. **/ VOID InitializeLocalWorkSpaceHeader ( VOID ) { // // Check signature with gEdkiiWorkingBlockSignatureGuid. // if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) { // // The local work space header has been initialized. // return; } SetMem ( &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), FTW_ERASED_BYTE ); // // Here using gEdkiiWorkingBlockSignatureGuid as the signature. // CopyMem ( &mWorkingBlockHeader.Signature, &gEdkiiWorkingBlockSignatureGuid, sizeof (EFI_GUID) ); mWorkingBlockHeader.WriteQueueSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); // // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE. // // // Calculate the Crc of woking block header // mWorkingBlockHeader.Crc = FtwCalculateCrc32 (&mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)); mWorkingBlockHeader.WorkingBlockValid = FTW_VALID_STATE; mWorkingBlockHeader.WorkingBlockInvalid = FTW_INVALID_STATE; }
/** Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to see if a SCSI device is actually present at that location on the SCSI channel. @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. @param[in, out] Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel. On output, a pointer to the Target ID (an array of TARGET_MAX_BYTES) of the next SCSI device present on a SCSI channel. An input value of 0xF(all bytes in the array are 0xF) in the Target array retrieves the Target ID of the first SCSI device present on a SCSI channel. @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI channel was returned in Target. @retval EFI_INVALID_PARAMETER Target or Lun is NULL. @retval EFI_TIMEOUT Target array is not all 0xF, and Target were not returned on a previous call to GetNextTarget(). Currently not implemented. @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. **/ EFI_STATUS EFIAPI IScsiExtScsiPassThruGetNextTarget ( IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN OUT UINT8 **Target ) { UINT8 TargetId[TARGET_MAX_BYTES]; SetMem (TargetId, TARGET_MAX_BYTES, 0xFF); if (CompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) { (*Target)[0] = 0; return EFI_SUCCESS; } else if ((*Target)[0] == 0) { return EFI_NOT_FOUND; } else { return EFI_INVALID_PARAMETER; } }
int cN2Prov0501::RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len) { if(Init(id,120)) { SetSp(0x0FFF,0x0EF8); SetMem(load,data,len); SetPc(run); ClearBreakpoints(); AddBreakpoint(stop); if(stop!=0x0000) AddBreakpoint(0x0000); AddRomCallbacks(); while(!Run(100000)) { if(GetPc()==0x0000 || GetPc()==stop) { GetMem(fetch,data,fetch_len); return 1; } else if(!RomCallbacks()) break; } } return -1; }
/** Initializes pre-allocated memory pointed by ScratchBuffer for subsequent runtime use. @param[in, out] ScratchBuffer Pointer to user-supplied memory buffer. @param[in] ScratchBufferSize Size of supplied buffer in bytes. @retval EFI_SUCCESS Successful initialization. **/ EFI_STATUS InitializeScratchMemory ( IN OUT UINT8 *ScratchBuffer, IN UINTN ScratchBufferSize ) { UINTN Index; UINTN MemorySize; // // Parameters Checking // if (ScratchBuffer == NULL) { return EFI_INVALID_PARAMETER; } if (ScratchBufferSize < MIN_REQUIRED_BLOCKS * 1024) { return EFI_BUFFER_TOO_SMALL; } mRTPageTable = (RT_MEMORY_PAGE_TABLE *)ScratchBuffer; // // Initialize Internal Page Table for Memory Management // SetMem (mRTPageTable, ScratchBufferSize, 0xFF); MemorySize = ScratchBufferSize - sizeof (RT_MEMORY_PAGE_TABLE) + sizeof (RT_MEMORY_PAGE_ENTRY); mRTPageTable->PageCount = MemorySize / (RT_PAGE_SIZE + sizeof (RT_MEMORY_PAGE_ENTRY)); mRTPageTable->LastEmptyPageOffset = 0x0; for (Index = 0; Index < mRTPageTable->PageCount; Index++) { mRTPageTable->Pages[Index].PageFlag = RT_PAGE_FREE; mRTPageTable->Pages[Index].StartPageOffset = 0; } mRTPageTable->DataAreaBase = ScratchBuffer + sizeof (RT_MEMORY_PAGE_TABLE) + (mRTPageTable->PageCount - 1) * sizeof (RT_MEMORY_PAGE_ENTRY); return EFI_SUCCESS; }
void* MemoryHeapManager::Alloc(size_t i_size) { MessagedAssert(_pMemoryAddress != nullptr, "_pMemoryAddress cannot be nullptr!"); void* pResult = nullptr; //calculate the realsize of memory alloc for the user. //becuase every time the memory address should be align 4, so we should calculate spaces beased on this size. size_t sizeOfMemory = (size_t)ceil((float)i_size / (float)NewAlignment::NEW_ALIGN_4) * NewAlignment::NEW_ALIGN_4;//ceil means round up value //std::unique_lock<std::mutex> lk(_heapMutex); MemoryChunkHeader* pChunk = GetFirstSuitbaleChunk(sizeOfMemory); if (pChunk == nullptr) { MessagedAssert(pChunk != nullptr, "No enough Memory!"); return nullptr; } pResult = pChunk->GetAddress(); //calculate how many memory left in the chunk size_t leftMemSize = pChunk->GetSize() - sizeOfMemory; pChunk->SetUsed(true); //if there is no enough space left for generating the next chunk, just return the result chunk for user if (leftMemSize <= sizeof(MemoryChunkHeader)) { return pResult; } //Before create a new Chunk, we should resize the size of the current Chunk pChunk->ReSize(sizeOfMemory); //else we need to create a new Chunk and link it with others void* pNewStartAddress = static_cast<char*>(pResult) + sizeOfMemory; MemoryChunkHeader* pNextChunk = CreateNewChunk(pNewStartAddress, leftMemSize); SetMem((uint8_t*)pNextChunk->GetAddress(), (size_t)pNextChunk->GetSize(), 0); pNextChunk->SetUsed(false); //link the new chunk with others pNextChunk->SetPrevPtr(pChunk); MemoryChunkHeader* pPreviousNext = pChunk->GetNextPtr(); pChunk->SetNextPtr(pNextChunk); pNextChunk->SetNextPtr(pPreviousNext); //return the address for user return pResult; }
void LoadMaterial(const char* i_pBinaryMaterialFile) { // First, Load and set the material buffer uint32_t o_lengthOfWholerMaterialBuffer = 0; uint32_t o_lengthOfEffectPath = 0; uint8_t* pBuffer = LoadMaterialInfo(i_pBinaryMaterialFile, o_lengthOfWholerMaterialBuffer, o_lengthOfEffectPath); if (o_lengthOfWholerMaterialBuffer == 0) { SAFE_DELETE(pBuffer); return; } // Second, let's copy the buffer for real material uint8_t* pOutBuffer = new uint8_t[o_lengthOfWholerMaterialBuffer - o_lengthOfEffectPath]; SetMem(pOutBuffer, o_lengthOfWholerMaterialBuffer - o_lengthOfEffectPath, 0); CopyMem(pBuffer, pOutBuffer, o_lengthOfWholerMaterialBuffer - o_lengthOfEffectPath); MaterialDesc* pTtemp = (MaterialDesc*)pOutBuffer; assert(pTtemp->_sizeOfMaterialBuffer == o_lengthOfWholerMaterialBuffer); // Third, add this MaterialDesc buffer to the Material Map. std::string mat_path(i_pBinaryMaterialFile); std::string key = GetFileNameWithoutExtension(mat_path.c_str()); MaterialManager::GetInstance()->AddMaterialDesc(key.c_str(), pOutBuffer); SAFE_DELETE(pBuffer); }
/** Allocates resources for a new in-memory image of the specified width and height. @param[in] Width Desired image width. @param[in] Height Desired image height. @retval IMAGE* Pointer to a zero-initialized memory location ready to receive pixel data up to the width and height specified. **/ IMAGE* CreateImage( IN UINTN Width, IN UINTN Height) { IMAGE *Image; Image = (IMAGE *)AllocatePool(sizeof(IMAGE)); if (Image == NULL) { return NULL; } Image->Width = Width; Image->Height = Height; Image->PixelData = (EFI_UGA_PIXEL *)AllocatePool(Width * Height * sizeof(EFI_UGA_PIXEL)); if (Image->PixelData == NULL) { DestroyImage(Image); return NULL; } SetMem(Image->PixelData, sizeof Image->PixelData, 0); return Image; }
/** Used to translate a device path node to a Target ID and LUN. @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. @param[in] DevicePath A pointer to a single device path node that describes the SCSI device on the SCSI channel. @param[out] Target A pointer to the Target Array which represents the ID of a SCSI device on the SCSI channel. @param[out] Lun A pointer to the LUN of a SCSI device on the SCSI channel. @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and LUN, and they were returned in Target and Lun. @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL. @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN does not exist.Currently not implemented. @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath. **/ EFI_STATUS EFIAPI IScsiExtScsiPassThruGetTargetLun ( IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 **Target, OUT UINT64 *Lun ) { ISCSI_DRIVER_DATA *Private; ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData; if ((DevicePath == NULL) || (Target == NULL) || (Lun == NULL)) { return EFI_INVALID_PARAMETER; } if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || (DevicePath->SubType != MSG_ISCSI_DP) || (DevicePathNodeLength (DevicePath) <= sizeof (ISCSI_DEVICE_PATH)) ) { return EFI_UNSUPPORTED; } Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This); ConfigNvData = &Private->Session.ConfigData.NvData; SetMem (*Target, TARGET_MAX_BYTES, 0xFF); (*Target)[0] = 0; if (AsciiStrCmp (ConfigNvData->TargetName, (CHAR8 *) DevicePath + sizeof (ISCSI_DEVICE_PATH)) != 0) { return EFI_UNSUPPORTED; } CopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64)); return EFI_SUCCESS; }
/** Initialization for Fault Tolerant Write protocol. @param[in, out] FtwDevice Pointer to the FTW device structure @retval EFI_SUCCESS Initialize the FTW protocol successfully. @retval EFI_NOT_FOUND No proper FVB protocol was found. **/ EFI_STATUS InitFtwProtocol ( IN OUT EFI_FTW_DEVICE *FtwDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; UINTN Length; EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader; UINTN Offset; EFI_HANDLE FvbHandle; // // Find the right SMM Fvb protocol instance for FTW. // Status = FindFvbForFtw (FtwDevice); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } // // Calculate the start LBA of working block. Working block is an area which // contains working space in its last block and has the same size as spare // block, unless there are not enough blocks before the block that contains // working space. // FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1; ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0); // // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE. // FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1); FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace; FtwDevice->FtwLastWriteHeader = NULL; FtwDevice->FtwLastWriteRecord = NULL; // // Refresh the working space data from working block // Status = WorkSpaceRefresh (FtwDevice); ASSERT_EFI_ERROR (Status); // // If the working block workspace is not valid, try the spare block // if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { // // Read from spare block // Length = FtwDevice->FtwWorkSpaceSize; Status = FtwDevice->FtwBackupFvb->Read ( FtwDevice->FtwBackupFvb, FtwDevice->FtwSpareLba, FtwDevice->FtwWorkSpaceBase, &Length, FtwDevice->FtwWorkSpace ); ASSERT_EFI_ERROR (Status); // // If spare block is valid, then replace working block content. // if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { Status = FlushSpareBlockToWorkingBlock (FtwDevice); DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in InitFtwProtocol() - %r\n", Status)); FtwAbort (&FtwDevice->FtwInstance); // // Refresh work space. // Status = WorkSpaceRefresh (FtwDevice); ASSERT_EFI_ERROR (Status); } else { DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n")); // // If both are invalid, then initialize work space. // SetMem ( FtwDevice->FtwWorkSpace, FtwDevice->FtwWorkSpaceSize, FTW_ERASED_BYTE ); InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader); // // Initialize the work space // Status = FtwReclaimWorkSpace (FtwDevice, FALSE); ASSERT_EFI_ERROR (Status); } } // // If the FtwDevice->FtwLastWriteRecord is 1st record of write header && // (! SpareComplete) THEN call Abort(). // if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) && (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) && IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) ) { DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n")); FtwAbort (&FtwDevice->FtwInstance); } // // If Header is incompleted and the last record has completed, then // call Abort() to set the Header->Complete FLAG. // if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) && IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) ) { DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n")); FtwAbort (&FtwDevice->FtwInstance); } // // To check the workspace buffer following last Write header/records is EMPTY or not. // If it's not EMPTY, FTW also need to call reclaim(). // FtwHeader = FtwDevice->FtwLastWriteHeader; Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace; if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) { Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize); } if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) { Status = FtwReclaimWorkSpace (FtwDevice, TRUE); ASSERT_EFI_ERROR (Status); } // // Restart if it's boot block // if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) ) { if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) { Status = FlushSpareBlockToBootBlock (FtwDevice); DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status)); ASSERT_EFI_ERROR (Status); FtwAbort (&FtwDevice->FtwInstance); } else { // // if (SpareCompleted) THEN Restart to fault tolerant write. // FvbHandle = NULL; FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb); if (FvbHandle != NULL) { Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle); DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status)); ASSERT_EFI_ERROR (Status); } FtwAbort (&FtwDevice->FtwInstance); } } // // Hook the protocol API // FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize; FtwDevice->FtwInstance.Allocate = FtwAllocate; FtwDevice->FtwInstance.Write = FtwWrite; FtwDevice->FtwInstance.Restart = FtwRestart; FtwDevice->FtwInstance.Abort = FtwAbort; FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite; return EFI_SUCCESS; }
/** The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s. @return The memset function returns the value of s. **/ void * memset(void *s, int c, size_t n) { return SetMem( s, (UINTN)n, (UINT8)c); }
/** Initialize the Event Log and log events passed from the PEI phase. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES Out of memory. **/ EFI_STATUS EFIAPI SetupEventLog ( VOID ) { EFI_STATUS Status; TCG_PCR_EVENT *TcgEvent; EFI_PEI_HOB_POINTERS GuidHob; EFI_PHYSICAL_ADDRESS Lasa; if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) { Lasa = mTcgClientAcpiTemplate.Lasa; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)), &Lasa ); if (EFI_ERROR (Status)) { return Status; } mTcgClientAcpiTemplate.Lasa = Lasa; // // To initialize them as 0xFF is recommended // because the OS can know the last entry for that. // SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF); mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen); } else { Lasa = mTcgServerAcpiTemplate.Lasa; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)), &Lasa ); if (EFI_ERROR (Status)) { return Status; } mTcgServerAcpiTemplate.Lasa = Lasa; // // To initialize them as 0xFF is recommended // because the OS can know the last entry for that. // SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF); mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen); } GuidHob.Raw = GetHobList (); while (!EFI_ERROR (Status) && (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) { TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid); GuidHob.Raw = GET_NEXT_HOB (GuidHob); Status = TcgDxeLogEventI ( &mTcgDxeData, (TCG_PCR_EVENT_HDR*)TcgEvent, TcgEvent->Event ); } return Status; }
/** Retrieves the recovery capsule in root directory of the current volume. @param PrivateData The private data structure that contains recovery module information. @param BlockIoPpi The Block IO PPI used to access the volume. @param BlockIo2Ppi The Block IO 2 PPI used to access the volume. @param IndexBlockDevice The index of current block device. @param Lba The starting logic block address to retrieve capsule. @retval EFI_SUCCESS The recovery capsule is successfully found in the volume. @retval EFI_NOT_FOUND The recovery capsule is not found in the volume. @retval Others **/ EFI_STATUS EFIAPI RetrieveCapsuleFileFromRoot ( IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData, IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi, IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi, IN UINTN IndexBlockDevice, IN UINT32 Lba ) { EFI_STATUS Status; UINTN BufferSize; UINT8 *Buffer; PEI_CD_EXPRESS_DIR_FILE_RECORD *FileRecord; UINTN Index; Buffer = PrivateData->BlockBuffer; BufferSize = PEI_CD_BLOCK_SIZE; SetMem (Buffer, BufferSize, 0); if (BlockIo2Ppi != NULL) { Status = BlockIo2Ppi->ReadBlocks ( (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), BlockIo2Ppi, IndexBlockDevice, Lba, BufferSize, Buffer ); } else { Status = BlockIoPpi->ReadBlocks ( (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), BlockIoPpi, IndexBlockDevice, Lba, BufferSize, Buffer ); } if (EFI_ERROR (Status)) { return Status; } while (1) { FileRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *) Buffer; if (FileRecord->Length == 0) { break; } // // Not intend to check other flag now // if ((FileRecord->Flag & PEI_CD_EXPRESS_DIR_FILE_REC_FLAG_ISDIR) != 0) { Buffer += FileRecord->Length; continue; } for (Index = 0; Index < FileRecord->FileIDLength; Index++) { if (FileRecord->FileID[Index] == ';') { break; } } if (Index != (sizeof (PEI_RECOVERY_FILE_NAME) - 1)) { Buffer += FileRecord->Length; continue; } if (!StringCmp (FileRecord->FileID, (UINT8 *) PEI_RECOVERY_FILE_NAME, sizeof (PEI_RECOVERY_FILE_NAME) - 1, FALSE)) { Buffer += FileRecord->Length; continue; } PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleStartLBA = FileRecord->LocationOfExtent[0]; PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleSize = ( FileRecord->DataLength[0] / PEI_CD_BLOCK_SIZE + 1 ) * PEI_CD_BLOCK_SIZE; return EFI_SUCCESS; } return EFI_NOT_FOUND; }
/** Show progress bar with title above it. It only works in Graphics mode. @param TitleForeground Foreground color for Title. @param TitleBackground Background color for Title. @param Title Title above progress bar. @param ProgressColor Progress bar color. @param Progress Progress (0-100) @param PreviousValue The previous value of the progress. @retval EFI_STATUS Success update the progress bar **/ EFI_STATUS PlatformBdsShowProgress ( IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, IN CHAR16 *Title, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, IN UINTN Progress, IN UINTN PreviousValue ) { EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_UGA_DRAW_PROTOCOL *UgaDraw; UINT32 SizeOfX; UINT32 SizeOfY; UINT32 ColorDepth; UINT32 RefreshRate; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; UINTN BlockHeight; UINTN BlockWidth; UINTN BlockNum; UINTN PosX; UINTN PosY; UINTN Index; if (Progress > 100) { return EFI_INVALID_PARAMETER; } UgaDraw = NULL; Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput ); if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { GraphicsOutput = NULL; Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw ); } if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } SizeOfX = 0; SizeOfY = 0; if (GraphicsOutput != NULL) { SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; } else if (UgaDraw != NULL) { Status = UgaDraw->GetMode ( UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } } else { return EFI_UNSUPPORTED; } BlockWidth = SizeOfX / 100; BlockHeight = SizeOfY / 50; BlockNum = Progress; PosX = 0; PosY = SizeOfY * 48 / 50; if (BlockNum == 0) { // // Clear progress area // SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, &Color, EfiBltVideoFill, 0, 0, 0, PosY - EFI_GLYPH_HEIGHT - 1, SizeOfX, SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) &Color, EfiUgaVideoFill, 0, 0, 0, PosY - EFI_GLYPH_HEIGHT - 1, SizeOfX, SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), SizeOfX * sizeof (EFI_UGA_PIXEL) ); } else { return EFI_UNSUPPORTED; } } // // Show progress by drawing blocks // for (Index = PreviousValue; Index < BlockNum; Index++) { PosX = Index * BlockWidth; if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, &ProgressColor, EfiBltVideoFill, 0, 0, PosX, PosY, BlockWidth - 1, BlockHeight, (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) &ProgressColor, EfiUgaVideoFill, 0, 0, PosX, PosY, BlockWidth - 1, BlockHeight, (BlockWidth) * sizeof (EFI_UGA_PIXEL) ); } else { return EFI_UNSUPPORTED; } } PrintXY ( (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2, PosY - EFI_GLYPH_HEIGHT - 1, &TitleForeground, &TitleBackground, Title ); return EFI_SUCCESS; }
/** Erases and initializes a firmware volume block. The EraseBlocks() function erases one or more blocks as denoted by the variable argument list. The entire parameter list of blocks must be verified before erasing any blocks. If a block is requested that does not exist within the associated firmware volume (it has a larger index than the last block of the firmware volume), the EraseBlocks() function must return the status code EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. Implementations should be mindful that the firmware volume might be in the WriteDisabled state. If it is in this state, the EraseBlocks() function must return the status code EFI_ACCESS_DENIED without modifying the contents of the firmware volume. All calls to EraseBlocks() must be fully flushed to the hardware before the EraseBlocks() service returns. @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. @param ... The variable argument list is a list of tuples. Each tuple describes a range of LBAs to erase and consists of the following: - An EFI_LBA that indicates the starting LBA - A UINTN that indicates the number of blocks to erase The list is terminated with an EFI_LBA_LIST_TERMINATOR. For example, the following indicates that two ranges of blocks (5-7 and 10-11) are to be erased: EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); @retval EFI_SUCCESS The erase request was successfully completed. @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. The firmware device may have been partially erased. @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do not exist in the firmware volume. **/ EFI_STATUS EFIAPI FvbProtocolEraseBlocks ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ... ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; VA_LIST args; EFI_LBA StartingLba; UINTN NumOfLba; UINT8 Erase; VOID *ErasePtr; UINTN EraseSize; FvbDevice = FVB_DEVICE_FROM_THIS (This); Erase = 0; VA_START (args, This); do { StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } NumOfLba = VA_ARG (args, UINT32); // // Check input parameters // if ((NumOfLba == 0) || (StartingLba > 1) || ((StartingLba + NumOfLba) > 2)) { VA_END (args); return EFI_INVALID_PARAMETER; } if (StartingLba == 0) { Erase = (UINT8) (Erase | BIT0); } if ((StartingLba + NumOfLba) == 2) { Erase = (UINT8) (Erase | BIT1); } } while (1); VA_END (args); ErasePtr = (UINT8*) FvbDevice->BufferPtr; EraseSize = 0; if ((Erase & BIT0) != 0) { EraseSize = EraseSize + FvbDevice->BlockSize; } else { ErasePtr = (VOID*) ((UINT8*)ErasePtr + FvbDevice->BlockSize); } if ((Erase & BIT1) != 0) { EraseSize = EraseSize + FvbDevice->BlockSize; } if (EraseSize != 0) { SetMem ( (VOID*) ErasePtr, EraseSize, ERASED_UINT8 ); VA_START (args, This); PlatformFvbBlocksErased (This, args); VA_END (args); } return EFI_SUCCESS; }
/** Start this driver on ControllerHandle. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Start() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle @retval other This driver does not support this device **/ EFI_STATUS EFIAPI SCSIBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { UINT64 Lun; UINT8 *TargetId; BOOLEAN ScanOtherPuns; BOOLEAN FromFirstTarget; BOOLEAN ExtScsiSupport; EFI_STATUS Status; EFI_STATUS DevicePathStatus; EFI_STATUS PassThruStatus; SCSI_BUS_DEVICE *ScsiBusDev; SCSI_TARGET_ID ScsiTargetId; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface; EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface; EFI_SCSI_BUS_PROTOCOL *BusIdentify; TargetId = NULL; ScanOtherPuns = TRUE; FromFirstTarget = FALSE; ExtScsiSupport = FALSE; PassThruStatus = EFI_SUCCESS; TargetId = &ScsiTargetId.ScsiId.ExtScsi[0]; SetMem (TargetId, TARGET_MAX_BYTES, 0xFF); DevicePathStatus = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) { return DevicePathStatus; } // // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead. // Status = gBS->OpenProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, (VOID **) &ExtScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); // // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead. // if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { Status = gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **) &ScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); // // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time. // if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { if (!EFI_ERROR(DevicePathStatus)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; } } else { // // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol // with BY_DRIVER if it is also present on the handle. The intent is to prevent // another SCSI Bus Driver to work on the same host handle. // ExtScsiSupport = TRUE; PassThruStatus = gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **) &ScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); } if (Status != EFI_ALREADY_STARTED) { // // Go through here means either ExtPassThru or PassThru Protocol is successfully opened // on this handle for this time. Then construct Host controller private data. // ScsiBusDev = NULL; ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE)); if (ScsiBusDev == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE; ScsiBusDev->ExtScsiSupport = ExtScsiSupport; ScsiBusDev->DevicePath = ParentDevicePath; if (ScsiBusDev->ExtScsiSupport) { ScsiBusDev->ExtScsiInterface = ExtScsiInterface; } else { ScsiBusDev->ScsiInterface = ScsiInterface; } // // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol. // Status = gBS->InstallProtocolInterface ( &Controller, &gEfiCallerIdGuid, EFI_NATIVE_INTERFACE, &ScsiBusDev->BusIdentify ); if (EFI_ERROR (Status)) { goto ErrorExit; } } else { // // Go through here means Start() is re-invoked again, nothing special is required to do except // picking up Host controller private information. // Status = gBS->OpenProtocol ( Controller, &gEfiCallerIdGuid, (VOID **) &BusIdentify, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify); } Lun = 0; if (RemainingDevicePath == NULL) { // // If RemainingDevicePath is NULL, // must enumerate all SCSI devices anyway // FromFirstTarget = TRUE; } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // if (ScsiBusDev->ExtScsiSupport) { Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun); } else { Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun); } if (EFI_ERROR (Status)) { return Status; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // ScanOtherPuns = FALSE; } while(ScanOtherPuns) { if (FromFirstTarget) { // // Remaining Device Path is NULL, scan all the possible Puns in the // SCSI Channel. // if (ScsiBusDev->ExtScsiSupport) { Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun); } else { Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun); } if (EFI_ERROR (Status)) { // // no legal Pun and Lun found any more // break; } } else { ScanOtherPuns = FALSE; } // // Avoid creating handle for the host adapter. // if (ScsiBusDev->ExtScsiSupport) { if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) { continue; } } else { if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) { continue; } } // // Scan for the scsi device, if it attaches to the scsi bus, // then create handle and install scsi i/o protocol. // Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev); } return EFI_SUCCESS; ErrorExit: if (ScsiBusDev != NULL) { FreePool (ScsiBusDev); } if (ExtScsiSupport) { gBS->CloseProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); if (!EFI_ERROR (PassThruStatus)) { gBS->CloseProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); } } else { gBS->CloseProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
/** Test to see if this driver supports ControllerHandle. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Supported() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to test @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device @retval EFI_ALREADY_STARTED This driver is already running on this device @retval other This driver does not support this device **/ EFI_STATUS EFIAPI SCSIBusDriverBindingSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_SCSI_PASS_THRU_PROTOCOL *PassThru; EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru; UINT64 Lun; UINT8 *TargetId; SCSI_TARGET_ID ScsiTargetId; TargetId = &ScsiTargetId.ScsiId.ExtScsi[0]; SetMem (TargetId, TARGET_MAX_BYTES, 0xFF); // // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead. // Status = gBS->OpenProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, (VOID **)&ExtPassThru, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (Status == EFI_ALREADY_STARTED) { return EFI_SUCCESS; } else if (!EFI_ERROR(Status)) { // // Check if RemainingDevicePath is NULL or the End of Device Path Node, // if yes, return EFI_SUCCESS. // if ((RemainingDevicePath == NULL) || IsDevicePathEnd (RemainingDevicePath)) { // // Close protocol regardless of RemainingDevicePath validation // gBS->CloseProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_SUCCESS; } else { // // If RemainingDevicePath isn't the End of Device Path Node, check its validation // Status = ExtPassThru->GetTargetLun (ExtPassThru, RemainingDevicePath, &TargetId, &Lun); // // Close protocol regardless of RemainingDevicePath validation // gBS->CloseProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); if (!EFI_ERROR(Status)) { return EFI_SUCCESS; } } } // // Come here in 2 condition: // 1. ExtPassThru doesn't exist. // 2. ExtPassThru exists but RemainingDevicePath is invalid. // Status = gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **)&PassThru, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (Status == EFI_ALREADY_STARTED) { return EFI_SUCCESS; } if (EFI_ERROR (Status)) { return Status; } // // Test RemainingDevicePath is valid or not. // if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) { Status = PassThru->GetTargetLun (PassThru, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun); } gBS->CloseProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
EFI_STATUS AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN TableHandle; UINT32 FvStatus; UINTN Size; EFI_ACPI_TABLE_VERSION Version; QNC_DEVICE_ENABLES QNCDeviceEnables; EFI_HANDLE Handle; UINTN Index; PCI_DEVICE_INFO *PciDeviceInfo; EFI_ACPI_HANDLE PciRootHandle; BOOLEAN UpdatePRT; BOOLEAN UpdatePRW; PCI_DEVICE_SETTING *mConfigData; Instance = 0; TableHandle = 0; CurrentTable = NULL; mConfigData = NULL; QNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables); // // Initialize the EFI Driver Library // ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512); Status = gBS->AllocatePool ( EfiACPIMemoryNVS, sizeof (EFI_GLOBAL_NVS_AREA), (VOID**)&mGlobalNvsArea.Area ); Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gEfiGlobalNvsAreaProtocolGuid, EFI_NATIVE_INTERFACE, &mGlobalNvsArea ); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { SetMem ( mGlobalNvsArea.Area, sizeof (EFI_GLOBAL_NVS_AREA), 0 ); } // // Initialize the data. Eventually, this will be controlled by setup options. // mGlobalNvsArea.Area->HpetEnable = PcdGetBool (PcdHpetEnable); mGlobalNvsArea.Area->Pm1blkIoBaseAddress = PcdGet16(PcdPm1blkIoBaseAddress); mGlobalNvsArea.Area->PmbaIoBaseAddress = PcdGet16(PcdPmbaIoBaseAddress); mGlobalNvsArea.Area->Gpe0blkIoBaseAddress = PcdGet16(PcdGpe0blkIoBaseAddress); mGlobalNvsArea.Area->GbaIoBaseAddress = PcdGet16(PcdGbaIoBaseAddress); mGlobalNvsArea.Area->SmbaIoBaseAddress = PcdGet16(PcdSmbaIoBaseAddress); mGlobalNvsArea.Area->SpiDmaIoBaseAddress = PcdGet16(PcdSpiDmaIoBaseAddress); mGlobalNvsArea.Area->WdtbaIoBaseAddress = PcdGet16(PcdWdtbaIoBaseAddress); mGlobalNvsArea.Area->HpetBaseAddress = (UINT32)PcdGet64(PcdHpetBaseAddress); mGlobalNvsArea.Area->HpetSize = (UINT32)PcdGet64(PcdHpetSize); mGlobalNvsArea.Area->PciExpressBaseAddress= (UINT32)PcdGet64(PcdPciExpressBaseAddress); mGlobalNvsArea.Area->PciExpressSize = (UINT32)PcdGet64(PcdPciExpressSize); mGlobalNvsArea.Area->RcbaMmioBaseAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress); mGlobalNvsArea.Area->RcbaMmioSize = (UINT32)PcdGet64(PcdRcbaMmioSize); mGlobalNvsArea.Area->IoApicBaseAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress); mGlobalNvsArea.Area->IoApicSize = (UINT32)PcdGet64(PcdIoApicSize); mGlobalNvsArea.Area->TpmPresent = (UINT32)(FALSE); // // Find the AcpiTable protocol // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Initialize MADT table // Status = MadtTableInitialize (&CurrentTable, &Size); ASSERT_EFI_ERROR (Status); // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle ); ASSERT_EFI_ERROR (Status); CurrentTable = NULL; // // Init Pci Device PRT PRW information structure from PCD // mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING)); ASSERT_EFI_ERROR (mConfigData); InitPciDeviceInfoStructure (mConfigData); // // Get the Acpi SDT protocol for manipulation on acpi table // Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt); ASSERT_EFI_ERROR (Status); // // Locate the firmware volume protocol // Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Read tables from the storage file. // while (Status == EFI_SUCCESS) { Status = FwVol->ReadSection ( FwVol, (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), EFI_SECTION_RAW, Instance, (VOID**)&CurrentTable, &Size, &FvStatus ); if (!EFI_ERROR(Status)) { // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length, &TableHandle ); if (EFI_ERROR(Status)) { return EFI_ABORTED; } // // If this table is the DSDT table, then update the _PRT and _PRW based on // the settings from pcds // if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { // // Create the root handle for DSDT table // Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle); ASSERT_EFI_ERROR (Status); PciRootHandle = NULL; PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle); ASSERT (PciRootHandle != NULL); PciDeviceInfo = NULL; for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) { PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]); // // Check whether this is a valid item // if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) { //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress)); UpdatePRT = FALSE; UpdatePRW = FALSE; SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW); // // Check whether there is any valid pci routing item // if (UpdatePRT) { // // Update the pci routing information // //DEBUG ((EFI_D_ERROR, "Update _PRT\n")); SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo); } // // Check whether there is any valid pci routing item // if (UpdatePRW) { // // Update the pci wakeup information // //DEBUG ((EFI_D_ERROR, "Update _PRW\n")); SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo); } } } Status = mAcpiSdt->Close (PciRootHandle); ASSERT_EFI_ERROR (Status); // // Mark the root handle as modified , let SDT protocol recaculate the checksum // ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE; Status = mAcpiSdt->Close (mDsdtHandle); ASSERT_EFI_ERROR (Status); } // // Increment the instance // Instance++; CurrentTable = NULL; } } gBS->FreePool (mConfigData); return EFI_SUCCESS; }
void UniformPool::ResetBuffer() { SetMem(_pBuffer, _sizeOfBuffer, 0); }
/** Parse the DHCP ACK to get Dns4 server information. @param Instance The DNS instance. @param DnsServerCount Retrieved Dns4 server Ip count. @param DnsServerList Retrieved Dns4 server Ip list. @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. **/ EFI_STATUS GetDns4ServerFromDhcp4 ( IN DNS_INSTANCE *Instance, OUT UINT32 *DnsServerCount, OUT EFI_IPv4_ADDRESS **DnsServerList ) { EFI_STATUS Status; EFI_HANDLE Image; EFI_HANDLE Controller; EFI_STATUS MediaStatus; EFI_HANDLE MnpChildHandle; EFI_MANAGED_NETWORK_PROTOCOL *Mnp; EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData; EFI_HANDLE Dhcp4Handle; EFI_DHCP4_PROTOCOL *Dhcp4; EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; UINTN DataSize; VOID *Data; EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo; EFI_DHCP4_PACKET SeedPacket; EFI_DHCP4_PACKET_OPTION *ParaList[2]; DNS4_SERVER_INFOR DnsServerInfor; EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token; BOOLEAN IsDone; UINTN Index; Image = Instance->Service->ImageHandle; Controller = Instance->Service->ControllerHandle; MnpChildHandle = NULL; Mnp = NULL; Dhcp4Handle = NULL; Dhcp4 = NULL; Ip4Config2 = NULL; DataSize = 0; Data = NULL; InterfaceInfo = NULL; ZeroMem ((UINT8 *) ParaList, sizeof (ParaList)); ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA)); ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR)); ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN)); DnsServerInfor.ServerCount = DnsServerCount; IsDone = FALSE; // // Check media. // MediaStatus = EFI_SUCCESS; NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus); if (MediaStatus != EFI_SUCCESS) { return EFI_NO_MEDIA; } // // Create a Mnp child instance, get the protocol and config for it. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiManagedNetworkServiceBindingProtocolGuid, &MnpChildHandle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( MnpChildHandle, &gEfiManagedNetworkProtocolGuid, (VOID **) &Mnp, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } MnpConfigData.ReceivedQueueTimeoutValue = 0; MnpConfigData.TransmitQueueTimeoutValue = 0; MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO; MnpConfigData.EnableUnicastReceive = TRUE; MnpConfigData.EnableMulticastReceive = TRUE; MnpConfigData.EnableBroadcastReceive = TRUE; MnpConfigData.EnablePromiscuousReceive = FALSE; MnpConfigData.FlushQueuesOnReset = TRUE; MnpConfigData.EnableReceiveTimestamps = FALSE; MnpConfigData.DisableBackgroundPolling = FALSE; Status = Mnp->Configure(Mnp, &MnpConfigData); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Create a DHCP4 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDhcp4ServiceBindingProtocolGuid, &Dhcp4Handle ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = gBS->OpenProtocol ( Dhcp4Handle, &gEfiDhcp4ProtocolGuid, (VOID **) &Dhcp4, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Get Ip4Config2 instance info. // Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data); if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { goto ON_EXIT; } Data = AllocateZeroPool (DataSize); if (Data == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data); if (EFI_ERROR (Status)) { goto ON_EXIT; } InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data; // // Build required Token. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, DhcpCommonNotify, &IsDone, &Token.CompletionEvent ); if (EFI_ERROR (Status)) { goto ON_EXIT; } SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff); Token.RemotePort = 67; Token.ListenPointCount = 1; Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT)); if (Token.ListenPoints == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } if (Instance->Dns4CfgData.UseDefaultSetting) { CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS)); CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS)); } else { CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS)); CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS)); } Token.ListenPoints[0].ListenPort = 68; Token.TimeoutValue = DNS_TIME_TO_GETMAP; DnsInitSeedPacket (&SeedPacket, InterfaceInfo); ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION)); if (ParaList[0] == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } ParaList[0]->OpCode = DHCP4_TAG_TYPE; ParaList[0]->Length = 1; ParaList[0]->Data[0] = DHCP4_MSG_REQUEST; ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION)); if (ParaList[1] == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } ParaList[1]->OpCode = DHCP4_TAG_PARA_LIST; ParaList[1]->Length = 1; ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER; Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet); Token.Packet->Dhcp4.Header.Xid = HTONL(NET_RANDOM (NetRandomInitSeed ())); Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000); if (Instance->Dns4CfgData.UseDefaultSetting) { CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS)); } else { CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS)); } CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize); Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize); // // TransmitReceive Token // Status = Dhcp4->TransmitReceive (Dhcp4, &Token); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Poll the packet // do { Status = Mnp->Poll (Mnp); } while (!IsDone); // // Parse the ACK to get required information if received done. // if (IsDone && !EFI_ERROR (Token.Status)) { for (Index = 0; Index < Token.ResponseCount; Index++) { Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor); if (!EFI_ERROR (Status)) { break; } } *DnsServerList = DnsServerInfor.ServerList; } else { Status = Token.Status; } ON_EXIT: if (Data != NULL) { FreePool (Data); } for (Index = 0; Index < 2; Index++) { if (ParaList[Index] != NULL) { FreePool (ParaList[Index]); } } if (Token.ListenPoints) { FreePool (Token.ListenPoints); } if (Token.Packet) { FreePool (Token.Packet); } if (Token.ResponseList != NULL) { FreePool (Token.ResponseList); } if (Token.CompletionEvent != NULL) { gBS->CloseEvent (Token.CompletionEvent); } if (Dhcp4 != NULL) { Dhcp4->Stop (Dhcp4); Dhcp4->Configure (Dhcp4, NULL); gBS->CloseProtocol ( Dhcp4Handle, &gEfiDhcp4ProtocolGuid, Image, Controller ); } if (Dhcp4Handle != NULL) { NetLibDestroyServiceChild ( Controller, Image, &gEfiDhcp4ServiceBindingProtocolGuid, Dhcp4Handle ); } if (Mnp != NULL) { Mnp->Configure (Mnp, NULL); gBS->CloseProtocol ( MnpChildHandle, &gEfiManagedNetworkProtocolGuid, Image, Controller ); } NetLibDestroyServiceChild ( Controller, Image, &gEfiManagedNetworkServiceBindingProtocolGuid, MnpChildHandle ); return Status; }
EFIAPI ShellCommandConsistMappingGenMappingName ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN EFI_DEVICE_PATH_PROTOCOL **Table ) { POOL_PRINT Str; DEVICE_CONSIST_MAPPING_INFO MappingInfo; EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; UINTN Index; UINTN NewSize; ASSERT(DevicePath != NULL); ASSERT(Table != NULL); HIDevicePath = GetHIDevicePath (DevicePath); if (HIDevicePath == NULL) { return NULL; } for (Index = 0; Table[Index] != NULL; Index++) { if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) { break; } } FreePool (HIDevicePath); if (Table[Index] == NULL) { return NULL; } MappingInfo.Hi = Index; MappingInfo.Mtd = MTDTypeUnknown; MappingInfo.Digital = FALSE; GetDeviceConsistMappingInfo (&MappingInfo, DevicePath); SetMem (&Str, sizeof (Str), 0); for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) { if (MappingInfo.Mtd == mMTDName[Index].MTDType) { break; } } if (mMTDName[Index].MTDType != MTDTypeEnd) { CatPrint (&Str, L"%s", mMTDName[Index].Name); } CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi); if (MappingInfo.Csd.Str != NULL) { CatPrint (&Str, L"%s", MappingInfo.Csd.Str); FreePool (MappingInfo.Csd.Str); } if (Str.Str != NULL) { CatPrint (&Str, L":"); } NewSize = (Str.Len + 1) * sizeof (CHAR16); Str.Str = ReallocatePool (Str.Len, NewSize, Str.Str); if (Str.Str == NULL) { return (NULL); } Str.Str[Str.Len] = CHAR_NULL; return Str.Str; }
/** Perform the memory test base on the memory test intensive level, and update the memory resource. @param Level The memory test intensive level. @retval EFI_STATUS Success test all the system memory and update the memory resource **/ EFI_STATUS EFIAPI BdsMemoryTest ( IN EXTENDMEM_COVERAGE_LEVEL Level ) { EFI_STATUS Status; EFI_STATUS KeyStatus; EFI_STATUS InitStatus; EFI_STATUS ReturnStatus; BOOLEAN RequireSoftECCInit; EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; UINT64 TestedMemorySize; UINT64 TotalMemorySize; UINTN TestPercent; UINT64 PreviousValue; BOOLEAN ErrorOut; BOOLEAN TestAbort; EFI_INPUT_KEY Key; CHAR16 StrPercent[80]; CHAR16 *StrTotalMemory; CHAR16 *Pos; CHAR16 *TmpStr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; BOOLEAN IsFirstBoot; UINT32 TempData; UINTN StrTotalMemorySize; ReturnStatus = EFI_SUCCESS; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); StrTotalMemorySize = 128; Pos = AllocateZeroPool (StrTotalMemorySize); if (Pos == NULL) { return ReturnStatus; } StrTotalMemory = Pos; TestedMemorySize = 0; TotalMemorySize = 0; PreviousValue = 0; ErrorOut = FALSE; TestAbort = FALSE; SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); RequireSoftECCInit = FALSE; Status = gBS->LocateProtocol ( &gEfiGenericMemTestProtocolGuid, NULL, (VOID **) &GenMemoryTest ); if (EFI_ERROR (Status)) { FreePool (Pos); return EFI_SUCCESS; } InitStatus = GenMemoryTest->MemoryTestInit ( GenMemoryTest, Level, &RequireSoftECCInit ); if (InitStatus == EFI_NO_MEDIA) { // // The PEI codes also have the relevant memory test code to check the memory, // it can select to test some range of the memory or all of them. If PEI code // checks all the memory, this BDS memory test will has no not-test memory to // do the test, and then the status of EFI_NO_MEDIA will be returned by // "MemoryTestInit". So it does not need to test memory again, just return. // FreePool (Pos); return EFI_SUCCESS; } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } } else { DEBUG ((EFI_D_INFO, "Enter memory test.\n")); } do { Status = GenMemoryTest->PerformMemoryTest ( GenMemoryTest, &TestedMemorySize, &TotalMemorySize, &ErrorOut, TestAbort ); if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } ASSERT (0); } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); TestPercent = (UINTN) DivU64x32 ( DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), TempData ); if (TestPercent != PreviousValue) { UnicodeValueToString (StrPercent, 0, TestPercent, 0); TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); if (TmpStr != NULL) { // // TmpStr size is 64, StrPercent is reserved to 16. // StrCatS (StrPercent, sizeof (StrPercent) / sizeof (CHAR16), TmpStr); PrintXY (10, 10, NULL, NULL, StrPercent); FreePool (TmpStr); } TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, TestPercent, (UINTN) PreviousValue ); FreePool (TmpStr); } } PreviousValue = TestPercent; } else { DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); } if (!PcdGetBool (PcdConInConnectOnDemand)) { KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { if (!RequireSoftECCInit) { if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, 100, (UINTN) PreviousValue ); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, L"100"); } Status = GenMemoryTest->Finished (GenMemoryTest); goto Done; } TestAbort = TRUE; } } } while (Status != EFI_NOT_FOUND); Status = GenMemoryTest->Finished (GenMemoryTest); Done: if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); if (StrTotalMemory[0] == L',') { StrTotalMemory++; StrTotalMemorySize -= sizeof (CHAR16); } TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); if (TmpStr != NULL) { StrCatS (StrTotalMemory, StrTotalMemorySize / sizeof (CHAR16), TmpStr); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, StrTotalMemory); PlatformBdsShowProgress ( Foreground, Background, StrTotalMemory, Color, 100, (UINTN) PreviousValue ); } else { DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); } FreePool (Pos); // // Use a DynamicHii type pcd to save the boot status, which is used to // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. // IsFirstBoot = PcdGetBool(PcdBootState); if (IsFirstBoot) { PcdSetBool(PcdBootState, FALSE); } return ReturnStatus; }
/** Main entry point. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS Successfully initialized. **/ EFI_STATUS EFIAPI FvbInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; VOID *Ptr; VOID *SubPtr; BOOLEAN Initialize; EFI_HANDLE Handle; EFI_PHYSICAL_ADDRESS Address; RETURN_STATUS PcdStatus; DEBUG ((EFI_D_INFO, "EMU Variable FVB Started\n")); // // Verify that the PCD's are set correctly. // if ( (PcdGet32 (PcdVariableStoreSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) ) > EMU_FVB_BLOCK_SIZE ) { DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizes\n")); return EFI_INVALID_PARAMETER; } if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) { DEBUG ((EFI_D_INFO, "Disabling EMU Variable FVB since " "flash variables appear to be supported.\n")); return EFI_ABORTED; } // // By default we will initialize the FV contents. But, if // PcdEmuVariableNvStoreReserved is non-zero, then we will // use this location for our buffer. // // If this location does not have a proper FV header, then // we will initialize it. // Initialize = TRUE; if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) { Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved); DEBUG (( EFI_D_INFO, "EMU Variable FVB: Using pre-reserved block at %p\n", Ptr )); Status = ValidateFvHeader (Ptr); if (!EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FV\n")); Initialize = FALSE; } } else { Ptr = AllocateAlignedRuntimePages ( EFI_SIZE_TO_PAGES (EMU_FVB_SIZE), SIZE_64KB ); } mEmuVarsFvb.BufferPtr = Ptr; // // Initialize the main FV header and variable store header // if (Initialize) { SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8); InitializeFvAndVariableStoreHeaders (Ptr); } PcdStatus = PcdSet64S (PcdFlashNvStorageVariableBase64, (UINT32)(UINTN) Ptr); ASSERT_RETURN_ERROR (PcdStatus); // // Initialize the Fault Tolerant Write data area // SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize)); PcdStatus = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr); ASSERT_RETURN_ERROR (PcdStatus); // // Initialize the Fault Tolerant Write spare block // SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE); PcdStatus = PcdSet32S (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr); ASSERT_RETURN_ERROR (PcdStatus); // // Setup FVB device path // Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr; mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address; mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1; // // Install the protocols // DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable support\n")); Handle = 0; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gEfiFirmwareVolumeBlock2ProtocolGuid, &mEmuVarsFvb.FwVolBlockInstance, &gEfiDevicePathProtocolGuid, &mEmuVarsFvb.DevicePath, NULL ); ASSERT_EFI_ERROR (Status); // // Register for the virtual address change event // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, FvbVirtualAddressChangeEvent, NULL, &gEfiEventVirtualAddressChangeGuid, &mEmuVarsFvbAddrChangeEvent ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
/** Finds out the recovery capsule in the current volume. @param PrivateData The private data structure that contains recovery module information. @retval EFI_SUCCESS The recovery capsule is successfully found in the volume. @retval EFI_NOT_FOUND The recovery capsule is not found in the volume. **/ EFI_STATUS EFIAPI FindRecoveryCapsules ( IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData ) { EFI_STATUS Status; UINTN Lba; EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi; EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi; UINTN BufferSize; UINT8 *Buffer; UINT8 Type; UINT8 *StandardID; UINT32 RootDirLBA; PEI_CD_EXPRESS_DIR_FILE_RECORD *RoorDirRecord; UINTN VolumeSpaceSize; BOOLEAN StartOfVolume; UINTN OriginalLBA; UINTN IndexBlockDevice; Buffer = PrivateData->BlockBuffer; BufferSize = PEI_CD_BLOCK_SIZE; Lba = 16; // // The volume descriptor starts on Lba 16 // IndexBlockDevice = PrivateData->CapsuleData[PrivateData->CapsuleCount].IndexBlock; BlockIoPpi = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo; BlockIo2Ppi = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2; VolumeSpaceSize = 0; StartOfVolume = TRUE; OriginalLBA = 16; while (TRUE) { SetMem (Buffer, BufferSize, 0); if (BlockIo2Ppi != NULL) { Status = BlockIo2Ppi->ReadBlocks ( (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), BlockIo2Ppi, IndexBlockDevice, Lba, BufferSize, Buffer ); } else { Status = BlockIoPpi->ReadBlocks ( (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), BlockIoPpi, IndexBlockDevice, Lba, BufferSize, Buffer ); } if (EFI_ERROR (Status)) { return Status; } StandardID = (UINT8 *) (Buffer + PEI_CD_EXPRESS_STANDARD_ID_OFFSET); if (!StringCmp (StandardID, (UINT8 *) PEI_CD_STANDARD_ID, PEI_CD_EXPRESS_STANDARD_ID_SIZE, TRUE)) { break; } if (StartOfVolume) { OriginalLBA = Lba; StartOfVolume = FALSE; } Type = *(UINT8 *) (Buffer + PEI_CD_EXPRESS_VOLUME_TYPE_OFFSET); if (Type == PEI_CD_EXPRESS_VOLUME_TYPE_TERMINATOR) { if (VolumeSpaceSize == 0) { break; } else { Lba = (OriginalLBA + VolumeSpaceSize); VolumeSpaceSize = 0; StartOfVolume = TRUE; continue; } } if (Type != PEI_CD_EXPRESS_VOLUME_TYPE_PRIMARY) { Lba++; continue; } VolumeSpaceSize = *(UINT32 *) (Buffer + PEI_CD_EXPRESS_VOLUME_SPACE_OFFSET); RoorDirRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *) (Buffer + PEI_CD_EXPRESS_ROOT_DIR_RECORD_OFFSET); RootDirLBA = RoorDirRecord->LocationOfExtent[0]; Status = RetrieveCapsuleFileFromRoot (PrivateData, BlockIoPpi, BlockIo2Ppi, IndexBlockDevice, RootDirLBA); if (!EFI_ERROR (Status)) { // // Just look for the first primary descriptor // return EFI_SUCCESS; } Lba++; } return EFI_NOT_FOUND; }
/* ** Entry point for the LAN9118 driver ** */ EFI_STATUS Lan9118DxeEntry ( IN EFI_HANDLE Handle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LAN9118_DRIVER *LanDriver; EFI_SIMPLE_NETWORK_PROTOCOL *Snp; EFI_SIMPLE_NETWORK_MODE *SnpMode; LAN9118_DEVICE_PATH *Lan9118Path; EFI_HANDLE ControllerHandle; // The PcdLan9118DxeBaseAddress PCD must be defined ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0); // Allocate Resources LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER)); if (LanDriver == NULL) { return EFI_OUT_OF_RESOURCES; } Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate); if (Lan9118Path == NULL) { return EFI_OUT_OF_RESOURCES; } // Initialize pointers Snp = &(LanDriver->Snp); SnpMode = &(LanDriver->SnpMode); Snp->Mode = SnpMode; // Set the signature of the LAN Driver structure LanDriver->Signature = LAN9118_SIGNATURE; // Assign fields and func pointers Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Snp->WaitForPacket = NULL; Snp->Initialize = SnpInitialize; Snp->Start = SnpStart; Snp->Stop = SnpStop; Snp->Reset = SnpReset; Snp->Shutdown = SnpShutdown; Snp->ReceiveFilters = SnpReceiveFilters; Snp->StationAddress = SnpStationAddress; Snp->Statistics = SnpStatistics; Snp->MCastIpToMac = SnpMcastIptoMac; Snp->NvData = SnpNvData; Snp->GetStatus = SnpGetStatus; Snp->Transmit = SnpTransmit; Snp->Receive = SnpReceive; // Start completing simple network mode structure SnpMode->State = EfiSimpleNetworkStopped; SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes) SnpMode->NvRamSize = 0; // No NVRAM with this device SnpMode->NvRamAccessSize = 0; // No NVRAM with this device // // Claim that all receive filter settings are supported, though the MULTICAST mode // is not completely supported. The LAN9118 Ethernet controller is only able to // do a "hash filtering" and not a perfect filtering on multicast addresses. The // controller does not filter the multicast addresses directly but a hash value // of them. The hash value of a multicast address is derived from its CRC and // ranges from 0 to 63 included. // We claim that the perfect MULTICAST filtering mode is supported because // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode // and thus not being able to take advantage of the hash filtering. // SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; // We do not intend to receive anything for the time being. SnpMode->ReceiveFilterSetting = 0; // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; SnpMode->MCastFilterCount = 0; ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS)); // Set the interface type (1: Ethernet or 6: IEEE 802 Networks) SnpMode->IfType = NET_IFTYPE_ETHERNET; // Mac address is changeable as it is loaded from erasable memory SnpMode->MacAddressChangeable = TRUE; // Can only transmit one packet at a time SnpMode->MultipleTxSupported = FALSE; // MediaPresent checks for cable connection and partner link SnpMode->MediaPresentSupported = TRUE; SnpMode->MediaPresent = FALSE; // Set broadcast address SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); // Power up the device so we can find the MAC address Status = Lan9118Initialize (Snp); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Lan9118: Error initialising hardware\n")); return EFI_DEVICE_ERROR; } // Assign fields for device path CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN); Lan9118Path->Lan9118.IfType = Snp->Mode->IfType; // Initialise the protocol ControllerHandle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &ControllerHandle, &gEfiSimpleNetworkProtocolGuid, Snp, &gEfiDevicePathProtocolGuid, Lan9118Path, NULL ); // Say what the status of loading the protocol structure is if (EFI_ERROR(Status)) { FreePool (LanDriver); } else { LanDriver->ControllerHandle = ControllerHandle; } return Status; }
/** Set up the Simple Network Protocol fields, the Simple Network Mode fields, and the Exit Boot Services Event of the virtio-net driver instance. This function may only be called by VirtioNetDriverBindingStart(). @param[in,out] Dev The VNET_DEV driver instance being created for the virtio-net device. @return Status codes from the CreateEvent() boot service or the VirtioNetGetFeatures() function. @retval EFI_SUCCESS Configuration successful. */ STATIC EFI_STATUS EFIAPI VirtioNetSnpPopulate ( IN OUT VNET_DEV *Dev ) { EFI_STATUS Status; // // We set up a function here that is asynchronously callable by an // external application to check if there are any packets available for // reception. The least urgent task priority level we can specify for such a // "software interrupt" is TPL_CALLBACK. // // TPL_CALLBACK is also the maximum TPL an SNP implementation is allowed to // run at (see 6.1 Event, Timer, and Task Priority Services in the UEFI // Specification 2.3.1+errC). // // Since we raise our TPL to TPL_CALLBACK in every single function that // accesses the device, and the external application also queues its interest // for received packets at the same TPL_CALLBACK, in effect the // VirtioNetIsPacketAvailable() function will never interrupt any // device-accessing driver function, it will be scheduled in isolation. // // TPL_CALLBACK (which basically this entire driver runs at) is allowed // for "[l]ong term operations (such as file system operations and disk // I/O)". Because none of our functions block, we'd satisfy an even stronger // requirement. // Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, &VirtioNetIsPacketAvailable, Dev, &Dev->Snp.WaitForPacket); if (EFI_ERROR (Status)) { return Status; } Dev->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Dev->Snp.Start = &VirtioNetStart; Dev->Snp.Stop = &VirtioNetStop; Dev->Snp.Initialize = &VirtioNetInitialize; Dev->Snp.Reset = &VirtioNetReset; Dev->Snp.Shutdown = &VirtioNetShutdown; Dev->Snp.ReceiveFilters = &VirtioNetReceiveFilters; Dev->Snp.StationAddress = &VirtioNetStationAddress; Dev->Snp.Statistics = &VirtioNetStatistics; Dev->Snp.MCastIpToMac = &VirtioNetMcastIpToMac; Dev->Snp.NvData = &VirtioNetNvData; Dev->Snp.GetStatus = &VirtioNetGetStatus; Dev->Snp.Transmit = &VirtioNetTransmit; Dev->Snp.Receive = &VirtioNetReceive; Dev->Snp.Mode = &Dev->Snm; Dev->Snm.State = EfiSimpleNetworkStopped; Dev->Snm.HwAddressSize = SIZE_OF_VNET (Mac); Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (Mac) + // dst MAC SIZE_OF_VNET (Mac) + // src MAC 2; // Ethertype Dev->Snm.MaxPacketSize = 1500; Dev->Snm.NvRamSize = 0; Dev->Snm.NvRamAccessSize = 0; Dev->Snm.ReceiveFilterMask = RECEIVE_FILTERS_NO_MCAST; Dev->Snm.ReceiveFilterSetting = RECEIVE_FILTERS_NO_MCAST; Dev->Snm.MaxMCastFilterCount = 0; Dev->Snm.MCastFilterCount = 0; Dev->Snm.IfType = 1; // ethernet Dev->Snm.MacAddressChangeable = FALSE; Dev->Snm.MultipleTxSupported = TRUE; ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS)); Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress, &Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent); if (EFI_ERROR (Status)) { goto CloseWaitForPacket; } CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress, SIZE_OF_VNET (Mac)); SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF); // // VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to // cancel any pending virtio requests. The TPL_CALLBACK reasoning is // identical to the one above. There's one difference: this kind of // event is "globally visible", which means it can be signalled as soon as // we create it. We haven't raised our TPL here, hence VirtioNetExitBoot() // could be entered immediately. VirtioNetExitBoot() checks Dev->Snm.State, // so we're safe. // Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, &VirtioNetExitBoot, Dev, &Dev->ExitBoot); if (EFI_ERROR (Status)) { goto CloseWaitForPacket; } return EFI_SUCCESS; CloseWaitForPacket: gBS->CloseEvent (Dev->Snp.WaitForPacket); return Status; }
/** Group the legacy boot options in the BootOption. The routine assumes the boot options in the beginning that covers all the device types are ordered properly and re-position the following boot options just after the corresponding boot options with the same device type. For example: 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] Assuming [Harddisk1 CdRom2 Efi1] is ordered properly Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] **/ VOID GroupMultipleLegacyBootOption4SameType ( VOID ) { EFI_STATUS Status; UINTN Index; UINTN DeviceIndex; UINTN DeviceTypeIndex[7]; UINTN *NextIndex; UINT16 OptionNumber; UINT16 *BootOrder; UINTN BootOrderSize; CHAR16 OptionName[sizeof ("Boot####")]; EFI_BOOT_MANAGER_LOAD_OPTION BootOption; SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff); GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); if (BootOrder == NULL) { return; } for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption); ASSERT_EFI_ERROR (Status); if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) { // // Legacy Boot Option // DEBUG ((EFI_D_ERROR, "[BootManagerDxe] ==== Find Legacy Boot Option 0x%x! ==== \n", Index)); ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF) < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0])); NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF]; if (*NextIndex == (UINTN) -1) { // // *NextIndex is the Index in BootOrder to put the next Option Number for the same type // *NextIndex = Index + 1; } else { // // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position // OptionNumber = BootOrder[Index]; CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16)); BootOrder[*NextIndex] = OptionNumber; // // Update the DeviceTypeIndex array to reflect the right shift operation // for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) { if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) { DeviceTypeIndex[DeviceIndex]++; } } } } EfiBootManagerFreeLoadOption (&BootOption); } gRT->SetVariable ( L"BootOrder", &gEfiGlobalVariableGuid, VAR_FLAG, BootOrderSize, BootOrder ); FreePool (BootOrder); }