func (fh *FileHeader) SetState(s FileState) {
	fh.State = s ^ FileState(Attributes.ErasePolarity)
}
SetState sets file state respecting erase polarity
package uefi
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"github.com/linuxboot/fiano/pkg/guid"
	"github.com/linuxboot/fiano/pkg/log"
)
type FVFileType uint8
const (
	FVFileTypeAll FVFileType = iota
	FVFileTypeRaw
	FVFileTypeFreeForm
	FVFileTypeSECCore
	FVFileTypePEICore
	FVFileTypeDXECore
	FVFileTypePEIM
	FVFileTypeDriver
	FVFileTypeCombinedPEIMDriver
	FVFileTypeApplication
	FVFileTypeSMM
	FVFileTypeVolumeImage
	FVFileTypeCombinedSMMDXE
	FVFileTypeSMMCore
	FVFileTypeSMMStandalone
	FVFileTypeSMMCoreStandalone
	FVFileTypeOEMMin   FVFileType = 0xC0
	FVFileTypeOEMMax   FVFileType = 0xDF
	FVFileTypeDebugMin FVFileType = 0xE0
	FVFileTypeDebugMax FVFileType = 0xEF
	FVFileTypePad      FVFileType = 0xF0
	FVFileTypeFFSMin   FVFileType = 0xF0
	FVFileTypeFFSMax   FVFileType = 0xFF
)
var SupportedFiles = map[FVFileType]bool{
	FVFileTypeFreeForm: true,
	FVFileTypeSECCore:  true,
	FVFileTypePEICore:  true,
	FVFileTypeDXECore:  true,
	FVFileTypeDriver:             true,
	FVFileTypeCombinedPEIMDriver: true,
	FVFileTypeApplication:        true,
	FVFileTypeSMM:                true,
	FVFileTypeVolumeImage:        true,
	FVFileTypeCombinedSMMDXE:     true,
	FVFileTypeSMMCore:            true,
	FVFileTypeSMMStandalone:      true,
	FVFileTypeSMMCoreStandalone:  true,
}
var fileTypeNames = map[FVFileType]string{
	FVFileTypeRaw:                "EFI_FV_FILETYPE_RAW",
	FVFileTypeFreeForm:           "EFI_FV_FILETYPE_FREEFORM",
	FVFileTypeSECCore:            "EFI_FV_FILETYPE_SECURITY_CORE",
	FVFileTypePEICore:            "EFI_FV_FILETYPE_PEI_CORE",
	FVFileTypeDXECore:            "EFI_FV_FILETYPE_DXE_CORE",
	FVFileTypePEIM:               "EFI_FV_FILETYPE_PEIM",
	FVFileTypeDriver:             "EFI_FV_FILETYPE_DRIVER",
	FVFileTypeCombinedPEIMDriver: "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER",
	FVFileTypeApplication:        "EFI_FV_FILETYPE_APPLICATION",
	FVFileTypeSMM:                "EFI_FV_FILETYPE_MM",
	FVFileTypeVolumeImage:        "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",
	FVFileTypeCombinedSMMDXE:     "EFI_FV_FILETYPE_COMBINED_MM_DXE",
	FVFileTypeSMMCore:            "EFI_FV_FILETYPE_MM_CORE",
	FVFileTypeSMMStandalone:      "EFI_FV_FILETYPE_MM_STANDALONE",
	FVFileTypeSMMCoreStandalone:  "EFI_FV_FILETYPE_MM_CORE_STANDALONE",
}
func (f FVFileType) String() string {
	switch {
	case FVFileTypeOEMMin <= f && f <= FVFileTypeOEMMax:
		return fmt.Sprintf("EFI_FV_FILETYPE_OEM (%#x)", uint8(f))
	case FVFileTypeDebugMin <= f && f <= FVFileTypeDebugMax:
		return fmt.Sprintf("EFI_FV_FILETYPE_DEBUG (%#x)", uint8(f))
	case FVFileTypeFFSMin < f && f <= FVFileTypeFFSMax:
		return fmt.Sprintf("EFI_FV_FILETYPE_FFS (%#x)", uint8(f))
	case f == FVFileTypePad:
		return "EFI_FV_FILETYPE_FFS_PAD"
	}
	if t, ok := fileTypeNames[f]; ok {
		return t
	}
	return "UNKNOWN"
}
var (
	ZeroGUID = guid.MustParse("00000000-0000-0000-0000-000000000000")
	FFGUID   = guid.MustParse("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
)
var fileAlignments = []uint64{
	1,
	16,
	128,
	512,
	1024,
	4 * 1024,
	32 * 1024,
	64 * 1024,
	128 * 1024,
	256 * 1024,
	512 * 1024,
	1024 * 1024,
	2 * 1024 * 1024,
	4 * 1024 * 1024,
	8 * 1024 * 1024,
	16 * 1024 * 1024,
}
const (
	FileHeaderMinLength = 0x18
	FileHeaderExtMinLength = 0x20
	EmptyBodyChecksum uint8 = 0xAA
)
type IntegrityCheck struct {
	Header uint8
	File   uint8
}
type fileAttr uint8
type FileState uint8
const (
	FileStateHeaderConstruction FileState = 0x01
	FileStateHeaderValid        FileState = 0x02
	FileStateDataValid          FileState = 0x04
	FileStateMarkeForUpdate     FileState = 0x08
	FileStateDeleted            FileState = 0x10
	FileStateHeaderInvalid      FileState = 0x20
	FileStateValid FileState = FileStateHeaderConstruction | FileStateHeaderValid | FileStateDataValid
)
type FileHeader struct {
	GUID       guid.GUID       
	Checksum   IntegrityCheck `json:"-"`
	Type       FVFileType
	Attributes fileAttr
	Size       [3]uint8 `json:"-"`
	State      FileState
}
func (a fileAttr) IsLarge() bool {
	return a&0x01 != 0
}
func (a fileAttr) GetAlignment() uint64 {
	alignVal := (a & 0x38) >> 3
	alignVal |= (a & 0x02) << 2
	return fileAlignments[alignVal]
}
func (a *fileAttr) setLarge(large bool) {
	if large {
		*a |= 0x01
	} else {
		*a &= 0xFE
	}
}
func (a fileAttr) HasChecksum() bool {
	return a&0x40 != 0
}