private ESPPartitionInfo FindESPPartition() { LogHelper.Log("EFIFirmwareService:FindESPPartition:"); //Assume it's 512 bytes long blockSize = 512; //Get the physical disk for the application partition int physicalDriveNumber = systemVerificationService.CurrentPhysicalDiskIndex; LogHelper.Log("EFIFirmwareService:FindESPPartition: Current physical drive: {0}", physicalDriveNumber); if (physicalDriveNumber == -1) { return(null); } //Get the blockSize of the ESP partition ObjectQuery query = new ObjectQuery("SELECT Bootable, BlockSize FROM Win32_DiskPartition where DiskIndex like " + physicalDriveNumber); ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(query); foreach (ManagementObject mo in moSearcher.Get()) { if ((bool)mo["Bootable"]) { blockSize = (long.Parse)(mo["BlockSize"].ToString()); break; } } //Query for the Volume{GUID} query = new ObjectQuery("SELECT DeviceId, DriveLetter, Name, FileSystem, Label FROM Win32_Volume"); moSearcher = new ManagementObjectSearcher(query); foreach (ManagementObject mo in moSearcher.Get()) { string deviceId = mo["DeviceID"].ToString().Replace("\\", "").Replace("?", ""); int disk = GetDiskForVolume(deviceId); //We assume the USB stick has exactly 2 partition if (disk == physicalDriveNumber && (mo["DriveLetter"] == null || !mo["DriveLetter"].ToString().Equals(systemVerificationService.CurrentDriveLetter))) { LogHelper.Log("EFIFirmwareService:FindESPPartition: ESP Volume: {0}", deviceId); LogHelper.Log("EFIFirmwareService:FindESPPartition: ESP Name: {0}", mo["name"]); LogHelper.Log("EFIFirmwareService:FindESPPartition: ESP FileSystem: {0}", mo["FileSystem"]); LogHelper.Log("EFIFirmwareService:FindESPPartition: ESP Label: {0}", mo["Label"] == null ? "Null" : mo["Label"].ToString()); ESPPartitionInfo tempPartitionInfo = GetESPPartitionInfo(deviceId); if (tempPartitionInfo != null && ESP_GUID.Equals(tempPartitionInfo.partitionType)) { tempPartitionInfo.blockSize = blockSize; return(tempPartitionInfo); } } } return(null); }
protected override void SetupEndlessLaunch(string description, string path) { LogHelper.Log("EFIFirmwareService:SetupEndlessLaunch:"); ObtainPrivileges(SE_SYSTEM_ENVIRONMENT_NAME); ObtainPrivileges(SE_SHUTDOWN_NAME); ESPPartitionInfo partitionInfo = FindESPPartition(); if (partitionInfo == null) { throw new FirmwareSetupException(FirmwareSetupErrorCode.EspPartitionNotFoundError, "Could not Found USB ESP volume"); } LogHelper.Log("EFIFirmwareService:SetupEndlessLaunch: ESP partition found:{0}", partitionInfo); //We assume there is at least the Windows UEFI entry entries = GetGPTUefiEntries(); if (entries == null || entries.Count == 0) { throw new FirmwareSetupException(FirmwareSetupErrorCode.NoExistingUefiEntriesError, "Found 0 UEFI entries"); } PrintUefiEntries(); UefiGPTEntry entry = CreateUefiEntry(partitionInfo, description, path); if (entry == null) { throw new FirmwareSetupException(FirmwareSetupErrorCode.CreateNewUefiEntryError, "Create new Uefi entry failed"); } if (!entries.Contains(entry)) { entries.Add(entry); } PrintUefiEntries(); bool inBootOrder = AddToBootOrder(entry); LogHelper.Log("EFIFirmwareService:SetupEndlessLaunch: In Boot order: {0}", inBootOrder); if (!inBootOrder) { throw new FirmwareSetupException(FirmwareSetupErrorCode.AddToBootOrderError, "Add new entry to BootOrder failed"); } else { if (!SetBootNext(entry)) { throw new FirmwareSetupException(FirmwareSetupErrorCode.SetBootNextError, "Set BootNext failed"); } } }
private UefiGPTEntry CreateUefiEntry(ESPPartitionInfo espPartitionInfo, string description, string path) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry:Description: {0}", description); LogHelper.Log("EFIFirmwareService:CreateUefiEntry:Path: {0}", path); foreach (UefiGPTEntry entry in entries) { if (entry.guid.Equals(espPartitionInfo.partitionId)) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry:Entry for {0} already exists. Return the existing entry", espPartitionInfo.partitionId); return(entry); } } EFI_HARD_DRIVE_PATH hdPath = new EFI_HARD_DRIVE_PATH(); LogHelper.Log("EFIFirmwareService:CreateUefiEntry: Partition startingOffset: {0}", espPartitionInfo.startingOffset / espPartitionInfo.blockSize); LogHelper.Log("EFIFirmwareService:CreateUefiEntry: PartitionLength: {0}", espPartitionInfo.partitionLength / espPartitionInfo.blockSize); //EFI_HARD_DRIVE_PATH hdPath.type = 0x4; hdPath.subtype = 0x1; hdPath.signature = new byte[16]; hdPath.length = (ushort)Marshal.SizeOf(hdPath); hdPath.part_num = (UInt32)espPartitionInfo.partitionNumber; hdPath.start = (UInt64)(espPartitionInfo.startingOffset / espPartitionInfo.blockSize); hdPath.size = (UInt64)(espPartitionInfo.partitionLength / espPartitionInfo.blockSize); hdPath.signature = espPartitionInfo.partitionId.ToByteArray(); hdPath.mbr_type = 2; /* GPT */ hdPath.signature_type = 2; /* GPT partition UUID */ //EFI_END_DEVICE_PATH EFI_END_DEVICE_PATH endPath = new EFI_END_DEVICE_PATH(); endPath.type = 0x7f; /* Descriptor end */ endPath.subtype = 0xff; /* Full path end */ endPath.length = 4; // EFI_FILE_PATH EFI_FILE_PATH filePath = new EFI_FILE_PATH(); byte[] pathBytes = Encoding.Unicode.GetBytes(path); byte[] descBytes = Encoding.Unicode.GetBytes(description); filePath.length = (ushort)(Marshal.SizeOf(filePath) + pathBytes.Length + 2); filePath.type = 4; /* Media device */ filePath.subtype = 4; /* File path */ // EFI_LOAD_OPTION EFI_LOAD_OPTION loadOption = new EFI_LOAD_OPTION(); loadOption.attributes = 1; //Mark as active loadOption.file_path_list_length = (ushort)(hdPath.length + filePath.length + endPath.length); int totalSize = Marshal.SizeOf(loadOption) + hdPath.length + filePath.length + endPath.length + descBytes.Length + 2; byte[] entryBytes = new byte[totalSize]; int offset = 0; //Copy EFI_LOAD_OPTION offset += CopyStructureToArray <EFI_LOAD_OPTION>(loadOption, offset, entryBytes); //Copy Description Array.Copy(descBytes, 0, entryBytes, offset, descBytes.Length); offset += descBytes.Length; offset += 2; //Copy EFI_HARD_DRIVE_PATH offset += CopyStructureToArray <EFI_HARD_DRIVE_PATH>(hdPath, offset, entryBytes); //Copy EFI_FILE_PATH without the actual path string /EFI/BOOT/<loader>.efi offset += CopyStructureToArray <EFI_FILE_PATH>(filePath, offset, entryBytes); //Copy path i.e: /EFI/BOOT/<loader>.efi Array.Copy(pathBytes, 0, entryBytes, offset, pathBytes.Length); offset += pathBytes.Length; offset += 2; //Copy EFI_END_DEVICE_PATH offset += CopyStructureToArray <EFI_END_DEVICE_PATH>(endPath, offset, entryBytes); int firstFreeEntry = GetFirstFreeUefiEntryNumber(); if (firstFreeEntry == -1) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry: Could not find a free Uefi entry:"); throw new FirmwareSetupException(FirmwareSetupErrorCode.FindFreeUefiEntryError, "Could not find a free Uefi entry"); } bool success = SetFirmwareEnvironmentVariable("Boot" + firstFreeEntry.ToString("X4"), UEFI_BOOT_NAMESPACE, entryBytes, (uint)entryBytes.Length); UefiGPTEntry newEntry = null; if (success) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry: Entry Created:"); newEntry = new UefiGPTEntry() { description = description, path = path, partitionNumber = (int)hdPath.part_num, guid = espPartitionInfo.partitionId, number = (ushort)firstFreeEntry }; } return(newEntry); }
private ESPPartitionInfo GetESPPartitionInfo(string volumePath) { ESPPartitionInfo partitionInfo = null; volumePath = "\\\\.\\" + volumePath; SafeFileHandle hndl = CreateFile(volumePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, IntPtr.Zero); if (hndl.IsInvalid) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry:Invalid handle:Error: {0}", Marshal.GetLastWin32Error()); throw new FirmwareSetupException(FirmwareSetupErrorCode.GetPartitionEspInfoError, "Get ESP partition information failed"); } PARTITION_INFORMATION_EX partition = new PARTITION_INFORMATION_EX(); UInt32 outBufferSize = (UInt32)Marshal.SizeOf(partition); IntPtr outBuffer = Marshal.AllocHGlobal((int)outBufferSize); UInt32 bytesReturned = 0; if (!DeviceIoControl(hndl, IOCTL_DISK_GET_PARTITION_INFO_EX, IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero)) { LogHelper.Log("EFIFirmwareService:CreateUefiEntry:IOCTL_DISK_GET_PARTITION_INFO_EX Failed: Error: {0}", Marshal.GetLastWin32Error()); } else { partition = (PARTITION_INFORMATION_EX)Marshal.PtrToStructure(outBuffer, typeof(PARTITION_INFORMATION_EX)); PARTITION_INFORMATION_GPT gptPartition = partition.DriveLayoutInformaiton.Gpt; LogHelper.Log("EFIFirmwareService:GetESPPartitionInfo:gptPartition:{0}", gptPartition.Name); partitionInfo = new ESPPartitionInfo() { volume = volumePath, partitionId = gptPartition.PartitionId, partitionType = gptPartition.PartitionType, partitionNumber = partition.PartitionNumber, startingOffset = partition.StartingOffset, partitionLength = partition.PartitionLength }; } Marshal.FreeHGlobal(outBuffer); hndl.Close(); return(partitionInfo); }