github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/acpi/sdt.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  	"bytes"
     9  	"encoding/binary"
    10  	"fmt"
    11  )
    12  
    13  var sdtLen = 36
    14  
    15  // SDT contains information about tables. It does not differentiate 32- vs 64-bit
    16  // tables.
    17  type SDT struct {
    18  	// Table is the SDT itself.
    19  	Table
    20  
    21  	// Addrs is the array of physical addresses in the SDT.
    22  	Addrs []int64
    23  
    24  	// Base is the SDT base, used to generate a new SDT for, e.g, coreboot.
    25  	Base int64
    26  }
    27  
    28  var _ = Table(&SDT{})
    29  
    30  // NewSDTAddr returns an SDT, given an address.
    31  func NewSDTAddr(addr int64) (*SDT, error) {
    32  	t, err := ReadRawTable(addr)
    33  	if err != nil {
    34  		return nil, fmt.Errorf("can not read SDT at %#x", addr)
    35  	}
    36  	Debug("NewSDTAddr: %s %#x", String(t), t.TableData())
    37  	return NewSDT(t, addr)
    38  }
    39  
    40  // NewSDT returns an SDT, given a Table
    41  func NewSDT(t Table, addr int64) (*SDT, error) {
    42  	s := &SDT{
    43  		Table: t,
    44  		Base:  addr,
    45  	}
    46  	r := bytes.NewReader(t.TableData())
    47  	x := true
    48  	if t.Sig() == "RSDT" {
    49  		x = false
    50  	}
    51  	for r.Len() > 0 {
    52  		var a int64
    53  		if x {
    54  			if err := binary.Read(r, binary.LittleEndian, &a); err != nil {
    55  				return nil, err
    56  			}
    57  		} else {
    58  			var a32 uint32
    59  			if err := binary.Read(r, binary.LittleEndian, &a32); err != nil {
    60  				return nil, err
    61  			}
    62  			a = int64(a32)
    63  		}
    64  		Debug("Add addr %#x", a)
    65  		s.Addrs = append(s.Addrs, a)
    66  	}
    67  	Debug("NewSDT: %v", s.String())
    68  	return s, nil
    69  }
    70  
    71  // String implements string for an SDT.
    72  func (sdt *SDT) String() string {
    73  	return fmt.Sprintf("%s at %#x with %d tables: %#x", String(sdt), sdt.Base, len(sdt.Addrs), sdt.Addrs)
    74  }