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