EFIAPI DuplicateDevicePathProtocolInterface ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { return DuplicateDevicePath (DevicePath); }
EFI_STATUS CreateSingleSupportFile ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName, IN EFI_HANDLE ImageHandle, IN VOID *Context, OUT EFI_SCT_TEST_FILE **SupportFile ) /*++ Routine Description: Create a test support file data structure. --*/ { EFI_STATUS Status; // // Check parameter // if ((DevicePath == NULL) || (FileName == NULL) || (SupportFile == NULL)) { return EFI_INVALID_PARAMETER; } // // Allocate memory for the support file // Status = BS->AllocatePool ( EfiBootServicesData, sizeof(EFI_SCT_TEST_FILE), SupportFile ); if (EFI_ERROR(Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Allocate pool - %r", Status)); return Status; } ZeroMem (*SupportFile, sizeof(EFI_SCT_TEST_FILE)); // // Initialize the items of support file // (*SupportFile)->Signature = EFI_SCT_TEST_FILE_SIGNATURE; (*SupportFile)->Revision = EFI_SCT_TEST_FILE_REVISION; (*SupportFile)->DevicePath = DuplicateDevicePath (DevicePath); (*SupportFile)->FileName = StrDuplicate (FileName); (*SupportFile)->ImageHandle = ImageHandle; (*SupportFile)->Type = EFI_SCT_TEST_FILE_TYPE_SUPPORT; (*SupportFile)->Context = Context; // // Done // return EFI_SUCCESS; }
EFI_STATUS CheckStore ( IN EFI_HANDLE SimpleFileSystemHandle, IN UINT32 VolumeId, OUT EFI_DEVICE_PATH_PROTOCOL **Device ) { #define BLOCK_SIZE 0x200 #define FAT16_VOLUME_ID_OFFSET 39 #define FAT32_VOLUME_ID_OFFSET 67 EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlkIo; UINT8 BootSector[BLOCK_SIZE]; *Device = NULL; Status = gBS->HandleProtocol ( SimpleFileSystemHandle, &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem (VOID*)&BlkIo ); if (EFI_ERROR (Status)) { goto ErrHandle; } if (!BlkIo->Media->MediaPresent) { DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media not present!\n")); Status = EFI_NO_MEDIA; goto ErrHandle; } if (BlkIo->Media->ReadOnly) { DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media is read-only!\n")); Status = EFI_ACCESS_DENIED; goto ErrHandle; } Status = BlkIo->ReadBlocks( BlkIo, BlkIo->Media->MediaId, 0, BLOCK_SIZE, BootSector ); ASSERT_EFI_ERROR (Status); if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) && (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId) ) { Status = EFI_NOT_FOUND; goto ErrHandle; } *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle)); ASSERT (*Device != NULL); ErrHandle: return Status; }
EFI_DEVICE_PATH_PROTOCOL * AppendDevicePathInstance ( IN EFI_DEVICE_PATH_PROTOCOL *Src, IN EFI_DEVICE_PATH_PROTOCOL *Instance ) /*++ Routine Description: Function is used to add a device path instance to a device path. Arguments: Src - A pointer to a device path data structure Instance - A pointer to a device path instance. Returns: This function returns a pointer to the new device path. If there is not enough temporary pool memory available to complete this function, then NULL is returned. It is up to the caller to free the memory used by Src and Instance if they are no longer needed. --*/ { UINT8 *Ptr; EFI_DEVICE_PATH_PROTOCOL *DevPath; UINTN SrcSize; UINTN InstanceSize; if (Src == NULL) { return DuplicateDevicePath (Instance); } SrcSize = DevicePathSize(Src); InstanceSize = DevicePathSize(Instance); Ptr = AllocatePool (SrcSize + InstanceSize); DevPath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr; ASSERT(DevPath); CopyMem (Ptr, Src, SrcSize); // FreePool (Src); while (!IsDevicePathEnd(DevPath)) { DevPath = NextDevicePathNode(DevPath); } // // Convert the End to an End Instance, since we are // appending another instacne after this one its a good // idea. // DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; DevPath = NextDevicePathNode(DevPath); CopyMem (DevPath, Instance, InstanceSize); return (EFI_DEVICE_PATH_PROTOCOL *)Ptr; }
EFIAPI GetNextDevicePathInstance ( IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size ) { EFI_DEVICE_PATH_PROTOCOL *DevPath; EFI_DEVICE_PATH_PROTOCOL *ReturnValue; UINT8 Temp; ASSERT (Size != NULL); if (DevicePath == NULL || *DevicePath == NULL) { *Size = 0; return NULL; } if (!IsDevicePathValid (*DevicePath, 0)) { return NULL; } // // Find the end of the device path instance // DevPath = *DevicePath; while (!IsDevicePathEndType (DevPath)) { DevPath = NextDevicePathNode (DevPath); } // // Compute the size of the device path instance // *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); // // Make a copy and return the device path instance // Temp = DevPath->SubType; DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; ReturnValue = DuplicateDevicePath (*DevicePath); DevPath->SubType = Temp; // // If DevPath is the end of an entire device path, then another instance // does not follow, so *DevicePath is set to NULL. // if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { *DevicePath = NULL; } else { *DevicePath = NextDevicePathNode (DevPath); } return ReturnValue; }
EFI_DEVICE_PATH* GetAlignedDevicePath ( IN EFI_DEVICE_PATH* DevicePath ) { if ((UINTN)DevicePath & 0x1) { return DuplicateDevicePath (DevicePath); } else { return DevicePath; } }
EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; UINTN BootFilePathSize; FILEPATH_DEVICE_PATH* EndingDevicePath; FILEPATH_DEVICE_PATH* FilePathDevicePath; EFI_DEVICE_PATH* DevicePath; DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); Print(L"File path of the %s: ", FileName); StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX); Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return Status; } BootFilePathSize = StrSize(BootFilePath); if (BootFilePathSize == 2) { *NewDevicePath = NULL; return EFI_NOT_FOUND; } // Create the FilePath Device Path node FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); if (NULL == FilePathDevicePath) { return EFI_INVALID_PARAMETER; } FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); // Generate the new Device Path by replacing the last node by the updated node SetDevicePathEndNode (EndingDevicePath); *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); FreePool(DevicePath); return EFI_SUCCESS; }
EFI_STATUS CheckStore ( IN EFI_HANDLE SimpleFileSystemHandle, OUT EFI_DEVICE_PATH_PROTOCOL **Device ) { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlkIo; EFI_FILE_PROTOCOL *File; *Device = NULL; Status = gBS->HandleProtocol ( SimpleFileSystemHandle, &gEfiBlockIoProtocolGuid, (VOID*)&BlkIo ); if (EFI_ERROR (Status)) { goto ErrHandle; } if (!BlkIo->Media->MediaPresent) { DEBUG ((DEBUG_ERROR, "FwhMappedFile: Media not present!\n")); Status = EFI_NO_MEDIA; goto ErrHandle; } if (BlkIo->Media->ReadOnly) { DEBUG ((DEBUG_ERROR, "FwhMappedFile: Media is read-only!\n")); Status = EFI_ACCESS_DENIED; goto ErrHandle; } Status = FileOpen (DevicePathFromHandle (SimpleFileSystemHandle), mFvInstance->MappedFile, &File, EFI_FILE_MODE_READ); if (EFI_ERROR (Status)) { goto ErrHandle; } /* We found it! Maybe do more checks...? */ FileClose (File); *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle)); ASSERT (*Device != NULL); ErrHandle: return Status; }
UINTN GetUnalignedDevicePathSize ( IN EFI_DEVICE_PATH* DevicePath ) { UINTN Size; EFI_DEVICE_PATH* AlignedDevicePath; if ((UINTN)DevicePath & 0x1) { AlignedDevicePath = DuplicateDevicePath (DevicePath); Size = GetDevicePathSize (AlignedDevicePath); FreePool (AlignedDevicePath); } else { Size = GetDevicePathSize (DevicePath); } return Size; }
/** Find the platform active active video controller and connect it. @retval EFI_NOT_FOUND There is no active video controller. @retval EFI_SUCCESS The video controller is connected. **/ EFI_STATUS ConnectVideoController ( VOID ) { EFI_HANDLE VideoController; EFI_DEVICE_PATH_PROTOCOL *Gop; // // Get the platform vga device // VideoController = GetVideoController (); if (VideoController == NULL) { return EFI_NOT_FOUND; } // // Try to connect the PCI device path, so that GOP dirver could start on this // device and create child handles with GraphicsOutput Protocol installed // on them, then we get device paths of these child handles and select // them as possible console device. // gBS->ConnectController (VideoController, NULL, NULL, FALSE); Gop = EfiBootManagerGetGopDevicePath (VideoController); if (Gop == NULL) { // // Last chance - just try VGA controller // Don't assume all VGA controller support GOP operation // DEBUG ((EFI_D_ERROR, "[Bds] GOP not found, try VGA device path!\n")); Gop = DuplicateDevicePath (DevicePathFromHandle (VideoController)); if (Gop == NULL) { return EFI_NOT_FOUND; } } EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL); FreePool (Gop); // // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated. // return gBS->ConnectController (VideoController, NULL, NULL, TRUE); }
EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; MEMMAP_DEVICE_PATH* EndingDevicePath; EFI_DEVICE_PATH* DevicePath; DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); Print(L"Starting Address of the %s: ", FileName); UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress); Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { //return EFI_ABORTED; goto Exit; } Print(L"Ending Address of the %s: ", FileName); UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress); Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { goto Exit; //return EFI_ABORTED; } EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); Exit: if (EFI_ERROR(Status)) { FreePool(DevicePath); } else { *NewDevicePath = DevicePath; } return Status; }
/** Update the parameters of a Pxe boot option @param[in] OldDevicePath Current complete device path of the Pxe boot option. This has to be a valid complete Pxe boot option path. @param[in] FileName Description of the file the path is asked for @param[out] NewDevicePath Pointer to the new complete device path. @retval EFI_SUCCESS Update completed @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource **/ EFI_STATUS BdsLoadOptionPxeUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { // // Make a copy of the complete device path that is made of : // the device path of the device supporting the Pxe base code protocol // followed by an end node. // *NewDevicePath = DuplicateDevicePath (OldDevicePath); if (*NewDevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } else { return EFI_SUCCESS; } }
// Get the parent device in an EFI_DEVICE_PATH // Note: the returned device path is allocated and must be freed static EFI_DEVICE_PATH* GetParentDevice(CONST EFI_DEVICE_PATH* DevicePath) { EFI_DEVICE_PATH *dp, *ldp; dp = DuplicateDevicePath((EFI_DEVICE_PATH*)DevicePath); if (dp == NULL) return NULL; ldp = GetLastDevicePath(dp); if (ldp == NULL) return NULL; ldp->Type = END_DEVICE_PATH_TYPE; ldp->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; SetDevicePathNodeLength(ldp, sizeof (*ldp)); return dp; }
static EFI_STATUS FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType, EFI_DEVICE_PATH **Out) { EFI_DEVICE_PATH *dp = In; if (!In || !Out) return EFI_INVALID_PARAMETER; for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { if (DevicePathType(dp) == Type && DevicePathSubType(dp) == SubType) { *Out = DuplicateDevicePath(dp); if (!*Out) return EFI_OUT_OF_RESOURCES; return EFI_SUCCESS; } } *Out = NULL; return EFI_NOT_FOUND; }
/** Get the device path info saved in the menu structure. @param KeyValue Key value to identify the type of data to expect. **/ VOID LibGetDevicePath ( IN UINT16 KeyValue ) { UINT16 FileOptionMask; MENU_ENTRY *NewMenuEntry; FILE_CONTEXT *NewFileContext; FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue) - mQuestionIdUpdate; NewMenuEntry = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, FileOptionMask); NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext; if (gFileExplorerPrivate.RetDevicePath != NULL) { FreePool (gFileExplorerPrivate.RetDevicePath); } gFileExplorerPrivate.RetDevicePath = DuplicateDevicePath (NewFileContext->DevicePath); }
/** Initialize a load option. @param Option Pointer to the load option to be initialized. @param OptionNumber Option number of the load option. @param OptionType Type of the load option. @param Attributes Attributes of the load option. @param Description Description of the load option. @param FilePath Device path of the load option. @param OptionalData Optional data of the load option. @param OptionalDataSize Size of the optional data of the load option. @retval EFI_SUCCESS The load option was initialized successfully. @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL. **/ EFI_STATUS EFIAPI EfiBootManagerInitializeLoadOption ( IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option, IN UINTN OptionNumber, IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType, IN UINT32 Attributes, IN CHAR16 *Description, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN UINT8 *OptionalData, OPTIONAL IN UINT32 OptionalDataSize ) { if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) { return EFI_INVALID_PARAMETER; } if (((OptionalData != NULL) && (OptionalDataSize == 0)) || ((OptionalData == NULL) && (OptionalDataSize != 0))) { return EFI_INVALID_PARAMETER; } if ((UINT32) OptionType >= LoadOptionTypeMax) { return EFI_INVALID_PARAMETER; } ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); Option->OptionNumber = OptionNumber; Option->OptionType = OptionType; Option->Attributes = Attributes; Option->Description = AllocateCopyPool (StrSize (Description), Description); Option->FilePath = DuplicateDevicePath (FilePath); if (OptionalData != NULL) { Option->OptionalData = AllocateCopyPool (OptionalDataSize, OptionalData); Option->OptionalDataSize = OptionalDataSize; } return EFI_SUCCESS; }
EFI_DEVICE_PATH* AppendDevicePathInstance ( IN EFI_DEVICE_PATH *Src, IN EFI_DEVICE_PATH *Instance ) { UINT8 *Ptr; EFI_DEVICE_PATH *DevPath; UINTN SrcSize; UINTN InstanceSize; if (Src == NULL) { return DuplicateDevicePath (Instance); } SrcSize = DevicePathSize(Src); InstanceSize = DevicePathSize(Instance); Ptr = AllocatePool (SrcSize + InstanceSize); DevPath = (EFI_DEVICE_PATH *)Ptr; ASSERT(DevPath); CopyMem (Ptr, Src, SrcSize); // FreePool (Src); while (!IsDevicePathEnd(DevPath)) { DevPath = NextDevicePathNode(DevPath); } // // Convert the End to an End Instance, since we are // appending another instacne after this one its a good // idea. // DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; DevPath = NextDevicePathNode(DevPath); CopyMem (DevPath, Instance, InstanceSize); return (EFI_DEVICE_PATH *)Ptr; }
/** Find the file handle from the input device path info. @param RootDirectory Device path info. @param RetFileHandle Return the file handle for the input device path. @param ParentFileName Parent file name. @param DeviceHandle Driver handle for this partition. @retval EFI_SUCESS Find the file handle success. @retval Other Find the file handle failure. **/ EFI_STATUS LibGetFileHandleFromDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *RootDirectory, OUT EFI_FILE_HANDLE *RetFileHandle, OUT UINT16 **ParentFileName, OUT EFI_HANDLE *DeviceHandle ) { EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; EFI_STATUS Status; EFI_HANDLE Handle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE FileHandle; EFI_FILE_HANDLE LastHandle; CHAR16 *TempPath; *ParentFileName = NULL; // // Attempt to access the file via a file system interface // DevicePathNode = RootDirectory; Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &DevicePathNode, &Handle); if (EFI_ERROR (Status)) { return Status; } Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&Volume); if (EFI_ERROR (Status)) { return Status; } // // Open the Volume to get the File System handle // Status = Volume->OpenVolume (Volume, &FileHandle); if (EFI_ERROR (Status)) { return Status; } *DeviceHandle = Handle; if (IsDevicePathEnd(DevicePathNode)) { *ParentFileName = AllocateCopyPool (StrSize (L"\\"), L"\\"); *RetFileHandle = FileHandle; return EFI_SUCCESS; } // // Duplicate the device path to avoid the access to unaligned device path node. // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH // nodes, It assures the fields in device path nodes are 2 byte aligned. // TempDevicePathNode = DuplicateDevicePath (DevicePathNode); if (TempDevicePathNode == NULL) { // // Setting Status to an EFI_ERROR value will cause the rest of // the file system support below to be skipped. // Status = EFI_OUT_OF_RESOURCES; goto Done; } // // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the // directory information and filename can be seperate. The goal is to inch // our way down each device path node and close the previous node // DevicePathNode = TempDevicePathNode; while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) { if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH || DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) { Status = EFI_UNSUPPORTED; goto Done; } LastHandle = FileHandle; FileHandle = NULL; Status = LastHandle->Open ( LastHandle, &FileHandle, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName, EFI_FILE_MODE_READ, 0 ); if (*ParentFileName == NULL) { *ParentFileName = AllocateCopyPool (StrSize (((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName), ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName); } else { TempPath = LibAppendFileName (*ParentFileName, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName); if (TempPath == NULL) { LastHandle->Close (LastHandle); Status = EFI_OUT_OF_RESOURCES; goto Done; } FreePool (*ParentFileName); *ParentFileName = TempPath; } // // Close the previous node // LastHandle->Close (LastHandle); DevicePathNode = NextDevicePathNode (DevicePathNode); } if (EFI_ERROR (Status)) { goto Done; } *RetFileHandle = FileHandle; Status = EFI_SUCCESS; Done: if (TempDevicePathNode != NULL) { FreePool (TempDevicePathNode); } if ((FileHandle != NULL) && (EFI_ERROR (Status))) { FileHandle->Close (FileHandle); } return Status; }
/** Open a device named by PathName. The PathName includes a device name and path separated by a :. See file header for more details on the PathName syntax. There is no checking to prevent a file from being opened more than one type. SectionType is only used to open an FV. Each file in an FV contains multiple sections and only the SectionType section is opened. For any file that is opened with EfiOpen() must be closed with EfiClose(). @param PathName Path to parse to open @param OpenMode Same as EFI_FILE.Open() @param SectionType Section in FV to open. @return NULL Open failed @return Valid EFI_OPEN_FILE handle **/ EFI_OPEN_FILE * EfiOpen ( IN CHAR8 *PathName, IN CONST UINT64 OpenMode, IN CONST EFI_SECTION_TYPE SectionType ) { EFI_STATUS Status; EFI_OPEN_FILE *File; EFI_OPEN_FILE FileData; UINTN StrLen; UINTN FileStart; UINTN DevNumber = 0; EFI_OPEN_FILE_GUARD *GuardFile; BOOLEAN VolumeNameMatch; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN Size; EFI_IP_ADDRESS Ip; CHAR8 *CwdPlusPathName; UINTN Index; EFI_SECTION_TYPE ModifiedSectionType; EblUpdateDeviceLists (); File = &FileData; ZeroMem (File, sizeof (EFI_OPEN_FILE)); StrLen = AsciiStrSize (PathName); if (StrLen <= 1) { // Smallest valid path is 1 char and a null return NULL; } for (FileStart = 0; FileStart < StrLen; FileStart++) { if (PathName[FileStart] == ':') { FileStart++; break; } } // // Matching volume name has precedence over handle based names // VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber); if (!VolumeNameMatch) { if (FileStart == StrLen) { // No Volume name or device name, so try Current Working Directory if (gCwd == NULL) { // No CWD return NULL; } // We could add a current working directory concept CwdPlusPathName = AllocatePool (AsciiStrSize (gCwd) + AsciiStrSize (PathName)); if (CwdPlusPathName == NULL) { return NULL; } if ((PathName[0] == '/') || (PathName[0] == '\\')) { // PathName starts in / so this means we go to the root of the device in the CWD. CwdPlusPathName[0] = '\0'; for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) { CwdPlusPathName[FileStart] = gCwd[FileStart]; if (gCwd[FileStart] == ':') { FileStart++; CwdPlusPathName[FileStart] = '\0'; break; } } } else { AsciiStrCpy (CwdPlusPathName, gCwd); StrLen = AsciiStrLen (gCwd); if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) { AsciiStrCat (CwdPlusPathName, "\\"); } } AsciiStrCat (CwdPlusPathName, PathName); if (AsciiStrStr (CwdPlusPathName, ":") == NULL) { // Extra error check to make sure we don't recurse and blow stack return NULL; } File = EfiOpen (CwdPlusPathName, OpenMode, SectionType); FreePool (CwdPlusPathName); return File; } DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName); } File->DeviceName = AllocatePool (StrLen); AsciiStrCpy (File->DeviceName, PathName); File->DeviceName[FileStart - 1] = '\0'; File->FileName = &File->DeviceName[FileStart]; if (File->FileName[0] == '\0') { // if it is just a file name use / as root File->FileName = "\\"; } // // Use best match algorithm on the dev names so we only need to look at the // first few charters to match the full device name. Short name forms are // legal from the caller. // Status = EFI_SUCCESS; if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) { if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) { if (DevNumber >= mFsCount) { goto ErrorExit; } File->Type = EfiOpenFileSystem; File->EfiHandle = mFs[DevNumber]; Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode); } else if (PathName[1] == 'v' || PathName[1] == 'V') { if (DevNumber >= mFvCount) { goto ErrorExit; } File->Type = EfiOpenFirmwareVolume; File->EfiHandle = mFv[DevNumber]; if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) { // Skip leading / as its not really needed for the FV since no directories are supported FileStart++; } // Check for 2nd : ModifiedSectionType = SectionType; for (Index = FileStart; PathName[Index] != '\0'; Index++) { if (PathName[Index] == ':') { // Support fv0:\DxeCore:0x10 // This means open the PE32 Section of the file ModifiedSectionType = (EFI_SECTION_TYPE)AsciiStrHexToUintn (&PathName[Index + 1]); PathName[Index] = '\0'; } } File->FvSectionType = ModifiedSectionType; Status = EblFvFileDevicePath (File, &PathName[FileStart], ModifiedSectionType); } } else if ((*PathName == 'A') || (*PathName == 'a')) { // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE File->Type = EfiOpenMemoryBuffer; // 1st colon is at PathName[FileStart - 1] File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]); // Find 2nd colon while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { FileStart++; } // If we ran out of string, there's no extra data if (PathName[FileStart] == '\0') { File->Size = 0; } else { File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); } // if there's no number after the second colon, default // the end of memory if (File->Size == 0) { File->Size = (UINTN)(0 - (UINTN)File->Buffer); } File->MaxPosition = File->Size; File->BaseOffset = (UINTN)File->Buffer; } else if (*PathName== 'l' || *PathName == 'L') { if (DevNumber >= mLoadFileCount) { goto ErrorExit; } File->Type = EfiOpenLoadFile; File->EfiHandle = mLoadFile[DevNumber]; Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); if (EFI_ERROR (Status)) { goto ErrorExit; } File->DevicePath = DuplicateDevicePath (DevicePath); } else if (*PathName == 'b' || *PathName == 'B') { // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE if (DevNumber >= mBlkIoCount) { goto ErrorExit; } File->Type = EfiOpenBlockIo; File->EfiHandle = mBlkIo[DevNumber]; EblFileDevicePath (File, "", OpenMode); // 1st colon is at PathName[FileStart - 1] File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]); // Find 2nd colon while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { FileStart++; } // If we ran out of string, there's no extra data if (PathName[FileStart] == '\0') { Size = 0; } else { Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); } // if a zero size is passed in (or the size is left out entirely), // go to the end of the device. if (Size == 0) { File->Size = File->Size - File->DiskOffset; } else { File->Size = Size; } File->MaxPosition = File->Size; File->BaseOffset = File->DiskOffset; } else if ((*PathName) >= '0' && (*PathName <= '9')) { // Get current IP address Status = EblGetCurrentIpAddress (&Ip); if (EFI_ERROR(Status)) { AsciiPrint("Device IP Address is not configured.\n"); goto ErrorExit; } // Parse X.X.X.X:Filename, only support IPv4 TFTP for now... File->Type = EfiOpenTftp; File->IsDirty = FALSE; File->IsBufferValid = FALSE; Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp); } if (EFI_ERROR (Status)) { goto ErrorExit; } GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD)); if (GuardFile == NULL) { goto ErrorExit; } GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER; CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE)); GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER; return &(GuardFile->File); ErrorExit: FreePool (File->DeviceName); return NULL; }
/** Build a list containing all serial devices. @retval EFI_SUCCESS The function complete successfully. @retval EFI_UNSUPPORTED No serial ports present. **/ EFI_STATUS LocateSerialIo ( VOID ) { UINTN Index; UINTN Index2; UINTN NoHandles; EFI_HANDLE *Handles; EFI_STATUS Status; ACPI_HID_DEVICE_PATH *Acpi; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_SERIAL_IO_PROTOCOL *SerialIo; EFI_DEVICE_PATH_PROTOCOL *Node; EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; BM_MENU_ENTRY *NewMenuEntry; BM_TERMINAL_CONTEXT *NewTerminalContext; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; VENDOR_DEVICE_PATH Vendor; UINT32 FlowControl; // // Get all handles that have SerialIo protocol installed // InitializeListHead (&TerminalMenu.Head); TerminalMenu.MenuNumber = 0; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles ); if (EFI_ERROR (Status)) { // // No serial ports present // return EFI_UNSUPPORTED; } // // Sort Uart handles array with Acpi->UID from low to high // then Terminal menu can be built from low Acpi->UID to high Acpi->UID // SortedUartHandle (Handles, NoHandles); for (Index = 0; Index < NoHandles; Index++) { // // Check to see whether the handle has DevicePath Protocol installed // gBS->HandleProtocol ( Handles[Index], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath ); Acpi = NULL; for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { break; } // // Acpi points to the node before Uart node // Acpi = (ACPI_HID_DEVICE_PATH *) Node; } if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); if (NewMenuEntry == NULL) { FreePool (Handles); return EFI_OUT_OF_RESOURCES; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath); // // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! // coz' the misc data for each platform is not correct, actually it's the device path stored in // datahub which is not completed, so a searching for end of device path will enter a // dead-loop. // NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); if (NULL == NewMenuEntry->DisplayString) { NewMenuEntry->DisplayString = DevicePathToStr (DevicePath); } NewMenuEntry->HelpString = NULL; gBS->HandleProtocol ( Handles[Index], &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo ); CopyMem ( &NewTerminalContext->BaudRate, &SerialIo->Mode->BaudRate, sizeof (UINT64) ); CopyMem ( &NewTerminalContext->DataBits, &SerialIo->Mode->DataBits, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->Parity, &SerialIo->Mode->Parity, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->StopBits, &SerialIo->Mode->StopBits, sizeof (UINT8) ); NewTerminalContext->FlowControl = 0; SerialIo->GetControl(SerialIo, &FlowControl); if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) { NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE; } InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); TerminalMenu.MenuNumber++; } } if (Handles != NULL) { FreePool (Handles); } // // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var // OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); if (OutDevicePath != NULL) { UpdateComAttributeFromVariable (OutDevicePath); } if (InpDevicePath != NULL) { UpdateComAttributeFromVariable (InpDevicePath); } if (ErrDevicePath != NULL) { UpdateComAttributeFromVariable (ErrDevicePath); } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); if (NULL == NewMenuEntry) { return EFI_NOT_FOUND; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; NewTerminalContext->TerminalType = 0; NewTerminalContext->IsConIn = FALSE; NewTerminalContext->IsConOut = FALSE; NewTerminalContext->IsStdErr = FALSE; Vendor.Header.Type = MESSAGING_DEVICE_PATH; Vendor.Header.SubType = MSG_VENDOR_DP; for (Index2 = 0; Index2 < 4; Index2++) { CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); NewDevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Vendor ); if (NewMenuEntry->HelpString != NULL) { FreePool (NewMenuEntry->HelpString); } // // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath); // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; // NewMenuEntry->HelpString = NULL; if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) { NewTerminalContext->IsConOut = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) { NewTerminalContext->IsConIn = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) { NewTerminalContext->IsStdErr = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } } } return EFI_SUCCESS; }
/** Build up Console Menu based on types passed in. The type can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", "ConInDev" or "ConErrDev" doesn't exists. @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. @retval EFI_SUCCESS Function completes successfully. **/ EFI_STATUS GetConsoleMenu ( IN UINTN ConsoleMenuType ) { EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; UINTN Size; UINTN AllCount; UINTN Index; UINTN Index2; BM_MENU_ENTRY *NewMenuEntry; BM_CONSOLE_CONTEXT *NewConsoleContext; TYPE_OF_TERMINAL Terminal; UINTN Com; BM_MENU_OPTION *ConsoleMenu; DevicePath = NULL; AllDevicePath = NULL; AllCount = 0; switch (ConsoleMenuType) { case BM_CONSOLE_IN_CONTEXT_SELECT: ConsoleMenu = &ConsoleInpMenu; DevicePath = EfiLibGetVariable ( L"ConIn", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ConInDev", &gEfiGlobalVariableGuid ); break; case BM_CONSOLE_OUT_CONTEXT_SELECT: ConsoleMenu = &ConsoleOutMenu; DevicePath = EfiLibGetVariable ( L"ConOut", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ConOutDev", &gEfiGlobalVariableGuid ); break; case BM_CONSOLE_ERR_CONTEXT_SELECT: ConsoleMenu = &ConsoleErrMenu; DevicePath = EfiLibGetVariable ( L"ErrOut", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ErrOutDev", &gEfiGlobalVariableGuid ); break; default: return EFI_UNSUPPORTED; } if (NULL == AllDevicePath) { return EFI_NOT_FOUND; } InitializeListHead (&ConsoleMenu->Head); AllCount = EfiDevicePathInstanceCount (AllDevicePath); ConsoleMenu->MenuNumber = 0; // // Following is menu building up for Console Devices selected. // MultiDevicePath = AllDevicePath; Index2 = 0; for (Index = 0; Index < AllCount; Index++) { DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; NewMenuEntry->OptionNumber = Index2; NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); ASSERT (NewConsoleContext->DevicePath != NULL); NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); if (NULL == NewMenuEntry->DisplayString) { NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); } NewConsoleContext->IsTerminal = IsTerminalDevicePath ( NewConsoleContext->DevicePath, &Terminal, &Com ); NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( DevicePath, NewConsoleContext->DevicePath ); if (NewConsoleContext->IsTerminal) { BOpt_DestroyMenuEntry (NewMenuEntry); } else { Index2++; ConsoleMenu->MenuNumber++; InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); } } return EFI_SUCCESS; }
EFI_STATUS find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments, UINT16 *optnum) { unsigned int size = sizeof(UINT32) + sizeof (UINT16) + StrLen(label)*2 + 2 + DevicePathSize(dp) + StrLen(arguments) * 2; CHAR8 *data = AllocateZeroPool(size + 2); if (!data) return EFI_OUT_OF_RESOURCES; CHAR8 *cursor = data; *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; cursor += sizeof (UINT32); *(UINT16 *)cursor = DevicePathSize(dp); cursor += sizeof (UINT16); StrCpy((CHAR16 *)cursor, label); cursor += StrLen(label)*2 + 2; CopyMem(cursor, dp, DevicePathSize(dp)); cursor += DevicePathSize(dp); StrCpy((CHAR16 *)cursor, arguments); int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; EFI_GUID global = EFI_GLOBAL_VARIABLE; EFI_STATUS rc; CHAR8 *candidate = AllocateZeroPool(size); if (!candidate) { FreePool(data); return EFI_OUT_OF_RESOURCES; } for(i = 0; i < nbootorder && i < 0x10000; i++) { varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12]; varname[5] = hexmap[(bootorder[i] & 0x0f00) >> 8]; varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4]; varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0]; UINTN candidate_size = size; rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global, NULL, &candidate_size, candidate); if (EFI_ERROR(rc)) continue; if (candidate_size != size) continue; if (CompareMem(candidate, data, size)) continue; /* at this point, we have duplicate data. */ if (!first_new_option) { first_new_option = DuplicateDevicePath(fulldp); first_new_option_args = arguments; first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } *optnum = i; FreePool(candidate); FreePool(data); return EFI_SUCCESS; } FreePool(candidate); FreePool(data); return EFI_NOT_FOUND; }
/** Update the parameters of a TFTP boot option The function asks sequentially to update the IPv4 parameters as well as the boot file path, providing the previously set value if any. @param[in] OldDevicePath Current complete device path of the Tftp boot option. This has to be a valid complete Tftp boot option path. By complete, we mean that it is not only the Tftp specific end part built by the "BdsLoadOptionTftpCreateDevicePath()" function. This path is handled as read only. @param[in] FileName Description of the file the path is asked for @param[out] NewDevicePath Pointer to the new complete device path. @retval EFI_SUCCESS Update completed @retval EFI_ABORTED Update aborted by the user @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource **/ EFI_STATUS BdsLoadOptionTftpUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16 *FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *DevicePathNode; UINT8 *Ipv4NodePtr; IPv4_DEVICE_PATH Ipv4Node; BOOLEAN IsDHCP; EFI_IP_ADDRESS OldIp; EFI_IP_ADDRESS OldSubnetMask; EFI_IP_ADDRESS OldGatewayIp; EFI_IP_ADDRESS LocalIp; EFI_IP_ADDRESS SubnetMask; EFI_IP_ADDRESS GatewayIp; EFI_IP_ADDRESS RemoteIp; UINT8 *FileNodePtr; CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; UINTN PathSize; UINTN BootFilePathSize; FILEPATH_DEVICE_PATH *NewFilePathNode; Ipv4NodePtr = NULL; // // Make a copy of the complete device path that is made of : // the device path of the device that support the Simple Network protocol // followed by an IPv4 node (type IPv4_DEVICE_PATH), // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up // by an end node. The IPv6 case is not handled yet. // DevicePath = DuplicateDevicePath (OldDevicePath); if (DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the // call to this function, we know that the device path ends with an IPv4 node // followed by a file path node and finally an end node. To get the address of // the last IPv4 node, we loop over the whole device path, noting down the // address of each encountered IPv4 node. // for (DevicePathNode = DevicePath; !IsDevicePathEnd (DevicePathNode); DevicePathNode = NextDevicePathNode (DevicePathNode)) { if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) { Ipv4NodePtr = (UINT8*)DevicePathNode; } } // Copy for alignment of the IPv4 node data CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH)); Print (L"Get the IP address from DHCP: "); Status = GetHIInputBoolean (&IsDHCP); if (EFI_ERROR (Status)) { goto ErrorExit; } if (!IsDHCP) { Print (L"Local static IP address: "); if (Ipv4Node.StaticIpAddress) { CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); Status = EditHIInputIP (&OldIp, &LocalIp); } else { Status = GetHIInputIP (&LocalIp); } if (EFI_ERROR (Status)) { goto ErrorExit; } Print (L"Get the network mask: "); if (Ipv4Node.StaticIpAddress) { CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); Status = EditHIInputIP (&OldSubnetMask, &SubnetMask); } else { Status = GetHIInputIP (&SubnetMask); } if (EFI_ERROR (Status)) { goto ErrorExit; } Print (L"Get the gateway IP address: "); if (Ipv4Node.StaticIpAddress) { CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); Status = EditHIInputIP (&OldGatewayIp, &GatewayIp); } else { Status = GetHIInputIP (&GatewayIp); } if (EFI_ERROR (Status)) { goto ErrorExit; } } Print (L"TFTP server IP address: "); // Copy remote IPv4 address into IPv4 or IPv6 union CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); Status = EditHIInputIP (&OldIp, &RemoteIp); if (EFI_ERROR (Status)) { goto ErrorExit; } // Get the path of the boot file and its size in number of bytes FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH); BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH; // // Ask for update of the boot file path // do { // Copy for 2-byte alignment of the Unicode string CopyMem ( BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH, MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX) ); BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0'; Print (L"File path of the %s: ", FileName); Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR (Status)) { goto ErrorExit; } PathSize = StrSize (BootFilePath); if (PathSize > 2) { break; } // Empty string, give the user another try Print (L"Empty string - Invalid path\n"); } while (PathSize <= 2) ; // // Update the IPv4 node. IPv6 case not handled yet. // if (IsDHCP) { Ipv4Node.StaticIpAddress = FALSE; ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); } else { Ipv4Node.StaticIpAddress = TRUE; CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS)); } CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS)); CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH)); // // Create the new file path node // NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool ( SIZE_OF_FILEPATH_DEVICE_PATH + PathSize ); NewFilePathNode->Header.Type = MEDIA_DEVICE_PATH; NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength ( NewFilePathNode, SIZE_OF_FILEPATH_DEVICE_PATH + PathSize ); CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize); // // Generate the new Device Path by replacing the file path node at address // "FileNodePtr" by the new one "NewFilePathNode" and return its address. // SetDevicePathEndNode (FileNodePtr); *NewDevicePath = AppendDevicePathNode ( DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode ); ErrorExit: if (DevicePath != NULL) { FreePool (DevicePath) ; } return Status; }
EFI_STATUS EFIAPI TOLOpen ( IN EFI_TEST_OUTPUT_LIBRARY_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName, IN BOOLEAN OverwriteFile, OUT EFI_FILE **FileHandle ) /*++ Routine Description: One interface function of the TestOutputLibrary to open a file. Arguments: This - the protocol instance structure. DevicePath - the file's root device path. FileName - the file's name relative to the root. OverwriteFile - whether to overwrite the file. FileHandle - return the file's handle. Returns: EFI_SUCCESS - open the file successfully. EFI_NOT_READY - to overwrite an opened file is not allowed. EFI_OUT_OF_RESOURCES - not enough memory. --*/ { EFI_STATUS Status; TEST_OUTPUT_FILE *OutputFile; TEST_OUTPUT_PRIVATE_DATA *Private; EFI_HANDLE DeviceHandle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN BufSize; CHAR8 Buffer[2]; EFI_DEVICE_PATH_PROTOCOL *PreDevicePath; Private = TEST_OUTPUT_PRIVATE_DATA_FROM_THIS (This); // // Search the file in OutputFileList to see whether the file has been opened // OutputFile = Private->OutputFileList; while (OutputFile != NULL) { if ((SctDevicePathCompare (DevicePath, OutputFile->DevicePath) == 0) && (StrCmp (FileName, OutputFile->FileName) == 0)) { break; } OutputFile = OutputFile->Next; } if (OutputFile == NULL) { // // Not found, open the file and add to the list // PreDevicePath = DevicePath; // // Determine device handle for fs protocol on specified device path // Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &PreDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { return Status; } // // Determine volume for file system on device handle // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR (Status)) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Determine the existence of the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (Status == EFI_NOT_FOUND) { // // The file not exist, create it // Status = SctCreateFile (RootDir, FileName, &Handle); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } // // Write the head of Unicode text file // Buffer[0] = 0xff; Buffer[1] = 0xfe; BufSize = 2; Status = Handle->Write (Handle, &BufSize, Buffer); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } } else if (EFI_ERROR (Status)) { RootDir->Close(RootDir); return Status; } if (OverwriteFile) { // // Overwrite the file // // // Delete the file // Status = Handle->Delete (Handle); // // EFI_FILE.Delete() return a warning status // if (Status != EFI_SUCCESS) { RootDir->Close (RootDir); return EFI_UNSUPPORTED; } // // Recreate the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } // // Write the head of Unicode text file // Buffer[0] = 0xff; Buffer[1] = 0xfe; BufSize = 2; Status = Handle->Write (Handle, &BufSize, Buffer); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } } else { // // Append the file // // // Set position to the end of file // Status = Handle->SetPosition (Handle, (UINT64)-1); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } } RootDir->Close (RootDir); // // Add the opened file to the OutputFileList // Status = BS->AllocatePool ( EfiBootServicesData, sizeof(TEST_OUTPUT_FILE), (VOID **)&OutputFile ); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } ZeroMem (OutputFile, sizeof(TEST_OUTPUT_FILE)); OutputFile->DevicePath = DuplicateDevicePath (DevicePath); if (OutputFile->DevicePath == NULL) { Handle->Close (Handle); BS->FreePool (OutputFile); return EFI_OUT_OF_RESOURCES; } OutputFile->FileName = StrDuplicate (FileName); if (OutputFile->FileName == NULL) { Handle->Close (Handle); BS->FreePool (OutputFile->DevicePath); BS->FreePool (OutputFile); return EFI_OUT_OF_RESOURCES; } OutputFile->FileHandle = Handle; OutputFile->Next = Private->OutputFileList; Private->OutputFileList = OutputFile; } // // Add the open count and return the file handle // OutputFile->OpenCount ++; *FileHandle = OutputFile->FileHandle; return EFI_SUCCESS; }
EFI_STATUS add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) { static int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; EFI_GUID global = EFI_GLOBAL_VARIABLE; EFI_STATUS rc; for(; i <= 0xffff; i++) { varname[4] = hexmap[(i & 0xf000) >> 12]; varname[5] = hexmap[(i & 0x0f00) >> 8]; varname[6] = hexmap[(i & 0x00f0) >> 4]; varname[7] = hexmap[(i & 0x000f) >> 0]; void *var = LibGetVariable(varname, &global); if (!var) { int size = sizeof(UINT32) + sizeof (UINT16) + StrLen(label)*2 + 2 + DevicePathSize(hddp) + StrLen(arguments) * 2; CHAR8 *data = AllocateZeroPool(size + 2); CHAR8 *cursor = data; *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; cursor += sizeof (UINT32); *(UINT16 *)cursor = DevicePathSize(hddp); cursor += sizeof (UINT16); StrCpy((CHAR16 *)cursor, label); cursor += StrLen(label)*2 + 2; CopyMem(cursor, hddp, DevicePathSize(hddp)); cursor += DevicePathSize(hddp); StrCpy((CHAR16 *)cursor, arguments); Print(L"Creating boot entry \"%s\" with label \"%s\" " L"for file \"%s\"\n", varname, label, filename); if (!first_new_option) { first_new_option = DuplicateDevicePath(fulldp); first_new_option_args = arguments; first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } rc = uefi_call_wrapper(RT->SetVariable, 5, varname, &global, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, size, data); FreePool(data); if (EFI_ERROR(rc)) { Print(L"Could not create variable: %d\n", rc); return rc; } CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16) * (nbootorder + 1)); if (!newbootorder) return EFI_OUT_OF_RESOURCES; int j = 0; newbootorder[0] = i & 0xffff; if (nbootorder) { for (j = 0; j < nbootorder; j++) newbootorder[j+1] = bootorder[j]; FreePool(bootorder); } bootorder = newbootorder; nbootorder += 1; #ifdef DEBUG_FALLBACK Print(L"nbootorder: %d\nBootOrder: ", nbootorder); for (j = 0 ; j < nbootorder ; j++) Print(L"%04x ", bootorder[j]); Print(L"\n"); #endif return EFI_SUCCESS; } } return EFI_OUT_OF_RESOURCES; }
EFI_STATUS BootAndroidBootImg ( IN UINTN BufferSize, IN VOID *Buffer ) { EFI_STATUS Status; CHAR8 KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE]; VOID *Kernel; UINTN KernelSize; VOID *Ramdisk; UINTN RamdiskSize; MEMORY_DEVICE_PATH KernelDevicePath; MEMORY_DEVICE_PATH* RamdiskDevicePath; Status = ParseAndroidBootImg ( Buffer, &Kernel, &KernelSize, &Ramdisk, &RamdiskSize, KernelArgs ); if (EFI_ERROR (Status)) { return Status; } KernelDevicePath = MemoryDevicePathTemplate; // Have to cast to UINTN before casting to EFI_PHYSICAL_ADDRESS in order to // appease GCC. KernelDevicePath.Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel; KernelDevicePath.Node1.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Kernel + KernelSize; RamdiskDevicePath = NULL; if (RamdiskSize != 0) { RamdiskDevicePath = (MEMORY_DEVICE_PATH*)DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*) &MemoryDevicePathTemplate); RamdiskDevicePath->Node1.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Ramdisk; RamdiskDevicePath->Node1.EndingAddress = ((EFI_PHYSICAL_ADDRESS)(UINTN) Ramdisk) + RamdiskSize; } Status = BdsBootLinuxFdt ( (EFI_DEVICE_PATH_PROTOCOL *) &KernelDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) RamdiskDevicePath, KernelArgs ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Couldn't Boot Linux: %d\n", Status)); return EFI_DEVICE_ERROR; } if (RamdiskDevicePath) { FreePool (RamdiskDevicePath); } // If we got here we do a confused face because BootLinuxFdt returned, // reporting success. DEBUG ((EFI_D_ERROR, "WARNING: BdsBootLinuxFdt returned EFI_SUCCESS.\n")); return EFI_SUCCESS; }
EFI_STATUS EFIAPI BdsLibConnectDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_HANDLE Handle; EFI_HANDLE PreviousHandle; UINTN Size; if (DevPathToTxt == NULL) { Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevPathToTxt); ASSERT((!EFI_ERROR(Status))); } if (DevicePathToConnect == NULL) { return EFI_SUCCESS; } DEBUG((DEBUG_INFO, "%a:%d dev path '%s' to connect\n", __FILE__, __LINE__, DevPathToTxt->ConvertDevicePathToText(DevicePathToConnect, TRUE, FALSE))); DevicePath = DuplicateDevicePath (DevicePathToConnect); if (DevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } CopyOfDevicePath = DevicePath; do { // // The outer loop handles multi instance device paths. // Only console variables contain multiple instance device paths. // // After this call DevicePath points to the next Instance // Instance = GetNextDevicePathInstance (&DevicePath, &Size); if (Instance == NULL) { FreePool (CopyOfDevicePath); return EFI_OUT_OF_RESOURCES; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // Start the real work of connect with RemainingDevicePath // PreviousHandle = NULL; do { // // Find the handle that best matches the Device Path. If it is only a // partial match the remaining part of the device path is returned in // RemainingDevicePath. // RemainingDevicePath = Instance; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); if (!EFI_ERROR (Status)) { if (Handle == PreviousHandle) { // // If no forward progress is made try invoking the Dispatcher. // A new FV may have been added to the system an new drivers // may now be found. // Status == EFI_SUCCESS means a driver was dispatched // Status == EFI_NOT_FOUND means no new drivers were dispatched // Status = gDS->Dispatch (); } if (!EFI_ERROR (Status)) { PreviousHandle = Handle; // // Connect all drivers that apply to Handle and RemainingDevicePath, // the Recursive flag is FALSE so only one level will be expanded. // // Do not check the connect status here, if the connect controller fail, // then still give the chance to do dispatch, because partial // RemainingDevicepath may be in the new FV // // 1. If the connect fail, RemainingDevicepath and handle will not // change, so next time will do the dispatch, then dispatch's status // will take effect // 2. If the connect success, the RemainingDevicepath and handle will // change, then avoid the dispatch, we have chance to continue the // next connection // gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); } } // // Loop until RemainingDevicePath is an empty device path // } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); } while (DevicePath != NULL); if (CopyOfDevicePath != NULL) { FreePool (CopyOfDevicePath); } // // All handle with DevicePath exists in the handle database // return Status; }
/** Save lines in HBufferImage to disk. NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!! @param[in] DeviceName The device name. @param[in] Offset The offset. @param[in] Size The size. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. @retval EFI_LOAD_ERROR A load error occured. @retval EFI_INVALID_PARAMETER A parameter was invalid. **/ EFI_STATUS HDiskImageSave ( IN CHAR16 *DeviceName, IN UINTN Offset, IN UINTN Size ) { CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; EFI_BLOCK_IO_PROTOCOL *BlkIo; EFI_STATUS Status; EFI_HANDLE Handle; VOID *Buffer; UINTN Bytes; UINT64 ByteOffset; EDIT_FILE_TYPE BufferTypeBackup; // // if not modified, directly return // if (HBufferImage.Modified == FALSE) { return EFI_SUCCESS; } BufferTypeBackup = HBufferImage.BufferType; HBufferImage.BufferType = FileTypeDiskBuffer; DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName); if (DevicePath == NULL) { // StatusBarSetStatusString (L"Cannot Find Device"); return EFI_INVALID_PARAMETER; } DupDevicePath = DuplicateDevicePath(DevicePath); // // get blkio interface // Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle); FreePool(DupDevicePath); if (EFI_ERROR (Status)) { // StatusBarSetStatusString (L"Read Disk Failed"); return Status; } Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR (Status)) { // StatusBarSetStatusString (L"Read Disk Failed"); return Status; } Bytes = BlkIo->Media->BlockSize * Size; Buffer = AllocateZeroPool (Bytes); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } // // concatenate the line list to a buffer // Status = HBufferImageListToBuffer (Buffer, Bytes); if (EFI_ERROR (Status)) { FreePool (Buffer); return Status; } ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize); // // write the buffer to disk // Status = BlkIo->WriteBlocks ( BlkIo, BlkIo->Media->MediaId, Offset, Bytes, Buffer ); FreePool (Buffer); if (EFI_ERROR (Status)) { return EFI_LOAD_ERROR; } // // now not modified // HBufferImage.Modified = FALSE; return EFI_SUCCESS; }
/** Read a disk from disk into HBufferImage. @param[in] DeviceName filename to read. @param[in] Offset The offset. @param[in] Size The size. @param[in] Recover if is for recover, no information print. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. @retval EFI_LOAD_ERROR A load error occured. @retval EFI_INVALID_PARAMETER A parameter was invalid. **/ EFI_STATUS HDiskImageRead ( IN CONST CHAR16 *DeviceName, IN UINTN Offset, IN UINTN Size, IN BOOLEAN Recover ) { CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree; EFI_HANDLE Handle; EFI_BLOCK_IO_PROTOCOL *BlkIo; EFI_STATUS Status; VOID *Buffer; CHAR16 *Str; UINTN Bytes; HEFI_EDITOR_LINE *Line; UINT64 ByteOffset; EDIT_FILE_TYPE BufferTypeBackup; BufferTypeBackup = HBufferImage.BufferType; HBufferImage.BufferType = FileTypeDiskBuffer; DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName); if (DevicePath == NULL) { StatusBarSetStatusString (L"Cannot Find Device"); return EFI_INVALID_PARAMETER; } DupDevicePath = DuplicateDevicePath(DevicePath); DupDevicePathForFree = DupDevicePath; // // get blkio interface // Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle); FreePool(DupDevicePathForFree); if (EFI_ERROR (Status)) { StatusBarSetStatusString (L"Read Disk Failed"); return Status; } Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR (Status)) { StatusBarSetStatusString (L"Read Disk Failed"); return Status; } // // if Offset exceeds LastBlock, // return error // if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) { StatusBarSetStatusString (L"Invalid Offset + Size"); return EFI_LOAD_ERROR; } Bytes = BlkIo->Media->BlockSize * Size; Buffer = AllocateZeroPool (Bytes); if (Buffer == NULL) { StatusBarSetStatusString (L"Read Disk Failed"); return EFI_OUT_OF_RESOURCES; } ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize); // // read from disk // Status = BlkIo->ReadBlocks ( BlkIo, BlkIo->Media->MediaId, Offset, Bytes, Buffer ); if (EFI_ERROR (Status)) { FreePool (Buffer); StatusBarSetStatusString (L"Read Disk Failed"); return EFI_LOAD_ERROR; } HBufferImageFree (); // // convert buffer to line list // Status = HBufferImageBufferToList (Buffer, Bytes); FreePool (Buffer); if (EFI_ERROR (Status)) { StatusBarSetStatusString (L"Read Disk Failed"); return Status; } Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size); if (EFI_ERROR (Status)) { StatusBarSetStatusString (L"Read Disk Failed"); return EFI_OUT_OF_RESOURCES; } // // initialize some variables // HDiskImage.BlockSize = BlkIo->Media->BlockSize; HBufferImage.DisplayPosition.Row = 2; HBufferImage.DisplayPosition.Column = 10; HBufferImage.MousePosition.Row = 2; HBufferImage.MousePosition.Column = 10; HBufferImage.LowVisibleRow = 1; HBufferImage.HighBits = TRUE; HBufferImage.BufferPosition.Row = 1; HBufferImage.BufferPosition.Column = 1; if (!Recover) { Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines); if (Str == NULL) { StatusBarSetStatusString (L"Read Disk Failed"); return EFI_OUT_OF_RESOURCES; } StatusBarSetStatusString (Str); SHELL_FREE_NON_NULL (Str); HMainEditor.SelectStart = 0; HMainEditor.SelectEnd = 0; } // // has line // if (HBufferImage.Lines != NULL) { HBufferImage.CurrentLine = CR ( HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST ); } else { // // create a dummy line // Line = HBufferImageCreateLine (); if (Line == NULL) { StatusBarSetStatusString (L"Read Disk Failed"); return EFI_OUT_OF_RESOURCES; } HBufferImage.CurrentLine = Line; } HBufferImage.Modified = FALSE; HBufferImageNeedRefresh = TRUE; HBufferImageOnlyLineNeedRefresh = FALSE; HBufferImageMouseNeedRefresh = TRUE; return EFI_SUCCESS; }
EFI_DEVICE_PATH * AppendDevicePath ( IN EFI_DEVICE_PATH *Src1, IN EFI_DEVICE_PATH *Src2 ) // Src1 may have multiple "instances" and each instance is appended // Src2 is appended to each instance is Src1. (E.g., it's possible // to append a new instance to the complete device path by passing // it in Src2) { UINTN Src1Size, Src1Inst, Src2Size, Size; EFI_DEVICE_PATH *Dst, *Inst; UINT8 *DstPos; // // If there's only 1 path, just duplicate it // if (!Src1) { ASSERT (!IsDevicePathUnpacked (Src2)); return DuplicateDevicePath (Src2); } if (!Src2) { ASSERT (!IsDevicePathUnpacked (Src1)); return DuplicateDevicePath (Src1); } // // Verify we're not working with unpacked paths // // ASSERT (!IsDevicePathUnpacked (Src1)); // ASSERT (!IsDevicePathUnpacked (Src2)); // // Append Src2 to every instance in Src1 // Src1Size = DevicePathSize(Src1); Src1Inst = DevicePathInstanceCount(Src1); Src2Size = DevicePathSize(Src2); Size = Src1Size * Src1Inst + Src2Size; Dst = (EFI_DEVICE_PATH *) AllocatePool (Size); if (Dst) { DstPos = (UINT8 *) Dst; // // Copy all device path instances // while (Inst = DevicePathInstance (&Src1, &Size)) { BS->CopyMem(DstPos, Inst, Size); DstPos += Size; BS->CopyMem(DstPos, Src2, Src2Size); DstPos += Src2Size; BS->CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH)); DstPos += sizeof(EFI_DEVICE_PATH); } // Change last end marker DstPos -= sizeof(EFI_DEVICE_PATH); BS->CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH)); } return Dst; }