github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/ibft/ibft_test.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 ibft 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "encoding/hex" 11 "net" 12 "testing" 13 14 "github.com/davecgh/go-spew/spew" 15 "github.com/google/go-cmp/cmp" 16 ) 17 18 var spewConfig = &spew.ConfigState{ 19 Indent: " ", 20 DisablePointerAddresses: true, 21 DisableCapacities: true, 22 } 23 24 // Header is described in iBFT Spec 1.4.3. 25 func emptyHeader() []byte { 26 return append([]byte("iBFT\x00\x00\x00\x00\x01\x00GoogleGoogIBFT"), bytes.Repeat([]byte{0}, 24)...) 27 } 28 29 func defaultControl() []byte { 30 return []byte{ 31 0x01 /* Control ID */, 0x01 /* version */, 18, 0 /* length */, 0 /* index */, 0 /* flags */, 0, 0, /* extensions */ 32 0x48, 0 /* Initiator */, 0x98, 0x0 /* NIC0 */, 0x0, 0x01 /* Target0 */, 0x0, 0x0 /* NIC1 */, 0x0, 0x0, /* Target1 */ 33 0, 0, 0, 0, 0, 0, /* padding */ 34 } 35 } 36 37 // Offsets are from iBFT Spec Section 1.4.5. 38 func initiator(flags byte, nameLen uint16, nameOffset uint16) []byte { 39 b := append(append( 40 []byte{0x02 /* Initiator ID */, 0x01 /* version */, 74, 0 /* length */, 0 /* index */, flags /* flags */}, 41 bytes.Repeat([]byte{0}, 16*4)...), 42 0, 0 /* initiator name length */, 0, 0, /* initiator name offset */ 43 0, 0, 0, 0, 0, 0, /* padding */ 44 ) 45 binary.LittleEndian.PutUint16(b[70:], nameLen) 46 binary.LittleEndian.PutUint16(b[72:], nameOffset) 47 return b 48 } 49 50 func emptyNIC() []byte { 51 return nic(0, nil, 0, nil, nil, nil, nil, 0) 52 } 53 54 // Offsets are from iBFT Spec Section 1.4.6. 55 func nic(flags uint8, ip net.IP, subnetMaskPrefix uint8, gateway, dns, dhcp net.IP, mac net.HardwareAddr, bdf uint16) []byte { 56 empty := append( 57 append( 58 []byte{0x03 /* NIC ID */, 0x01 /* version */, 102, 0 /* length */, 0 /* index */, flags /* flags */}, 59 bytes.Repeat([]byte{0}, 16+1+1+16*4+2+6+2+2+2)..., /* all fields */ 60 ), 61 0, 0, /* padding for alignment */ 62 ) 63 if ip != nil { 64 copy(empty[6:], ip.To16()) 65 } 66 empty[22] = subnetMaskPrefix 67 if gateway != nil { 68 copy(empty[24:], gateway.To16()) 69 } 70 if dns != nil { 71 copy(empty[40:], dns.To16()) 72 } 73 if dhcp != nil { 74 copy(empty[72:], dhcp.To16()) 75 } 76 if mac != nil { 77 copy(empty[90:], mac) 78 } 79 binary.LittleEndian.PutUint16(empty[96:], bdf) 80 return empty 81 } 82 83 func emptyTarget() []byte { 84 return target(0, nil, 0, 0, 0) 85 } 86 87 // Offsets are from iBFT Spec Section 1.4.7. 88 func target(flags uint8, ip net.IP, port uint16, nameLen uint16, nameOffset uint16) []byte { 89 empty := append( 90 []byte{0x04 /* Target ID */, 0x01 /* version */, 54, 0 /* length */, 0 /* index */, flags /* flags */}, 91 bytes.Repeat([]byte{0}, 49+1)..., /* all fields + 1 bytes padding for alignment */ 92 ) 93 if ip != nil { 94 copy(empty[6:], ip.To16()) 95 } 96 binary.LittleEndian.PutUint16(empty[22:], port) 97 binary.LittleEndian.PutUint16(empty[34:], nameLen) 98 binary.LittleEndian.PutUint16(empty[36:], nameOffset) 99 return empty 100 } 101 102 func heap(s []string) []byte { 103 var h []byte 104 for _, t := range s { 105 h = append(h, []byte(t)...) 106 h = append(h, 0) 107 } 108 return h 109 } 110 111 func join(b ...[]byte) []byte { 112 var r []byte 113 for _, bb := range b { 114 r = append(r, bb...) 115 } 116 return r 117 } 118 119 func TestMarshal(t *testing.T) { 120 for _, tt := range []struct { 121 desc string 122 i *IBFT 123 want []byte 124 }{ 125 { 126 desc: "empty iBFT", 127 i: &IBFT{}, 128 want: fixACPIHeader(join(emptyHeader(), defaultControl(), initiator(0, 0, 0), emptyNIC(), emptyTarget())), 129 }, 130 { 131 desc: "IBFT with relevant stuff.", 132 i: &IBFT{ 133 Initiator: Initiator{ 134 Valid: true, 135 Boot: true, 136 Name: "NERF", 137 }, 138 NIC0: NIC{ 139 Valid: true, 140 Boot: true, 141 Global: true, 142 IPNet: &net.IPNet{ 143 IP: net.IP{192, 168, 1, 15}, 144 Mask: net.IPv4Mask(255, 255, 255, 0), 145 }, 146 Gateway: net.IP{192, 168, 1, 1}, 147 PrimaryDNS: net.IP{8, 8, 8, 8}, 148 DHCPServer: net.IP{192, 168, 1, 1}, 149 MACAddress: net.HardwareAddr{52, 54, 00, 12, 34, 56}, 150 }, 151 Target0: Target{ 152 Valid: true, 153 Boot: true, 154 Target: &net.TCPAddr{ 155 IP: net.IP{192, 168, 1, 1}, 156 Port: 3260, 157 }, 158 TargetName: "iqn.2016-01.com.example:foo", 159 }, 160 }, 161 want: fixACPIHeader(join( 162 emptyHeader(), 163 defaultControl(), 164 initiator(1<<1|1, 4 /* len */, 0x138), 165 nic(1<<2|1<<1|1, net.IP{192, 168, 1, 15} /* ip */, 24 /* netmask */, net.IP{192, 168, 1, 1} /* gateway */, net.IP{8, 8, 8, 8} /* dns */, net.IP{192, 168, 1, 1} /* dhcp serv */, net.HardwareAddr{52, 54, 00, 12, 34, 56} /* mac */, 0 /* BDF */), 166 target(1<<1|1, net.IP{192, 168, 1, 1}, 3260, 27, 0x138+5), 167 heap([]string{"NERF", "iqn.2016-01.com.example:foo"})), 168 ), 169 }, 170 } { 171 t.Run(tt.desc, func(t *testing.T) { 172 got := tt.i.Marshal() 173 174 t.Logf("got:\n%s", hex.Dump(got)) 175 t.Logf("want:\n%s", hex.Dump(tt.want)) 176 177 if !cmp.Equal(got, tt.want) { 178 t.Errorf("IBFT(%s).Marshal() differences: %s", spewConfig.Sdump(tt.i), cmp.Diff(got, tt.want)) 179 } 180 }) 181 } 182 }