From 26f32318d38c1770653e5a07e63eb92a22918a75 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Mon, 3 Oct 2022 21:31:18 +0200 Subject: [PATCH 1/2] WIP: UEFI: handle compression --- cmds/utk/utk.go | 1 + pkg/uefi/file.go | 6 +++- pkg/uefi/firmwarevolume.go | 1 + pkg/uefi/section.go | 68 +++++++++++++++++++++++++++++++++++--- pkg/utk/utk.go | 4 +-- pkg/visitors/insert.go | 4 +++ 6 files changed, 77 insertions(+), 7 deletions(-) diff --git a/cmds/utk/utk.go b/cmds/utk/utk.go index 6fc50b67..181c7739 100644 --- a/cmds/utk/utk.go +++ b/cmds/utk/utk.go @@ -105,6 +105,7 @@ func main() { } } + log.Warnf("%v", args) if err := utk.Run(args...); err != nil { log.Fatalf("%v", err) } diff --git a/pkg/uefi/file.go b/pkg/uefi/file.go index 4820716a..7f3123ea 100644 --- a/pkg/uefi/file.go +++ b/pkg/uefi/file.go @@ -298,13 +298,17 @@ func (f *File) Apply(v Visitor) error { // ApplyChildren calls the visitor on each child node of File. func (f *File) ApplyChildren(v Visitor) error { + log.Warnf("apply children") if f.NVarStore != nil { + log.Warnf("nvar %v", v) if err := f.NVarStore.Apply(v); err != nil { return err } return nil } + log.Warnf("sections %v", f.Sections) for _, s := range f.Sections { + log.Warnf("apply %v %v", v, s) if err := s.Apply(v); err != nil { return err } @@ -489,7 +493,7 @@ func NewFile(buf []byte) (*File, error) { } for i, offset := 0, f.DataOffset; offset < f.Header.ExtendedSize; i++ { - s, err := NewSection(f.buf[offset:], i) + s, err := NewSection(f.buf[offset:], offset, i) if err != nil { return nil, fmt.Errorf("error parsing sections of file %v: %v", f.Header.GUID, err) } diff --git a/pkg/uefi/firmwarevolume.go b/pkg/uefi/firmwarevolume.go index dea6cb08..a035ccf9 100644 --- a/pkg/uefi/firmwarevolume.go +++ b/pkg/uefi/firmwarevolume.go @@ -185,6 +185,7 @@ func FindFirmwareVolumeOffset(data []byte) int64 { ) for offset = 32; offset+4 < int64(len(data)); offset += 8 { if bytes.Equal(data[offset:offset+4], fvSig) { + log.Warnf("_FVH@%x", data[offset+4:offset+20]) return offset - 40 // the actual volume starts 40 bytes before the signature } } diff --git a/pkg/uefi/section.go b/pkg/uefi/section.go index b85ba11f..7a684176 100644 --- a/pkg/uefi/section.go +++ b/pkg/uefi/section.go @@ -119,7 +119,51 @@ func (s *SectionGUIDDefined) GetBinHeaderLen() uint32 { return uint32(unsafe.Sizeof(s.SectionGUIDDefinedHeader)) } -// TypeHeader interface forces type specific headers to report their length +// SectionCompressionHeader contains the fields for a EFI_SECTION_COMPRESSION +// encapsulated section header. +type SectionCompressionHeader struct { + SectionHeader + UncompressedLength uint32 + CompressionType uint8 +} + +// SectionCompression contains the type specific fields for a +// EFI_SECTION_COMPRESSION section. +type SectionCompression struct { + SectionCompressionHeader + + // Metadata + Compression string +} + +// GetBinHeaderLen returns the length of the binary typ specific header +func (s *SectionCompression) GetBinHeaderLen() uint32 { + return uint32(unsafe.Sizeof(s.SectionCompressionHeader)) +} + +// SectionCompressionHeader contains the fields for a EFI_SECTION_COMPRESSION +// encapsulated section header. +type SectionCompressionExtHeader struct { + SectionExtHeader + UncompressedLength uint32 + CompressionType uint8 + // TypeHeader interface forces type specific headers to report their length +} + +// SectionCompression contains the type specific fields for a +// EFI_SECTION_COMPRESSION section. +type SectionCompressionExt struct { + SectionCompressionExtHeader + + // Metadata + Compression string +} + +// GetBinHeaderLen returns the length of the binary typ specific header +func (s *SectionCompressionExt) GetBinHeaderLen() uint32 { + return uint32(unsafe.Sizeof(s.SectionCompressionExtHeader)) +} + type TypeHeader interface { GetBinHeaderLen() uint32 } @@ -194,6 +238,7 @@ type Section struct { // Metadata for extraction and recovery ExtractPath string FileOrder int `json:"-"` + Offset uint64 // Type specific fields // TODO: It will be simpler if this was not an interface @@ -343,8 +388,8 @@ func (s *Section) GenSecHeader() error { // NewSection parses a sequence of bytes and returns a Section // object, if a valid one is passed, or an error. -func NewSection(buf []byte, fileOrder int) (*Section, error) { - s := Section{FileOrder: fileOrder} +func NewSection(buf []byte, offset uint64, fileOrder int) (*Section, error) { + s := Section{FileOrder: fileOrder, Offset: offset} // Read in standard header. r := bytes.NewReader(buf) if err := binary.Read(r, binary.LittleEndian, &s.Header.SectionHeader); err != nil { @@ -395,8 +440,23 @@ func NewSection(buf []byte, fileOrder int) (*Section, error) { copy(s.buf, newBuf) } + DEBUG := true + // Section type specific data switch s.Header.Type { + case SectionTypeCompression: + // NOTE: HERE BE DRAGONS + if DEBUG { + log.Warnf("[section] Compressed Section:\n %+v", s.Header) + } + typeSpec := &SectionCompression{} + if err := binary.Read(r, binary.LittleEndian, &typeSpec.SectionCompressionHeader); err != nil { + return nil, err + } + s.TypeSpecific = &TypeSpecificHeader{Type: SectionTypeCompression, Header: typeSpec} + if DEBUG { + log.Warnf("[section] SectionCompression:\n %+v", typeSpec) + } case SectionTypeGUIDDefined: typeSpec := &SectionGUIDDefined{} if err := binary.Read(r, binary.LittleEndian, &typeSpec.SectionGUIDDefinedHeader); err != nil { @@ -422,7 +482,7 @@ func NewSection(buf []byte, fileOrder int) (*Section, error) { } for i, offset := 0, uint64(0); offset < uint64(len(encapBuf)); i++ { - encapS, err := NewSection(encapBuf[offset:], i) + encapS, err := NewSection(encapBuf[offset:], offset, i) if err != nil { return nil, fmt.Errorf("error parsing encapsulated section #%d at offset %d: %v", i, offset, err) diff --git a/pkg/utk/utk.go b/pkg/utk/utk.go index c42e1942..a099fa7f 100644 --- a/pkg/utk/utk.go +++ b/pkg/utk/utk.go @@ -20,7 +20,7 @@ func Run(args ...string) error { return errors.New("at least one argument is required") } - v, err := visitors.ParseCLI(args[1:]) + visitor, err := visitors.ParseCLI(args[1:]) if err != nil { return err } @@ -56,5 +56,5 @@ func Run(args ...string) error { } // Execute the instructions from the command line. - return visitors.ExecuteCLI(parsedRoot, v) + return visitors.ExecuteCLI(parsedRoot, visitor) } diff --git a/pkg/visitors/insert.go b/pkg/visitors/insert.go index ad6719b8..ac176b24 100644 --- a/pkg/visitors/insert.go +++ b/pkg/visitors/insert.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + "github.com/linuxboot/fiano/pkg/log" "github.com/linuxboot/fiano/pkg/uefi" ) @@ -220,6 +221,7 @@ func (v *Insert) Visit(f uefi.Firmware) error { switch f := f.(type) { case *uefi.FirmwareVolume: for i := 0; i < len(f.Files); i++ { + log.Warnf("file %d", i) if f.Files[i] == v.FileMatch { // TODO: use InsertWherePreposition to define the location, instead of InsertType switch v.InsertType { @@ -241,6 +243,7 @@ func (v *Insert) Visit(f uefi.Firmware) error { } } + log.Warnf("apply") return f.ApplyChildren(v) } @@ -343,6 +346,7 @@ func genInsertFileCLI() func(args []string) (uefi.Visitor, error) { } // Insert File. + log.Warnf("1") return &Insert{ Predicate: pred, NewFile: file, From 8b8ad96b0c5199a03f273d2c695a48808e1bc0a2 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Mon, 3 Oct 2022 21:38:53 +0200 Subject: [PATCH 2/2] WIP: UEFI: handle compression Signed-off-by: Daniel Maslowski --- pkg/uefi/section.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/uefi/section.go b/pkg/uefi/section.go index 7a684176..dac64576 100644 --- a/pkg/uefi/section.go +++ b/pkg/uefi/section.go @@ -122,7 +122,6 @@ func (s *SectionGUIDDefined) GetBinHeaderLen() uint32 { // SectionCompressionHeader contains the fields for a EFI_SECTION_COMPRESSION // encapsulated section header. type SectionCompressionHeader struct { - SectionHeader UncompressedLength uint32 CompressionType uint8 } @@ -144,10 +143,8 @@ func (s *SectionCompression) GetBinHeaderLen() uint32 { // SectionCompressionHeader contains the fields for a EFI_SECTION_COMPRESSION // encapsulated section header. type SectionCompressionExtHeader struct { - SectionExtHeader UncompressedLength uint32 CompressionType uint8 - // TypeHeader interface forces type specific headers to report their length } // SectionCompression contains the type specific fields for a @@ -164,6 +161,7 @@ func (s *SectionCompressionExt) GetBinHeaderLen() uint32 { return uint32(unsafe.Sizeof(s.SectionCompressionExtHeader)) } +// TypeHeader interface forces type specific headers to report their length type TypeHeader interface { GetBinHeaderLen() uint32 }