gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/pkg/acpi/raw.go (about) 1 // Copyright 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 acpi 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "os" 13 14 "github.com/u-root/u-root/pkg/memio" 15 ) 16 17 // Raw ACPI table support. Raw tables are those tables 18 // one needs to read in, write out, but not change in any way. 19 // This is needed when, e.g., there is need to create files for 20 // coreboot cbfs. 21 22 // Raw is just a table embedded in a []byte. Operations on Raw are 23 // for figuring out how to skip a table you don't care about or, possibly, 24 // truncating a table and regenerating a checksum. 25 type Raw struct { 26 addr int64 27 data []byte 28 } 29 30 var _ = Table(&Raw{}) 31 32 // NewRaw returns a new Raw []Table fron a given byte slice. 33 func NewRaw(b []byte) ([]Table, error) { 34 var tab []Table 35 for { 36 if len(b) == 0 { 37 break 38 } 39 if len(b) < headerLength { 40 return nil, fmt.Errorf("NewRaw: byte slice is only %d bytes and must be at least %d bytes", len(b), headerLength) 41 } 42 u := binary.LittleEndian.Uint32(b[lengthOffset : lengthOffset+4]) 43 if int(u) > len(b) { 44 return nil, fmt.Errorf("Table length %d is too large for %d byte table (Signature %q", u, len(b), string(b[0:4])) 45 } 46 tab = append(tab, &Raw{data: b[:u]}) 47 b = b[u:] 48 } 49 return tab, nil 50 } 51 52 // RawFromFile reads from an io.Reader and returns a []Table and error if any. 53 func RawFromFile(r io.Reader) ([]Table, error) { 54 b, err := ioutil.ReadAll(r) 55 if err != nil { 56 return nil, err 57 } 58 return NewRaw(b) 59 } 60 61 // RawFromName reads a raw []Table in from a named file. 62 func RawFromName(n string) ([]Table, error) { 63 f, err := os.Open(n) 64 defer f.Close() 65 if err != nil { 66 return nil, err 67 } 68 return RawFromFile(f) 69 } 70 71 // ReadRawTable reads a full table in, given an address. 72 // 73 // ReadRawTable uses the io package. This may not always work 74 // if the kernel has restrictions on reading memory above 75 // the 1M boundary, and the tables are above boundary. 76 func ReadRawTable(physAddr int64) (Table, error) { 77 var u memio.Uint32 78 // Read the table size at a+4 79 if err := memio.Read(physAddr+4, &u); err != nil { 80 return nil, err 81 } 82 dat := memio.ByteSlice(make([]byte, u)) 83 if err := memio.Read(physAddr, &dat); err != nil { 84 return nil, err 85 } 86 return &Raw{addr: physAddr, data: []byte(dat)}, nil 87 } 88 89 // Address returns the table's base address 90 func (r *Raw) Address() int64 { 91 return r.addr 92 } 93 94 // Data returns all the data in a Raw table. 95 func (r *Raw) Data() []byte { 96 return r.data 97 } 98 99 // TableData returns the Raw table, minus the standard ACPI header. 100 func (r *Raw) TableData() []byte { 101 return r.data[headerLength:] 102 } 103 104 // Sig returns the table signature. 105 func (r *Raw) Sig() string { 106 return fmt.Sprintf("%s", r.data[:4]) 107 } 108 109 // Len returns the total table length. 110 func (r *Raw) Len() uint32 { 111 return uint32(len(r.data)) 112 } 113 114 // Revision returns the table Revision. 115 func (r *Raw) Revision() uint8 { 116 return uint8(r.data[8]) 117 } 118 119 // CheckSum returns the table CheckSum. 120 func (r *Raw) CheckSum() uint8 { 121 return uint8(r.data[9]) 122 } 123 124 // OEMID returns the table OEMID. 125 func (r *Raw) OEMID() string { 126 return fmt.Sprintf("%q", r.data[10:16]) 127 } 128 129 // OEMTableID returns the table OEMTableID. 130 func (r *Raw) OEMTableID() string { 131 return fmt.Sprintf("%q", r.data[16:24]) 132 } 133 134 // OEMRevision returns the table OEMRevision. 135 func (r *Raw) OEMRevision() uint32 { 136 return binary.LittleEndian.Uint32(r.data[24 : 24+4]) 137 } 138 139 // CreatorID returns the table CreatorID. 140 func (r *Raw) CreatorID() uint32 { 141 return binary.LittleEndian.Uint32(r.data[28 : 28+4]) 142 } 143 144 // CreatorRevision returns the table CreatorRevision. 145 func (r *Raw) CreatorRevision() uint32 { 146 return binary.LittleEndian.Uint32(r.data[32 : 32+4]) 147 }