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  }