github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/pkg/acpi/fns.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  	"log"
    12  	"net"
    13  	"reflect"
    14  )
    15  
    16  // gencsum generates a uint8 checksum of a []uint8
    17  func gencsum(b []uint8) uint8 {
    18  	var csum uint8
    19  	for _, bb := range b {
    20  		csum += bb
    21  	}
    22  	Debug("csum %#x %#x across %d bytes", csum, ^csum, len(b))
    23  	return ^csum + 1
    24  }
    25  
    26  // HeapTable is for ACPI tables that have a heap, i.e. the strings
    27  // are not subtables, as in most ACPI, but are contained in an area
    28  // at the end of the tables, after the other table elements. So far,
    29  // we only know of one such table, the IBFT.
    30  type HeapTable struct {
    31  	Head *bytes.Buffer
    32  	Heap *bytes.Buffer
    33  }
    34  
    35  // Marshal marshals basic types into HeapTable
    36  func (h *HeapTable) Marshal(i interface{}) error {
    37  	switch s := i.(type) {
    38  	case sockaddr:
    39  		Debug("addr")
    40  		a, err := net.ResolveTCPAddr("tcp", string(s))
    41  		if err != nil {
    42  			return fmt.Errorf("addr %s: %v", s, err)
    43  		}
    44  		w(h.Head, a.IP.To16(), uint16(a.Port))
    45  	case ipaddr:
    46  		a, err := net.ResolveIPAddr("ip", string(s))
    47  		if err != nil {
    48  			return fmt.Errorf("addr %s: %v", s, err)
    49  		}
    50  		w(h.Head, a.IP.To16())
    51  		Debug("net")
    52  	case flag:
    53  	case mac:
    54  		hw, err := net.ParseMAC(string(s))
    55  		if err != nil {
    56  			return err
    57  		}
    58  		if len(hw) != 6 {
    59  			return fmt.Errorf("%q is not an ethernet MAC", s)
    60  		}
    61  		w(h.Head, hw)
    62  		Debug("mac")
    63  	case bdf:
    64  		if err := uw(h.Head, string(s), 16); err != nil {
    65  			return err
    66  		}
    67  		Debug("bdf")
    68  	case u8:
    69  		if err := uw(h.Head, string(s), 8); err != nil {
    70  			return err
    71  		}
    72  
    73  	case u16:
    74  		if err := uw(h.Head, string(s), 16); err != nil {
    75  			return err
    76  		}
    77  
    78  	case u64:
    79  		if err := uw(h.Head, string(s), 64); err != nil {
    80  			return err
    81  		}
    82  	case sheap:
    83  		w(h.Head, uint16(len(s)), uint16(h.Heap.Len()))
    84  		Debug("Write %q to heap", string(s))
    85  		w(h.Heap, []byte(s))
    86  	default:
    87  		return fmt.Errorf("Don't know what to do with %T", s)
    88  	}
    89  	return nil
    90  }
    91  
    92  // Marshal marshals an ACPI Header into a []byte.
    93  func (h *Header) Marshal() ([]byte, error) {
    94  	nt := reflect.TypeOf(h).Elem()
    95  	nv := reflect.ValueOf(h).Elem()
    96  	var b = &bytes.Buffer{}
    97  	for i := 0; i < nt.NumField(); i++ {
    98  		f := nt.Field(i)
    99  		ft := f.Type
   100  		fv := nv.Field(i)
   101  
   102  		Debug("Header Marshal Field %d: %d ml %v %T (%v, %v)", i, b.Len(), f, f, ft, fv)
   103  		var err error
   104  		switch s := fv.Interface().(type) {
   105  
   106  		case u8:
   107  			if err := uw(b, string(s), 8); err != nil {
   108  				return nil, err
   109  			}
   110  
   111  		case u16:
   112  			if err := uw(b, string(s), 16); err != nil {
   113  				return nil, err
   114  			}
   115  
   116  		case u32:
   117  			if err := uw(b, string(s), 32); err != nil {
   118  				return nil, err
   119  			}
   120  		case u64:
   121  			if err := uw(b, string(s), 64); err != nil {
   122  				return nil, err
   123  			}
   124  		case sig:
   125  			if err := binary.Write(b, binary.LittleEndian, []byte(s)); err != nil {
   126  				return nil, err
   127  			}
   128  		case oem:
   129  			if err := binary.Write(b, binary.LittleEndian, []byte(s)); err != nil {
   130  				return nil, err
   131  			}
   132  		case tableid:
   133  			if err := binary.Write(b, binary.LittleEndian, []byte(s)); err != nil {
   134  				return nil, err
   135  			}
   136  		case uint32, uint8, uint16, uint64:
   137  			err = binary.Write(b, binary.LittleEndian, s)
   138  
   139  		default:
   140  			log.Panicf("Don't know what to do with %T", s)
   141  			return nil, fmt.Errorf("Don't know what to do with %T", s)
   142  		}
   143  		if err != nil {
   144  			return nil, err
   145  		}
   146  	}
   147  	return b.Bytes(), nil
   148  }
   149  
   150  // ShowTable converts a Table into string.
   151  func ShowTable(t Tabler) string {
   152  	return fmt.Sprintf("%s %d %d %#02x %s %s %#08x %#08x %#08x",
   153  		t.Sig(),
   154  		t.Len(),
   155  		t.Revision(),
   156  		t.CheckSum(),
   157  		t.OEMID(),
   158  		t.OEMTableID(),
   159  		t.OEMRevision(),
   160  		t.CreatorID(),
   161  		t.CreatorRevision())
   162  
   163  }