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  }