acpi

package
v6.0.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2019 License: BSD-3-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package acpi began life as a relatively simple set of functions. At some point we wanted to be able to extend the ACPI table over a kexec and that's when it all went nasty. A few issues crop up. In theory, one should be able to put tables anywhere. In practice, even in the EFI age, this is not simple. The root pointer for tables, RSDP, Root Services Data Pointer, is in memory protected by the southbridge/ICH/PCH with lockdown bits (disable writes once, can not be reset until power on/reset). Writes to it are transparently discarded. (This makes sense, as crap DOS programs probably tried to write that area all the time. Everything -- everything! -- about x86 and BIOS is explainable by DOS, 16 bit addresses, 4 bit segments, 20 bits, and the incredible failure of vision in 1999 of building a bunch of tables with 32 bit pointers in them. The x86 world is nothing if not consistent: short-sighted decisions for 40+ years). The two-byte EBDA pointer (16 bits) is shifted left 4 bits to get a 20-bit address which points to *the range of memory* containing, maybe, the RSDP. The RSDP has to live in the low 20 bits of address space (remember 20 bits, right?) (Yes, I know about the EFI tables which make this restriction less of a problem,

but for now all the firmware I've seen adheres to the "RSDP in e or f segment" rule.)

The RSDP has two pointers in it, one or both containing a value: 32 bit pointer or 64 bit pointer to the RSDT or XSDT. (see "failure of vision" above.) RSDT has 32-bit pointers, XSDT 64-bit pointers. The spec recommends you ignore the 32-bit pointer variants but as of 2019, I still see use of them; this package will read and write the variants but the internal structs are defined with 64-bit pointers (oh, if only the ACPICA code had gotten this right, but that code is pretty bad too). What's really fun: when you generate the [RX]SDT, you need to generate pointers too. It's best to keep those tables in a physically contiguous area, so we do; not all systems follow this rule, which is asking for trouble. Finally, not all tables are generated in a consistent way, e.g. the IBFT is not like most other tables containing variable length data, because the people who created it are Klever. IBFT has its own heap, and the elements in the heap follow rules unlike all other tables. Nice! If you really look at ACPI closely, you can kind of see that it's optimized for NASM, which is part of what makes it so unpleasant. But, it's what we have.

Index

Constants

View Source
const (
	// LengthOffset is the offset of the table length
	LengthOffset = 4
	// CSUMOffset is the offset of the single byte checksum in *most* ACPI tables
	CSUMOffset = 9
	// MinTableLength is the minimum length: 4 byte tag, 4 byte length, 1 byte revision, 1 byte checksum,
	MinTableLength = 10
)
View Source
const (
	// HeaderLength is a common header length for (almost)
	// all ACPI tables.
	HeaderLength = 36
)
View Source
const (
	// Revision marks lowest ACPI revision we support.
	Revision = 2
)

Variables

View Source
var (
	// Debug implements fmt.Sprintf and can be used for debug printing
	Debug = func(string, ...interface{}) {}
)

Functions

func Marshal

func Marshal(t Tabler) ([]byte, error)

Marshal marshals a Tabler into a byte slice. Once marshaling is done, it inserts the length into the standard place at LengthOffset, and then generates and inserts a checksum at CSUMOffset.

func NewRSDP

func NewRSDP(addr uintptr, len uint) []byte

NewRSDP returns a new and partially initialized RSDP, setting only the defaultRSDP values, address, length, and signature.

func ShowTable

func ShowTable(t Tabler) string

ShowTable converts a Table into string.

Types

type Generic

type Generic struct {
	Header
	// contains filtered or unexported fields
}

Generic is the generic ACPI table, with a Header and data This makes it possible for users to change certain parts of the Header (e.g. vendor id) without touching the data. When the table is Marshal'ed out checksums are regenerated.

func (*Generic) AllData

func (g *Generic) AllData() []byte

AllData returns the entire table as a byte slice.

func (*Generic) CheckSum

func (g *Generic) CheckSum() uint8

CheckSum returns the table CheckSum.

