github.com/linuxboot/fiano@v1.2.0/pkg/visitors/nvramcompact.go (about)

     1  // Copyright 2019 the LinuxBoot Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package visitors
     6  
     7  import (
     8  	"github.com/linuxboot/fiano/pkg/guid"
     9  	"github.com/linuxboot/fiano/pkg/uefi"
    10  )
    11  
    12  func compactNVarStore(s *uefi.NVarStore) error {
    13  	var keepEntries []*uefi.NVar
    14  	linkedNVar := make(map[uint64]*uefi.NVar)
    15  	// Find Data entries and associated metadata entries
    16  	for _, v := range s.Entries {
    17  		if !v.IsValid() {
    18  			continue
    19  		}
    20  		h, ok := linkedNVar[v.Offset]
    21  		if !ok {
    22  			h = v
    23  		}
    24  		if v.NextOffset != 0 {
    25  			linkedNVar[v.NextOffset] = h
    26  			continue
    27  		}
    28  		linkedNVar[v.Offset] = h
    29  		keepEntries = append(keepEntries, v)
    30  	}
    31  	var newEntries []*uefi.NVar
    32  	var guidStore []guid.GUID
    33  	guidStoredIndex := make(map[guid.GUID]uint8)
    34  	var offset uint64
    35  	// Rebuild GUID store and entries
    36  	for _, k := range keepEntries {
    37  		h := linkedNVar[k.Offset]
    38  		v := uefi.NVar{Type: uefi.FullNVarEntry, Header: h.Header, GUID: h.GUID, Name: h.Name, Offset: offset, NVarStore: k.NVarStore}
    39  		if v.Header.Attributes&uefi.NVarEntryGUID == 0 {
    40  			guidIndex, ok := guidStoredIndex[v.GUID]
    41  			if !ok {
    42  
    43  				guidIndex = uint8(len(guidStore))
    44  				guidStoredIndex[v.GUID] = guidIndex
    45  				guidStore = append(guidStore, v.GUID)
    46  			}
    47  			v.GUIDIndex = &guidIndex
    48  
    49  		}
    50  		if err := v.Assemble(k.Buf()[k.DataOffset:], false); err != nil {
    51  			return err
    52  		}
    53  		offset += uint64(len(v.Buf()))
    54  		newEntries = append(newEntries, &v)
    55  	}
    56  	// replace entries and GUID store
    57  	s.Entries = newEntries
    58  	s.GUIDStore = guidStore
    59  
    60  	// Assemble the tree just to make sure things are right
    61  	// It will do the mandatory second Assemble of NVar and update the Offsets
    62  	a := &Assemble{}
    63  	return a.Run(s)
    64  }
    65  
    66  // NVRamCompact compact nvram content by removing old version of variables
    67  type NVRamCompact struct {
    68  }
    69  
    70  // Run wraps Visit and performs some setup and teardown tasks.
    71  func (v *NVRamCompact) Run(f uefi.Firmware) error {
    72  	return f.Apply(v)
    73  }
    74  
    75  // Visit applies the NVRamCompact visitor to any Firmware type.
    76  func (v *NVRamCompact) Visit(f uefi.Firmware) error {
    77  	switch f := f.(type) {
    78  	case *uefi.NVarStore:
    79  		// First apply to children to compact nested stores in vars
    80  		err := f.ApplyChildren(v)
    81  		if err != nil {
    82  			return err
    83  		}
    84  		// call the compact function
    85  		return compactNVarStore(f)
    86  	}
    87  	return f.ApplyChildren(v)
    88  }
    89  
    90  func init() {
    91  	RegisterCLI("nvram-compact", "compact nvram content by removing old versions of variables", 0, func(args []string) (uefi.Visitor, error) {
    92  		return &NVRamCompact{}, nil
    93  	})
    94  }