Skip to content

WIP: UEFI: handle compression #392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmds/utk/utk.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func main() {
}
}

log.Warnf("%v", args)
if err := utk.Run(args...); err != nil {
log.Fatalf("%v", err)
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/uefi/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/uefi/firmwarevolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
64 changes: 61 additions & 3 deletions pkg/uefi/section.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,48 @@ func (s *SectionGUIDDefined) GetBinHeaderLen() uint32 {
return uint32(unsafe.Sizeof(s.SectionGUIDDefinedHeader))
}

// SectionCompressionHeader contains the fields for a EFI_SECTION_COMPRESSION
// encapsulated section header.
type SectionCompressionHeader struct {
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 {
UncompressedLength uint32
CompressionType uint8
}

// 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))
}

// TypeHeader interface forces type specific headers to report their length
type TypeHeader interface {
GetBinHeaderLen() uint32
Expand Down Expand Up @@ -194,6 +236,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
Expand Down Expand Up @@ -343,8 +386,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 {
Expand Down Expand Up @@ -395,8 +438,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 {
Expand All @@ -422,7 +480,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)
Expand Down
4 changes: 2 additions & 2 deletions pkg/utk/utk.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
4 changes: 4 additions & 0 deletions pkg/visitors/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"

"github.com/linuxboot/fiano/pkg/log"
"github.com/linuxboot/fiano/pkg/uefi"
)

Expand Down Expand Up @@ -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 {
Expand All @@ -241,6 +243,7 @@ func (v *Insert) Visit(f uefi.Firmware) error {
}
}

log.Warnf("apply")
return f.ApplyChildren(v)
}

Expand Down Expand Up @@ -343,6 +346,7 @@ func genInsertFileCLI() func(args []string) (uefi.Visitor, error) {
}

// Insert File.
log.Warnf("1")
return &Insert{
Predicate: pred,
NewFile: file,
Expand Down