func (*Generic) CreatorID

func (g *Generic) CreatorID() uint32

CreatorID returns the table CreatorID.

func (*Generic) CreatorRevision

func (g *Generic) CreatorRevision() uint32

CreatorRevision returns the table CreatorRevision.

func (*Generic) Len

func (g *Generic) Len() uint32

Len returns the length of an entire table.

func (*Generic) Marshal

func (g *Generic) Marshal() ([]byte, error)

Marshal marshals Generic tables. The main use of this function is when you want to tweak the header a bit; you can convert a Raw table to a Generic table, do what you wish, and write it out.

func (*Generic) OEMID

func (g *Generic) OEMID() string

OEMID returns the table OEMID.

func (*Generic) OEMRevision

func (g *Generic) OEMRevision() uint32

OEMRevision returns the table OEMRevision.

func (*Generic) OEMTableID

func (g *Generic) OEMTableID() string

OEMTableID returns the table OEMTableID.

func (*Generic) Revision

func (g *Generic) Revision() uint8

Revision returns the table Revision.

func (*Generic) Sig

func (g *Generic) Sig() string

Sig returns the table signature.

func (*Generic) TableData

func (g *Generic) TableData() []byte

TableData returns the table, minus the common ACPI header.

type Header struct {
	Sig             sig
	Length          uint32
	Revision        uint8
	CheckSum        uint8
	OEMID           oem
	OEMTableID      tableid
	OEMRevision     uint32
	CreatorID       uint32
	CreatorRevision uint32
}

Header is the standard header for all ACPI tables, except the ones that don't use it. (That's a joke. So is ACPI.) We use types that we hope are easy to read; they in turn make writing marshal code with type switches very convenient.

func GetHeader

func GetHeader(t Tabler) *Header

GetHeader extracts a Header from a Tabler and returns a reference to it.

func (*Header) Marshal

func (h *Header) Marshal() ([]byte, error)

Marshal marshals an ACPI Header into a []byte.

type HeapTable

type HeapTable struct {
	Head *bytes.Buffer
	Heap *bytes.Buffer
}

HeapTable is for ACPI tables that have a heap, i.e. the strings are not subtables, as in most ACPI, but are contained in an area at the end of the tables, after the other table elements. So far, we only know of one such table, the IBFT.

func (*HeapTable) Marshal

func (h *HeapTable) Marshal(i interface{}) error

Marshal marshals basic types into HeapTable

type IBFT

type IBFT struct {
	Generic
	// Control
	Multi     flag
	Initiator IBFTInitiator
	NIC0      IBFTNIC
	Target0   IBFTTarget
	NIC1      IBFTNIC
	Target1   IBFTTarget
}

IBFT defines all the bits of an IBFT users might want to set.

func (*IBFT) Marshal

func (ibft *IBFT) Marshal() ([]byte, error)

Marshal marshals an IBFT to a byte slice. It is somewhat complicated by the fact that we need to marshal to two things, a header and a heao; and record pointers to the heap in the head.

type IBFTInitiator

type IBFTInitiator struct {
	Valid                 flag
	Boot                  flag
	SNSServer             ipaddr
	SLPServer             ipaddr
	PrimaryRadiusServer   ipaddr
	SecondaryRadiusServer ipaddr
	Name                  sheap
}

IBFTInitiator defines an initiator

type IBFTNIC

type IBFTNIC struct {
	Valid        flag
	Boot         flag
	Global       flag
	Index        flag
	IPAddress    ipaddr
	SubNet       u8
	Origin       u8
	Gateway      ipaddr
	PrimaryDNS   ipaddr
	SecondaryDNS ipaddr
	DHCP         ipaddr
	VLAN         u16
	MACAddress   mac
	PCIBDF       bdf
	HostName     sheap
}

IBFTNIC defines an IBFT NIC structure.

type IBFTTarget

