github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/cbmem/cbmem_linux_test.go (about)

     1  // Copyright 2021 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 main
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/hex"
    10  	"encoding/json"
    11  	"io"
    12  	"os"
    13  	"path/filepath"
    14  	"testing"
    15  )
    16  
    17  func TestNotFound(t *testing.T) {
    18  	var err error
    19  	f, err := os.CreateTemp("", "cbmemNotFound")
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	if _, err := f.Write(make([]byte, 0x100000)); err != nil {
    24  		t.Fatalf("Writing empty file: got %v, want nil", err)
    25  	}
    26  	var found bool
    27  	for _, addr := range []int64{0, 0xf0000} {
    28  		t.Logf("Check %#08x", addr)
    29  		if _, found, err = parseCBtable(f, addr, 0x10000); err == nil {
    30  			break
    31  		}
    32  	}
    33  	if err != nil {
    34  		t.Errorf("Scanning empty file: got %v, want nil", err)
    35  	}
    36  	if found {
    37  		t.Fatalf("Found a coreboot table in empty file: got nil, want err")
    38  	}
    39  }
    40  
    41  func genFile(f *os.File, p func(string, ...interface{}), s []seg) error {
    42  	// Extend the test file to the full 4G, to match hardware.
    43  	if _, err := f.WriteAt([]byte{1}[:], 0xffffffff); err != nil {
    44  		return err
    45  	}
    46  	for _, r := range s {
    47  		p("Write %d bytes at %#x", len(r.dat), r.off)
    48  		if _, err := f.WriteAt(r.dat, r.off); err != nil {
    49  			return err
    50  		}
    51  	}
    52  	return nil
    53  }
    54  
    55  func TestAPU2(t *testing.T) {
    56  	var err error
    57  	f, err := os.CreateTemp("", "cbmemAPU2")
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	if err := genFile(f, t.Logf, apu2); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	var c *CBmem
    65  	var found bool
    66  	for _, addr := range []int64{0, 0xf0000} {
    67  		t.Logf("Check %#08x", addr)
    68  		if c, found, err = parseCBtable(f, addr, 0x10000); err == nil {
    69  			break
    70  		}
    71  	}
    72  	if !found {
    73  		t.Fatalf("Looking for coreboot table: got false, want true")
    74  	}
    75  	if err != nil {
    76  		t.Fatalf("Reading coreboot table: got %v, want nil", err)
    77  	}
    78  	b := &bytes.Buffer{}
    79  	DumpMem(f, c, false, b)
    80  	t.Logf("%s", b.String())
    81  	o := b.String()
    82  	if o != apu2Mem {
    83  		t.Errorf("APU2 DumpMem: got \n%s\n, want \n%s\n", hex.Dump(b.Bytes()), hex.Dump([]byte(apu2Mem)))
    84  	}
    85  	b.Reset()
    86  	DumpMem(f, c, true, b)
    87  	t.Logf("2nd dump string is %s", b.String())
    88  	if b.Len() == len(apu2Mem) {
    89  		t.Errorf("APU2 DumpMem: got %d bytes output, want more", b.Len())
    90  	}
    91  	// See if JSON even works. TODO: compare output
    92  	j, err := json.MarshalIndent(c, "", "\t")
    93  	if err != nil {
    94  		t.Fatalf("json marshal: %v", err)
    95  	}
    96  	// You can use this to generate new test data. It's a timesaver.
    97  	if false {
    98  		os.WriteFile("json", j, 0o666)
    99  	}
   100  	if string(j) != apu2JSON {
   101  		t.Errorf("APU2 JSON: got %s, want %s", j, apu2JSON)
   102  	}
   103  }
   104  
   105  func TestAPU2CBMemWrap(t *testing.T) {
   106  	var err error
   107  	f, err := os.CreateTemp("", "cbmemWRAPAPU2")
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	// Need to patch this a bit. First, add a patch so that the cursor has wrapped.
   112  	p := apu2
   113  	if true {
   114  		p = append(p, []seg{
   115  			{
   116  				// The buffer size will be 4, and the cursor will be 2 -> wrap.
   117  				off: 0x77fdf000, dat: []byte{
   118  					0x04 /*'ø'*/, 0x00 /*'ÿ'*/, 0x00 /*'\x01'*/, 0x00 /*'\x00'*/, 0x02 /*'\x02' */, 0x00 /*'\x00'*/, 0x00 /*'\x00'*/, 0x80, /*'\x80'*/
   119  				},
   120  			},
   121  		}...)
   122  	}
   123  	if err := genFile(f, t.Logf, p); err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	var c *CBmem
   127  	var found bool
   128  	if c, found, err = parseCBtable(f, 0, 0x10000); err != nil {
   129  		t.Fatalf("reading CB table: got %v, want nil", err)
   130  	}
   131  	if !found {
   132  		t.Fatalf("Looking for coreboot table: got false, want true")
   133  	}
   134  	want := "EnPC"
   135  	got := c.MemConsole.Data
   136  	if got != want {
   137  		t.Fatalf("Console data: got %q, want %q", got, want)
   138  	}
   139  }
   140  
   141  func TestAPU2CBBadCursor(t *testing.T) {
   142  	var err error
   143  	f, err := os.CreateTemp("", "cbmemWRAPAPU2")
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	// Need to patch this a bit. First, add a patch so that the cursor has wrapped.
   148  	p := apu2
   149  	p = append(p, []seg{
   150  		{
   151  			// The buffer size will be 4, and the cursor will be 2 -> wrap.
   152  			off: 0x77fdf000, dat: []byte{
   153  				/*0x77fdf000*/ 0x04 /*'ø'*/, 0x00 /*'ÿ'*/, 0x00 /*'\x01'*/, 0x00 /*'\x00'*/, 0x0a /*'\x0a'*/, 0x00 /*'\x00'*/, 0x00 /*'\x00'*/, 0x80, /*'\x80'*/
   154  			},
   155  		},
   156  	}...)
   157  
   158  	if err := genFile(f, t.Logf, p); err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	var c *CBmem
   162  	var found bool
   163  	if c, found, err = parseCBtable(f, 0, 0x10000); err != nil {
   164  		t.Fatalf("reading CB table: got %v, want nil", err)
   165  	}
   166  	if !found {
   167  		t.Fatalf("Looking for coreboot table: got false, want true")
   168  	}
   169  	want := "PCEn"
   170  	got := c.MemConsole.Data
   171  	if got != want {
   172  		t.Fatalf("Console data: got %q, want %q", got, want)
   173  	}
   174  }
   175  
   176  func TestAPU2CBBadPtr(t *testing.T) {
   177  	var err error
   178  	f, err := os.CreateTemp("", "cbmemWRAPAPU2")
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  	// Need to patch this a bit. First, add a patch so that the cursor has wrapped.
   183  	p := apu2
   184  	p = append(p, []seg{
   185  		{
   186  			off: 0x77fae170, dat: []byte{
   187  				0xff, 0xff, 0xff, 0xff,
   188  			},
   189  		},
   190  	}...)
   191  	if err := genFile(f, t.Logf, p); err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	if _, _, err = parseCBtable(f, 0, 0x10000); err == nil {
   195  		t.Fatalf("reading CB table: got nil, want err")
   196  	}
   197  }
   198  
   199  func TestIO(t *testing.T) {
   200  	var (
   201  		b = [8]byte{1}
   202  		i uint64
   203  	)
   204  	if err := readOneSize(bytes.NewReader(b[:1]), &i, 1, 23); err == nil {
   205  		t.Errorf("readOne on too small buffer: got nil, want err")
   206  	}
   207  	if err := readOneSize(bytes.NewReader(b[:]), &i, 0, 8); err != nil {
   208  		t.Fatalf("readOne: got %v, want nil", err)
   209  	}
   210  	if i != 1 {
   211  		t.Fatalf("readOne value: got %d, want 1", i)
   212  	}
   213  }
   214  
   215  func TestOffsetReader(t *testing.T) {
   216  	memFile, err := os.CreateTemp("", "cbmemAPU2")
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if err := genFile(memFile, t.Logf, apu2); err != nil {
   221  		t.Fatal(err)
   222  	}
   223  	o, err := newOffsetReader(memFile, 0x77fdf040, 1)
   224  	if err != nil {
   225  		t.Fatalf("newOffsetReader: got %v, want nil", err)
   226  	}
   227  	var b [9]byte
   228  	for _, i := range []int64{0x8000000000, -1, 0x77fdf03f} {
   229  		_, err := o.ReadAt(b[:], i)
   230  		if err == nil {
   231  			t.Errorf("Reading newOffsetReader at %#x: got nil, want err", i)
   232  		}
   233  	}
   234  	for _, i := range []int64{0x77fdf040} {
   235  		n, err := o.ReadAt(b[:], i)
   236  		if err != io.EOF {
   237  			t.Errorf("Reading newOffsetReader at %#x: got %v, want io.EOF", i, err)
   238  		}
   239  		if n != 1 {
   240  			t.Errorf("Reading newOffsetReader at %#x: got %d bytes, want nil", i, n)
   241  		}
   242  	}
   243  
   244  	// Now find the LBIO at 0x77fae000
   245  	if o, err = newOffsetReader(memFile, 0x77fae000, 8); err != nil {
   246  		t.Fatalf("newOffsetReader: got %v, want nil", err)
   247  	}
   248  	for _, i := range []int64{0x77fae000} {
   249  		_, err := o.ReadAt(b[:], i)
   250  		if err == nil {
   251  			t.Errorf("Reading newOffsetReader at %#x: got nil, want err", i)
   252  		}
   253  		if string(b[:4]) != "LBIO" {
   254  			t.Errorf("Reading newOffsetReader at %#x: got %q, want LBIO", 0x77fae000, string(b[:4]))
   255  		}
   256  	}
   257  	if err := memFile.Close(); err != nil {
   258  		t.Fatalf("Closing %s: got %v, want nil", memFile.Name(), err)
   259  	}
   260  	if _, err := newOffsetReader(memFile, 0x77fdf040, 1); err == nil {
   261  		t.Fatalf("newOffsetReader: got nil, want err")
   262  	}
   263  }
   264  
   265  func TestTimeStampsAPU2(t *testing.T) {
   266  	f, err := os.CreateTemp("", "cbmemAPU2")
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  	if err := genFile(f, t.Logf, apu2); err != nil {
   271  		t.Fatal(err)
   272  	}
   273  	var c *CBmem
   274  	var found bool
   275  	for _, addr := range []int64{0, 0xf0000} {
   276  		t.Logf("Check %#08x", addr)
   277  		if c, found, err = parseCBtable(f, addr, 0x10000); err == nil {
   278  			break
   279  		}
   280  	}
   281  	if !found {
   282  		t.Fatalf("Looking for coreboot table: got false, want true")
   283  	}
   284  	if err != nil {
   285  		t.Fatalf("Reading coreboot table: got %v, want nil", err)
   286  	}
   287  	if c.TimeStampsTable.Addr != 0 {
   288  		t.Fatalf("TimeStampsTable: got %#x, want 0", c.TimeStampsTable)
   289  	}
   290  }
   291  
   292  func TestCbmem(t *testing.T) {
   293  	for _, tt := range []struct {
   294  		name       string
   295  		mem        string
   296  		version    bool
   297  		verbose    bool
   298  		timestamps bool
   299  		dumpJSON   bool
   300  		list       bool
   301  		console    bool
   302  		want       string
   303  	}{
   304  		{
   305  			name:    "version true",
   306  			version: true,
   307  			want:    "cbmem in Go, including JSON output\n",
   308  		},
   309  		{
   310  			name:    "verbose true",
   311  			verbose: true,
   312  		},
   313  		{
   314  			name:     "dumpJSON true",
   315  			dumpJSON: true,
   316  			want:     "{\n\t\"Memory\": {\n\t\t\"Tag\": 1,\n\t\t\"Size\": 108,\n\t\t\"Maps\": [\n\t\t\t{\n\t\t\t\t\"Start\": 0,\n\t\t\t\t\"Size\": 4096,\n\t\t\t\t\"Mtype\": 16\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Start\": 4096,\n\t\t\t\t\"Size\": 651264,\n\t\t\t\t\"Mtype\": 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Start\": 786432,\n\t\t\t\t\"Size\": 2012143616,\n\t\t\t\t\"Mtype\": 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Start\": 2012930048,\n\t\t\t\t\"Size\": 335872,\n\t\t\t\t\"Mtype\": 16\n\t\t\t}\n\t\t]\n\t},\n\t\"MemConsole\": {\n\t\t\"Tag\": 23,\n\t\t\"Size\": 131064,\n\t\t\"Address\": 2013130752,\n\t\t\"CSize\": 0,\n\t\t\"Cursor\": 240,\n\t\t\"Data\": \"PCEngines apu2\\r\\ncoreboot build 20170228\\r\\n2032 MB DRAM\\r\\n\\r\\n\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\"\n\t},\n\t\"Consoles\": [\n\t\t\"\"\n\t],\n\t\"TimeStampsTable\": {\n\t\t\"Tag\": 0,\n\t\t\"Size\": 0,\n\t\t\"Addr\": 0\n\t},\n\t\"TimeStamps\": null,\n\t\"UART\": [\n\t\t{\n\t\t\t\"Tag\": 15,\n\t\t\t\"Size\": 20,\n\t\t\t\"Type\": 1,\n\t\t\t\"BaseAddr\": 1016,\n\t\t\t\"Baud\": 115200,\n\t\t\t\"RegWidth\": 16\n\t\t}\n\t],\n\t\"MainBoard\": {\n\t\t\"Tag\": 3,\n\t\t\"Size\": 40,\n\t\t\"Vendor\": \"PC Engines\",\n\t\t\"PartNumber\": \"PCEngines apu2\"\n\t},\n\t\"Hwrpb\": {\n\t\t\"Tag\": 0,\n\t\t\"Size\": 0,\n\t\t\"HwrPB\": 0\n\t},\n\t\"CBMemory\": null,\n\t\"BoardID\": {\n\t\t\"Tag\": 37,\n\t\t\"Size\": 16,\n\t\t\"BoardID\": 2012962816\n\t},\n\t\"StringVars\": {\n\t\t\"LB_TAG_BUILD\": \"Tue Feb 28 22:34:13 UTC 2017\",\n\t\t\"LB_TAG_COMPILE_BY\": \"root\",\n\t\t\"LB_TAG_COMPILE_DOMAIN\": \"\",\n\t\t\"LB_TAG_COMPILE_HOST\": \"3aa919ff57dc\",\n\t\t\"LB_TAG_COMPILE_TIME\": \"22:34:13\",\n\t\t\"LB_TAG_EXTRA_VERSION\": \"-4.0.7\",\n\t\t\"LB_TAG_VERSION\": \"8b10004\"\n\t},\n\t\"BootMediaParams\": {\n\t\t\"Tag\": 0,\n\t\t\"Size\": 0,\n\t\t\"FMAPOffset\": 0,\n\t\t\"CBFSOffset\": 0,\n\t\t\"CBFSSize\": 0,\n\t\t\"BootMediaSize\": 0\n\t},\n\t\"VersionTimeStamp\": 38,\n\t\"Unknown\": null,\n\t\"Ignored\": null\n}\n",
   317  		},
   318  		{
   319  			name: "list true",
   320  			list: true,
   321  		},
   322  		{
   323  			name:    "console true",
   324  			console: true,
   325  			want:    "PCEngines apu2\r\ncoreboot build 20170228\r\n2032 MB DRAM\r\n\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
   326  		},
   327  	} {
   328  		t.Run(tt.name, func(t *testing.T) {
   329  			f, err := os.Create(filepath.Join(t.TempDir(), "cbmemAPU2"))
   330  			if err != nil {
   331  				t.Errorf("could not gen file: %v", err)
   332  			}
   333  			defer f.Close()
   334  			if err := genFile(f, t.Logf, apu2); err != nil {
   335  				t.Errorf("could not gen file: %v", err)
   336  			}
   337  
   338  			*mem = f.Name()
   339  			version = tt.version
   340  			verbose = tt.verbose
   341  			timestamps = tt.timestamps
   342  			dumpJSON = tt.dumpJSON
   343  			list = tt.list
   344  			console = tt.console
   345  
   346  			buf := &bytes.Buffer{}
   347  
   348  			got := cbMem(buf)
   349  			if got != nil {
   350  				if got.Error() != tt.want {
   351  					t.Errorf("cbmem() = %q, want: %q", got.Error(), tt.want)
   352  				}
   353  			} else {
   354  				if buf.String() != tt.want {
   355  					t.Errorf("cbmem() = %q, want: %q", buf.String(), tt.want)
   356  				}
   357  			}
   358  		})
   359  	}
   360  }