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 }