github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/vpd/vpd.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 vpd 6 7 import ( 8 "os" 9 "path" 10 "path/filepath" 11 ) 12 13 // default variables 14 var ( 15 MaxBootEntry = 9999 16 DefaultVpdDir = "/sys/firmware/vpd" 17 ) 18 19 var globalReader = NewReader() 20 21 // NewReader returns a new VPD Reader. 22 func NewReader() *Reader { 23 return &Reader{ 24 VpdDir: DefaultVpdDir, 25 } 26 } 27 28 // Get wraps globalReader.Get . 29 func Get(key string, readOnly bool) ([]byte, error) { 30 return globalReader.Get(key, readOnly) 31 } 32 33 // Set wraps globalReader.Set . 34 func Set(key string, value []byte, readOnly bool) error { 35 return globalReader.Set(key, value, readOnly) 36 } 37 38 // GetAll wraps globalReader.GetAll . 39 func GetAll(readOnly bool) (map[string][]byte, error) { 40 return globalReader.GetAll(readOnly) 41 } 42 43 func (r *Reader) getBaseDir(readOnly bool) string { 44 if readOnly { 45 return path.Join(r.VpdDir, "ro") 46 } 47 return path.Join(r.VpdDir, "rw") 48 } 49 50 // Reader is a VPD reader object. 51 type Reader struct { 52 VpdDir string 53 } 54 55 // Get reads a VPD variable by name and returns its value as a sequence of 56 // bytes. The `readOnly` flag specifies whether the variable is read-only or 57 // read-write. 58 func (r *Reader) Get(key string, readOnly bool) ([]byte, error) { 59 buf, err := os.ReadFile(path.Join(r.getBaseDir(readOnly), key)) 60 if err != nil { 61 return []byte{}, err 62 } 63 return buf, nil 64 } 65 66 // Set sets a VPD variable with `key` as name and `value` as its byte-stream 67 // value. The `readOnly` flag specifies whether the variable is read-only or 68 // read-write. 69 // NOTE Unfortunately Set doesn't currently work, because the sysfs interface 70 // does not support writing. To write, this library needs a backend able to 71 // write to flash chips, like the command line tool flashrom or flashtools. 72 func (r *Reader) Set(key string, value []byte, readOnly bool) error { 73 // NOTE this is not implemented yet in the kernel interface, and will always 74 // return a permission denied error 75 return os.WriteFile(path.Join(r.getBaseDir(readOnly), key), value, 0o644) 76 } 77 78 // GetAll reads all the VPD variables and returns a map contaiing each 79 // name:value couple. The `readOnly` flag specifies whether the variable is 80 // read-only or read-write. 81 func (r *Reader) GetAll(readOnly bool) (map[string][]byte, error) { 82 vpdMap := make(map[string][]byte) 83 baseDir := r.getBaseDir(readOnly) 84 err := filepath.Walk(baseDir, func(fpath string, info os.FileInfo, _ error) error { 85 key := path.Base(fpath) 86 if key == "." || key == "/" || fpath == baseDir { 87 // empty or all slashes? 88 return nil 89 } 90 value, err := r.Get(key, readOnly) 91 if err != nil { 92 return err 93 } 94 vpdMap[key] = value 95 return nil 96 }) 97 return vpdMap, err 98 }