コード例 #1
0
        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);
        }
コード例 #2
0
        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");
                }
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }