github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/systembooter/bootentry.go (about) 1 // Copyright 2017-2019 the u-root 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 systembooter 6 7 import ( 8 "fmt" 9 "log" 10 11 "github.com/u-root/u-root/pkg/crypto" 12 "github.com/u-root/u-root/pkg/vpd" 13 ) 14 15 // Get, Set and GetAll are defined here as variables so they can be overridden 16 // for testing, or for using a key-value store other than VPD. 17 var ( 18 Get = vpd.Get 19 Set = vpd.Set 20 GetAll = vpd.GetAll 21 ) 22 23 // BootEntry represents a boot entry, with its name, configuration, and Booter 24 // instance. It can map to existing key-value stores like VPD or EFI vars. 25 type BootEntry struct { 26 Name string 27 Config []byte 28 Booter Booter 29 } 30 31 var supportedBooterParsers = []func([]byte) (Booter, error){ 32 NewNetBooter, 33 NewLocalBooter, 34 } 35 36 // GetBooterFor looks for a supported Booter implementation and returns it, if 37 // found. If not found, a NullBooter is returned. 38 func GetBooterFor(entry BootEntry) Booter { 39 var ( 40 booter Booter 41 err error 42 ) 43 for idx, booterParser := range supportedBooterParsers { 44 log.Printf("Trying booter #%d", idx) 45 booter, err = booterParser(entry.Config) 46 if err != nil { 47 log.Printf("This config is not valid for this booter (#%d)", idx) 48 continue 49 } 50 break 51 } 52 if booter == nil { 53 log.Printf("No booter found for entry: %+v", entry) 54 return &NullBooter{} 55 } 56 return booter 57 } 58 59 // GetBootEntries returns a list of BootEntry objects stored in the VPD 60 // partition of the flash chip 61 func GetBootEntries() []BootEntry { 62 var bootEntries []BootEntry 63 for idx := 0; idx < 9999; idx++ { 64 key := fmt.Sprintf("Boot%04d", idx) 65 // try the RW entries first 66 value, err := Get(key, false) 67 if err == nil { 68 crypto.TryMeasureData(crypto.NvramVarsPCR, value, key) 69 bootEntries = append(bootEntries, BootEntry{Name: key, Config: value}) 70 // WARNING WARNING WARNING this means that read-write boot entries 71 // have priority over read-only ones 72 continue 73 } 74 // try the RO entries then 75 value, err = Get(key, true) 76 if err == nil { 77 crypto.TryMeasureData(crypto.NvramVarsPCR, value, key) 78 bootEntries = append(bootEntries, BootEntry{Name: key, Config: value}) 79 } 80 } 81 // look for a Booter that supports the given configuration 82 for idx, entry := range bootEntries { 83 entry.Booter = GetBooterFor(entry) 84 if entry.Booter == nil { 85 log.Printf("No booter found for entry: %+v", entry) 86 } 87 bootEntries[idx] = entry 88 } 89 return bootEntries 90 }