github.com/linuxboot/fiano@v1.2.0/pkg/visitors/flatten.go (about) 1 // Copyright 2018 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 "encoding/json" 9 "fmt" 10 "io" 11 "os" 12 13 "github.com/linuxboot/fiano/pkg/uefi" 14 ) 15 16 // Flatten places all nodes into a single slice and removes their children. 17 // Each node contains the index of its parent (the root node's parent is 18 // itself). This format is suitable for insertion into a database. 19 type Flatten struct { 20 // Optionally write result as JSON. 21 W io.Writer 22 23 // Outputted flattened tree. 24 List []FlattenedFirmware 25 26 parent int 27 } 28 29 // FlattenedFirmware appears in the Flatten.List, contains the index of the 30 // parrent and has no children. 31 type FlattenedFirmware struct { 32 Parent int 33 Type string 34 Value uefi.Firmware 35 } 36 37 // Run wraps Visit and performs some setup and teardown tasks. 38 func (v *Flatten) Run(f uefi.Firmware) error { 39 if err := f.Apply(v); err != nil { 40 return err 41 } 42 43 // Remove children otherwise the output contains many duplicates of each node. 44 for _, f := range v.List { 45 switch f := f.Value.(type) { 46 case *uefi.BIOSRegion: 47 f.Elements = nil 48 case *uefi.File: 49 f.Sections = nil 50 case *uefi.FirmwareVolume: 51 f.Files = nil 52 case *uefi.FlashImage: 53 // TODO: Cannot remove IFD 54 // f.IFD = nil 55 f.Regions = nil 56 case *uefi.Section: 57 f.Encapsulated = nil 58 } 59 } 60 61 // Optionally print as JSON 62 if v.W != nil { 63 b, err := json.MarshalIndent(v.List, "", "\t") 64 if err != nil { 65 return err 66 } 67 _, err = fmt.Fprintln(v.W, string(b)) 68 return err 69 } 70 return nil 71 } 72 73 // Visit applies the Flatten visitor to any Firmware type. 74 func (v *Flatten) Visit(f uefi.Firmware) error { 75 parent := v.parent 76 v.parent = len(v.List) 77 v.List = append(v.List, FlattenedFirmware{ 78 Parent: parent, 79 Type: fmt.Sprintf("%T", f), 80 Value: f, 81 }) 82 if err := f.ApplyChildren(v); err != nil { 83 return err 84 } 85 v.parent = parent 86 return nil 87 } 88 89 func init() { 90 RegisterCLI("flatten", "prints a JSON list of nodes", 0, func(args []string) (uefi.Visitor, error) { 91 return &Flatten{ 92 W: os.Stdout, 93 }, nil 94 }) 95 }