type IBFTTarget struct {
	Valid             flag
	Boot              flag
	CHAP              flag
	RCHAP             flag     // can you do both? Standard implies yes.
	Index             flag     // 0 or 1
	TargetIP          sockaddr // in host:port format
	BootLUN           u64
	ChapType          u8
	Association       u8
	TargetName        sheap
	CHAPName          sheap
	CHAPSecret        sheap
	ReverseCHAPName   sheap
	ReverseCHAPSecret sheap
}

IBFTTarget defines an IBFT target, a.k.a. server

type RSDP

type RSDP struct {
	// contains filtered or unexported fields
}

RSDP is the v2 version of the RSDP struct, containing 32 and 64 bit pointers. RSDP don't quite follow the ACPI table standard, so some things return empty values. It has nevertheless proven useful to have them. We just define the RSDP for v2 and later here. It's the only one that matters. This whole layout is typical of the overall Failure Of Vision that is ACPI. 64-bit micros had existed for 10 years when ACPI was defined, and they still wired in 32-bit pointer assumptions, and had to backtrack and fix it later. We don't use this struct below, it's only worthwhile as documentation. The RSDP has not changed in 20 years.

func GetRSDP

func GetRSDP() (base int64, rsdp *RSDP, err error)

GetRSDP gets an RSDP. It is able to use several methods, because there is no consistency about how it is done. The base is also returned.

func (*RSDP) AllData

func (r *RSDP) AllData() []byte

AllData returns the RSDP as a []byte

func (*RSDP) Base

func (r *RSDP) Base() int64

Base returns a base address or the [RX]SDT. It will preferentially return the XSDT, but if that is 0 it will return the RSDT address.

func (*RSDP) CheckSum

func (r *RSDP) CheckSum() uint8

CheckSum returns the table CheckSum.

func (*RSDP) CreatorID

func (r *RSDP) CreatorID() uint32

CreatorID returns the table CreatorID.

func (*RSDP) CreatorRevision

func (r *RSDP) CreatorRevision() uint32

CreatorRevision returns the table CreatorRevision.

func (*RSDP) Len

func (r *RSDP) Len() uint32

Len returns the RSDP length

func (*RSDP) Marshal

func (r *RSDP) Marshal() ([]byte, error)

Marshal fails to marshal an RSDP.

func (*RSDP) OEMID

func (r *RSDP) OEMID() string

OEMID returns the RSDP OEMID

func (*RSDP) OEMRevision

func (r *RSDP) OEMRevision() uint32

OEMRevision returns the table OEMRevision.

func (*RSDP) OEMTableID

func (r *RSDP) OEMTableID() string

OEMTableID returns the RSDP OEMTableID

func (*RSDP) Revision

func (r *RSDP) Revision() uint8

Revision returns the RSDP revision, which after 2002 should be >= 2

func (*RSDP) Sig

func (r *RSDP) Sig() string

Sig returns the RSDP signature

func (*RSDP) TableData

func (r *RSDP) TableData() []byte

TableData returns the RSDP table data as a []byte

type Raw

type Raw struct {
	// contains filtered or unexported fields
}

Raw is just a table embedded in a []byte. Operations on Raw are useful for unpacking into a more refined table or just figuring out how to skip a table you don't care about.

func (*Raw) AllData

func (r *Raw) AllData() []byte

AllData returns all the data in a Raw table.

func (*Raw) CheckSum

func (r *Raw) CheckSum() uint8

CheckSum returns the table CheckSum.

func (*Raw) CreatorID

func (r *Raw) CreatorID() uint32

CreatorID returns the table CreatorID.

func (*Raw) CreatorRevision

func (r *Raw) CreatorRevision() uint32

CreatorRevision returns the table CreatorRevision.

func (*Raw) Len

func (r *Raw) Len() uint32

Len returns the total table length.

func (*Raw) Marshal

func (r *Raw) Marshal() ([]byte, error)

Marshal marshals Raw tables to a byte slice.

func (*Raw) OEMID

func (r *Raw) OEMID() string

OEMID returns the table OEMID.

func (*Raw) OEMRevision

func (r *Raw) OEMRevision() uint32

OEMRevision returns the table OEMRevision.

func (*Raw) OEMTableID

