github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/pci/devices_test.go (about) 1 // Copyright 2022 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 pci 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 "os" 11 "path/filepath" 12 "strings" 13 "testing" 14 ) 15 16 func TestPrint(t *testing.T) { 17 for _, tt := range []struct { 18 name string 19 devices Devices 20 verbose int 21 confSize int 22 want string 23 }{ 24 { 25 name: "test1", 26 devices: Devices{ 27 &PCI{ 28 Config: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 30 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 36 }, 37 Bridge: true, 38 IO: BAR{ 39 Base: 64, 40 }, 41 IRQPin: 10, 42 }, 43 }, 44 verbose: 10, 45 confSize: 10, 46 want: `: : 47 Control: I/O- Memory- DMA- Special- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisInt- 48 Status: INTx- Cap- 66MHz- UDF- FastB2b- ParErr- DEVSEL- DEVSEL=fast <MABORT- >SERR- <PERR- 49 Latency: 0, Cache Line Size: 255 bytes 50 Bus: primary=00, secondary=00, subordinate=00, sec-latency= 51 I/O behind bridge: 0x00000040-0x00000000 [size=0xffffffffffffffc1] 52 Memory behind bridge: [disabled] 53 Prefetchable memory behind bridge: [disabled] 54 Interrupt: pin 13 routed to IRQ 0 55 00000000 ff ff ff ff ff ff ff ff ff ff 56 `, 57 }, 58 { 59 name: "test2", 60 devices: Devices{ 61 &PCI{ 62 Config: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 }, 71 BARS: []BAR{ 72 { 73 Base: 64, 74 }, 75 }, 76 }, 77 }, 78 verbose: 0, 79 confSize: 0, 80 want: `: : 81 Control: I/O- Memory- DMA- Special- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisInt- 82 Status: INTx- Cap- 66MHz- UDF- FastB2b- ParErr- DEVSEL- DEVSEL=fast <MABORT- >SERR- <PERR- 83 Latency: 0 84 Region 0: Memory at 00000040 (32-bit, non-prefetchable) [size=0xffffffffffffffc1] 85 86 `, 87 }, 88 } { 89 t.Run(tt.name, func(t *testing.T) { 90 var writeBuf = &bytes.Buffer{} 91 if got := tt.devices.Print(writeBuf, 10, tt.confSize); got == nil { 92 if writeBuf.String() != tt.want { 93 t.Errorf("Buffer contains = %q, want: %q", writeBuf.String(), tt.want) 94 } 95 } 96 }) 97 } 98 } 99 100 func TestSetVendorDeviceName(t *testing.T) { 101 for _, tt := range []struct { 102 name string 103 devices Devices 104 VendorNameWant string 105 DeviceNameWant string 106 }{ 107 { 108 name: "Lookup Using ID 80ee Device cafe", 109 devices: Devices{ 110 &PCI{ 111 Vendor: 0x80ee, 112 Device: 0xcafe, 113 }, 114 }, 115 VendorNameWant: "InnoTek Systemberatung GmbH", 116 DeviceNameWant: "VirtualBox Guest Service", 117 }, 118 { 119 name: "Lookup Using ID 1055 Device e420", 120 devices: Devices{ 121 &PCI{ 122 Vendor: 0x1055, 123 Device: 0xe420, 124 }, 125 }, 126 VendorNameWant: "Efar Microsystems", 127 DeviceNameWant: "LAN9420/LAN9420i", 128 }, 129 } { 130 t.Run(tt.name, func(t *testing.T) { 131 tt.devices.SetVendorDeviceName() 132 VendorNameGot, DeviceNameGot := tt.devices[0].VendorName, tt.devices[0].DeviceName 133 if VendorNameGot != tt.VendorNameWant { 134 t.Errorf("Vendor mismatch, got: %q, want: %q\n", VendorNameGot, tt.VendorNameWant) 135 } 136 if DeviceNameGot != tt.DeviceNameWant { 137 t.Errorf("Device mismatch, got: %q, want: %q\n", DeviceNameGot, tt.DeviceNameWant) 138 } 139 }) 140 } 141 } 142 143 func TestReadConfig(t *testing.T) { 144 configBytes := []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} 145 dir := t.TempDir() 146 f, err := os.Create(filepath.Join(dir, "config")) 147 if err != nil { 148 t.Errorf("Creating file failed: %v", err) 149 } 150 _, err = f.Write(configBytes) 151 if err != nil { 152 t.Errorf("Writing to file failed: %v", err) 153 } 154 for _, tt := range []struct { 155 name string 156 devices Devices 157 controlWant Control 158 statusWant Status 159 errWant string 160 }{ 161 { 162 name: "Reading config file", 163 devices: Devices{ 164 &PCI{ 165 FullPath: dir, 166 }, 167 }, 168 controlWant: 0x5544, 169 statusWant: 0x7766, 170 }, 171 { 172 name: "config file does not exist", 173 devices: Devices{ 174 &PCI{ 175 FullPath: "d", 176 }, 177 }, 178 errWant: "no such file or directory", 179 }, 180 } { 181 t.Run(tt.name, func(t *testing.T) { 182 if got := tt.devices.ReadConfig(); got != nil { 183 if !strings.Contains(got.Error(), tt.errWant) { 184 t.Errorf("ReadConfig() = %q, want to contain: %q", got, tt.errWant) 185 } 186 } else { 187 if tt.devices[0].Control != tt.controlWant { 188 t.Errorf("Control is = '%#x', want: '%#x'", tt.devices[0].Control, tt.controlWant) 189 } 190 if tt.devices[0].Status != tt.statusWant { 191 t.Errorf("Status is = '%#x', want: '%#x'", tt.devices[0].Status, tt.statusWant) 192 } 193 } 194 }) 195 } 196 } 197 198 func TestReadConfigRegister(t *testing.T) { 199 configBytes := []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} 200 dir := t.TempDir() 201 f, err := os.Create(filepath.Join(dir, "config")) 202 if err != nil { 203 t.Errorf("Creating file failed: %v", err) 204 } 205 _, err = f.Write(configBytes) 206 if err != nil { 207 t.Errorf("Writing to file failed: %v", err) 208 } 209 for _, tt := range []struct { 210 name string 211 devices Devices 212 offset int64 213 size int64 214 valsWant uint64 215 errWant string 216 }{ 217 { 218 name: "read byte 2 from config file", 219 devices: Devices{ 220 &PCI{ 221 FullPath: dir, 222 }, 223 }, 224 offset: 1, 225 size: 8, 226 valsWant: 0x11, 227 }, 228 { 229 name: "read byte 2 & 3 from config file", 230 devices: Devices{ 231 &PCI{ 232 FullPath: dir, 233 }, 234 }, 235 offset: 1, 236 size: 16, 237 valsWant: 0x2211, 238 }, 239 { 240 name: "wrong size", 241 devices: Devices{ 242 &PCI{ 243 FullPath: dir, 244 }, 245 }, 246 offset: 0, 247 size: 0, 248 errWant: "only options are 8, 16, 32, 64", 249 }, 250 { 251 name: "config file does not exist", 252 devices: Devices{ 253 &PCI{ 254 FullPath: "d", 255 }, 256 }, 257 errWant: "no such file or directory", 258 }, 259 } { 260 t.Run(tt.name, func(t *testing.T) { 261 if vals, got := tt.devices.ReadConfigRegister(tt.offset, tt.size); got != nil { 262 if !strings.Contains(got.Error(), tt.errWant) { 263 t.Errorf("ReadConfig() = %q, want to contain: %q", got, tt.errWant) 264 } 265 } else { 266 if vals[0] != tt.valsWant { 267 t.Errorf("ReadConfig() = '%#x', want: '%#x'", vals[0], tt.valsWant) 268 } 269 } 270 }) 271 } 272 } 273 274 func TestWriteConfigRegister(t *testing.T) { 275 configBytes := []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} 276 dir := t.TempDir() 277 f, err := os.Create(filepath.Join(dir, "config")) 278 if err != nil { 279 t.Errorf("Creating file failed: %v", err) 280 } 281 _, err = f.Write(configBytes) 282 if err != nil { 283 t.Errorf("Writing to file failed: %v", err) 284 } 285 for _, tt := range []struct { 286 name string 287 devices Devices 288 offset int64 289 size int64 290 val uint64 291 want string 292 errWant string 293 }{ 294 { 295 name: "Writing 1 byte to config file with offset 1", 296 devices: Devices{ 297 &PCI{ 298 FullPath: dir, 299 }, 300 }, 301 offset: 1, 302 size: 8, 303 val: 0x22, 304 want: "0022223344556677", 305 }, 306 { 307 name: "Writing 2 bytes to config file with offset 1", 308 devices: Devices{ 309 &PCI{ 310 FullPath: dir, 311 }, 312 }, 313 offset: 1, 314 size: 16, 315 val: 0x4433, 316 want: "0033443344556677", 317 }, 318 { 319 name: "config file does not exist", 320 devices: Devices{ 321 &PCI{ 322 FullPath: "d", 323 }, 324 }, 325 errWant: "no such file or directory", 326 }, 327 } { 328 t.Run(tt.name, func(t *testing.T) { 329 if got := tt.devices.WriteConfigRegister(tt.offset, tt.size, tt.val); got != nil { 330 if !strings.Contains(got.Error(), tt.errWant) { 331 t.Errorf("ReadConfig() = %q, want to contain: %q", got, tt.errWant) 332 } 333 } else { 334 got, err := os.ReadFile(filepath.Join(dir, "config")) 335 if err != nil { 336 t.Errorf("Failed to read file %v", err) 337 } 338 if hex.EncodeToString(got) != tt.want { 339 t.Errorf("Config file contains = %q, want: %q", hex.EncodeToString(got), tt.want) 340 } 341 } 342 }) 343 } 344 }