efi_status=get_file_size(fh2,&len);if(EFI_ERROR(efi_status)){console_print(L"Could not get file size for \"%s\": %r\n",fullpath,efi_status);fh2->Close(fh2);returnefi_status;}if(len>1024*PAGE_SIZE){fh2->Close(fh2);returnEFI_BAD_BUFFER_SIZE;

/* * AMI BIOS (e.g, Intel NUC5i3MYHE) may automatically hide and patch BootXXXX * variables with ami_masked_device_path_guid. We can get the valid device path * if just skipping it and its next end path. */staticEFI_GUIDami_masked_device_path_guid={0x99e275e7,0x75a0,0x4b37,{0xa2,0xe6,0xc5,0x38,0x5e,0x6c,0x0,0xcb}};staticunsignedintcalc_masked_boot_option_size(unsignedintsize){returnsize+sizeof(EFI_DEVICE_PATH)+sizeof(ami_masked_device_path_guid)+sizeof(EFI_DEVICE_PATH);}staticintcheck_masked_boot_option(CHAR8*candidate,unsignedintcandidate_size,CHAR8*data,unsignedintdata_size){/* * The patched BootXXXX variables contain a hardware device path and * an end path, preceding the real device path. */if(calc_masked_boot_option_size(data_size)!=candidate_size)return1;CHAR8*cursor=candidate;/* Check whether the BootXXXX is patched */cursor+=sizeof(UINT32)+sizeof(UINT16);cursor+=StrSize((CHAR16*)cursor);unsignedintmin_valid_size=cursor-candidate+sizeof(EFI_DEVICE_PATH);if(candidate_size<=min_valid_size)return1;EFI_DEVICE_PATH*dp=(EFI_DEVICE_PATH*)cursor;unsignedintnode_size=DevicePathNodeLength(dp)-sizeof(EFI_DEVICE_PATH);min_valid_size+=node_size;if(candidate_size<=min_valid_size||DevicePathType(dp)!=HARDWARE_DEVICE_PATH||DevicePathSubType(dp)!=HW_VENDOR_DP||node_size!=sizeof(ami_masked_device_path_guid)||CompareGuid((EFI_GUID*)(cursor+sizeof(EFI_DEVICE_PATH)),&ami_masked_device_path_guid))return1;/* Check whether the patched guid is followed by an end path */min_valid_size+=sizeof(EFI_DEVICE_PATH);if(candidate_size<=min_valid_size)return1;dp=NextDevicePathNode(dp);if(!IsDevicePathEnd(dp))return1;/* * OK. We may really get a masked BootXXXX variable. The next * step is to test whether it is hidden. */UINT32attrs=*(UINT32*)candidate;#ifndef LOAD_OPTION_HIDDEN# define LOAD_OPTION_HIDDEN 0x00000008#endifif(!(attrs&LOAD_OPTION_HIDDEN))return1;attrs&=~LOAD_OPTION_HIDDEN;/* Compare the field Attributes */if(attrs!=*(UINT32*)data)return1;/* Compare the field FilePathListLength */data+=sizeof(UINT32);candidate+=sizeof(UINT32);if(calc_masked_boot_option_size(*(UINT16*)data)!=*(UINT16*)candidate)return1;/* Compare the field Description */data+=sizeof(UINT16);candidate+=sizeof(UINT16);if(CompareMem(candidate,data,cursor-candidate))return1;/* Compare the filed FilePathList */cursor=(CHAR8*)NextDevicePathNode(dp);data+=sizeof(UINT16);data+=StrSize((CHAR16*)data);returnCompareMem(cursor,data,candidate_size-min_valid_size);}

/* The file may or may not start with the Unicode byte order marker. * Sadness ensues. Since UEFI is defined as LE, I'm going to decree * that these files must also be LE. * * IT IS THUS SO. * * But if we find the LE byte order marker, just skip it.

efi_status=fh->GetInfo(fh,&EFI_FILE_INFO_GUID,&bs,NULL);if(EFI_ERROR(efi_status)&&efi_status!=EFI_BUFFER_TOO_SMALL){console_print(L"Could not get directory info for \\EFI\\%s\\: %r\n",dirname,efi_status);returnefi_status;