func (r *Raw) OEMTableID() string

OEMTableID returns the table OEMTableID.

func (*Raw) Revision

func (r *Raw) Revision() uint8

Revision returns the table Revision.

func (*Raw) Sig

func (r *Raw) Sig() string

Sig returns the table signature.

func (*Raw) TableData

func (r *Raw) TableData() []byte

TableData returns the Raw table, minus the standard ACPI header.

type SDT

type SDT struct {
	Generic
	Tables []int64
	Base   int64
}

SDT represents either an RSDT or XSDT. It has a Generic header and Tables, which are pointers. In the RSDT they are 32 bits; in the XSDT, 64. We unmarshal to 64 bits, and when we marshal, we use the signature to determine whether the table is 32 or 64.

func NewSDT

func NewSDT(opt ...func(*SDT)) (*SDT, error)

NewSDT creates a new SDT, defaulting to XSDT.

func ReadSDT

func ReadSDT() (*SDT, error)

ReadSDT reads an SDT in from memory, using UnMarshalSDT, which uses the io package. This is increasingly unlikely to work over time.

func UnMarshalSDT

func UnMarshalSDT(r *RSDP) (*SDT, error)

UnMarshalSDT unmarshals an SDT. It's pretty much impossible for the RSDP to point to anything else so we mainly do the unmarshal and type assertion.

func (*SDT) Marshal

func (s *SDT) Marshal() ([]byte, error)

Marshal marshals an [RX]SDT. If it has tables, it marshals them too. Note that tables are just pointers in this case. Most users will likely remove the tables (s->Tables = nil) and add their own in the call to MarshalAll.

func (*SDT) MarshalAll

func (s *SDT) MarshalAll(t ...Tabler) ([]byte, error)

MarshalAll marshals out an SDT, and all the tables, in a blob suitable for kexec. The most common use of this call would be to set s->Tables = nil and then pass in the desired Tables as parameters to this function. For passed-in tables, all addresses are recomputed, as there may be more tables. Further, even if tables were scattered all over, we unify them into one segment. There is one potential problem, which we can fix if needed: it is possible the [XR]SDT is placed so close to the top of memory there is no room for the table. In the unlikely event that ever happens, we will just figure out how to place the tables in memory lower than the [XR]SDT.

type Tabler

type Tabler interface {
	Sig() string
	Len() uint32
	Revision() uint8
	CheckSum() uint8
	OEMID() string
	OEMTableID() string
	OEMRevision() uint32
	CreatorID() uint32
	CreatorRevision() uint32
	AllData() []byte
	TableData() []byte
	Marshal() ([]byte, error)
}

Tabler is the interface to ACPI tables, be they held in memory as a byte slice, header and byte slice, or more complex struct.

func NewGeneric

func NewGeneric(b []byte) (Tabler, error)

NewGeneric creates a new Generic table from a byte slice.

func NewRaw

func NewRaw(b []byte) (Tabler, error)

NewRaw returns a new Raw table given a byte slice.

func RawFromFile

func RawFromFile(n string) (Tabler, error)

RawFromFile reads a raw table in from a file.

func RawTables

func RawTables() ([]Tabler, error)

RawTables returns an array of Raw, for all ACPI tables available in /sys

func ReadRaw

func ReadRaw(a int64) (Tabler, error)

ReadRaw reads a full table in, given an address. ReadRaw uses the io package. This may not always work if the kernel has restrictions on reading memory above the 1M boundary, and the tables are above boundary.

func UnMarshal

func UnMarshal(a int64) (Tabler, error)

UnMarshal unmarshals a single table and returns a Tabler. If the table is one of the many we don't care about we just return a Raw table, which can be easily written out again if needed. If it has an UnMarshal registered we use that instead once the Raw is unmarshaled.

func UnMarshalAll

func UnMarshalAll(s *SDT) ([]Tabler, error)

UnMarshalAll takes an SDT and unmarshals all the tables using UnMarshal. It returns a []Tabler. In most cases, the tables will be Raw, but in a few cases they might be further converted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL