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 }