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 bool SetBootNext(UefiGPTEntry entry)
        {
            LogHelper.Log("EFIFirmwareService:SetBootNext: Boot{0}", entry.number.ToString("X4"));
            byte[] bootNextBytes = BitConverter.GetBytes(entry.number);


            if (!SetFirmwareEnvironmentVariable("BootNext", EFI_GLOBAL_VARIABLE, bootNextBytes, (uint)bootNextBytes.Length))
            {
                LogHelper.Log("EFIFirmwareService:SetBootNext: Error: {0}", Marshal.GetLastWin32Error());
            }
            else
            {
                LogHelper.Log("EFIFirmwareService:SetBootNext: Success");
                return(true);
            }

            return(false);
        }
        private bool AddToBootOrder(UefiGPTEntry entry)
        {
            LogHelper.Log("EFIFirmwareService:AddToBootOrder: Boot{0}", entry.number.ToString("X4"));
            UInt16[] bootOrder = GetBootOrder();
            LogHelper.Log("EFIFirmwareService:AddToBootOrder: Current BootOrder:");
            PrintBootOrder(bootOrder);

            foreach (UInt16 bootNumber in bootOrder)
            {
                if (entry.number == bootNumber)
                {
                    LogHelper.Log("EFIFirmwareService:AddToBootOrder: Already in BootOrder");
                    return(true);
                }
            }

            byte[] newBootOrderBytes = new byte[(bootOrder.Length + 1) * sizeof(UInt16)];


            //Copy existing order bytes
            for (int i = 0; i < bootOrder.Length; i++)
            {
                Array.Copy(BitConverter.GetBytes(bootOrder[i]), 0, newBootOrderBytes, i * sizeof(UInt16), sizeof(UInt16));
            }

            Array.Copy(BitConverter.GetBytes(entry.number), 0, newBootOrderBytes, bootOrder.Length * sizeof(UInt16), sizeof(UInt16));

            bool success = SetFirmwareEnvironmentVariable("BootOrder", UEFI_BOOT_NAMESPACE, newBootOrderBytes, (uint)newBootOrderBytes.Length);

            if (!success)
            {
                LogHelper.Log("EFIFirmwareService:AddToBootOrder Failed: Error: {0}", Marshal.GetLastWin32Error());
            }
            LogHelper.Log("EFIFirmwareService:AddToBootOrder: New BootOrder: ");
            PrintBootOrder(GetBootOrder());

            return(success);
        }
        private List <UefiGPTEntry> GetGPTUefiEntries()
        {
            List <UefiGPTEntry> entries = new List <UefiGPTEntry>();
            int countEmpty = 0;

            for (int i = 0; i <= 0xffff && countEmpty <= 5; i++)
            {
                byte[] vardata        = new byte[10000];
                int    signature_type = -1;
                uint   size           = GetFirmwareEnvironmentVariable(string.Format(LOAD_OPTION_FORMAT, i), EFI_GLOBAL_VARIABLE, vardata, (uint)vardata.Length);
                if (size > 0)
                {
                    UefiGPTEntry entry = new UefiGPTEntry();
                    entry.number      = (UInt16)i;
                    entry.description = new string(Encoding.Unicode.GetString(vardata, 6, (int)size).TakeWhile(x => x != 0).ToArray());
                    var descBytes = Encoding.Unicode.GetBytes(entry.description);

                    //Device type
                    int devPathTypeStart = 6 + entry.description.Length * 2 + 2;
                    int iteration        = 0;

                    while (devPathTypeStart + HARD_DRIVE_DISKPATH_SIZE < (int)size)
                    {
                        iteration++;
                        byte devPathType = vardata[devPathTypeStart];

                        //Device subtype
                        int  devPathSubTypeStart = devPathTypeStart + 1;
                        byte devPathSubType      = vardata[devPathSubTypeStart];

                        switch (devPathType)
                        {
                        case 0x4:                   //Device type switch
                            switch (devPathSubType) //Device subtype switch
                            {
                            case 0x1:
                                int signature_type_index = devPathTypeStart + SIGNATURE_TYPE_OFFSET;
                                signature_type = vardata[signature_type_index];
                                switch (signature_type) //Device signature type
                                {
                                case 0x1:               //MBR  We're interested only in GPT entries, as our Drive use a GPT partition table
                                    break;

                                case 0x2:             //GPT We're interested only in GPT entries, as our Drive use a GPT partition table
                                    int partNumOffset = devPathTypeStart + PARTITION_NUMBER_OFFSET;
                                    entry.partitionNumber = (int)BitConverter.ToUInt32(vardata, partNumOffset);

                                    int signatureOffet = devPathTypeStart + SIGNATURE_OFFSET;
                                    entry.guid = new Guid(vardata.Skip(signatureOffet).Take(16).ToArray());

                                    break;
                                }
                                break;

                            case 0x4:
                            {
                                var filepath = new string(Encoding.Unicode.GetString(vardata, devPathTypeStart + 4, (int)size).TakeWhile(x => x != 0).ToArray());
                                entry.path = filepath;
                            }

                            break;
                            }
                            break;

                        case 0x7f:     // End of device path
                            break;
                        }

                        devPathTypeStart = devPathTypeStart + HARD_DRIVE_DISKPATH_SIZE;
                    }
                    entries.Add(entry);
                    countEmpty = 0;
                }
                else
                {
                    countEmpty++;
                }
            }
            return(entries);
        }
        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);
        }