github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/uefi/uefi_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 uefi
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/mvdan/u-root-coreutils/pkg/acpi"
    13  	"github.com/mvdan/u-root-coreutils/pkg/boot/kexec"
    14  )
    15  
    16  type kexecLoadFunc func(entry uintptr, segments kexec.Segments, flags uint64) error
    17  
    18  // TODO(chengchieh): move this function to kexec package
    19  func mockKexecLoad(entry uintptr, segments kexec.Segments, flags uint64) error {
    20  	if len(segments) > 16 {
    21  		return fmt.Errorf("number of segments should be less than 16 before dedup")
    22  	}
    23  
    24  	segments, err := kexec.AlignAndMerge(segments)
    25  	if err != nil {
    26  		return fmt.Errorf("could not align segments: %w", err)
    27  	}
    28  
    29  	if !segments.PhysContains(entry) {
    30  		return fmt.Errorf("entry point %#v is not covered by any segment", entry)
    31  	}
    32  	return nil
    33  }
    34  
    35  func mockKexecParseMemoryMap() (kexec.MemoryMap, error) {
    36  	return kexec.MemoryMap{}, nil
    37  }
    38  
    39  func mockGetRSDP() (*acpi.RSDP, error) {
    40  	return &acpi.RSDP{}, nil
    41  }
    42  
    43  func mockGetSMBIOSBase() (int64, int64, error) {
    44  	return 100, 200, nil
    45  }
    46  
    47  func TestLoadFvImage(t *testing.T) {
    48  	fv, err := New("testdata/fv_with_sec.fd")
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	defer func(old func() (kexec.MemoryMap, error)) { kexecParseMemoryMap = old }(kexecParseMemoryMap)
    54  	kexecParseMemoryMap = mockKexecParseMemoryMap
    55  
    56  	defer func(old func() (*acpi.RSDP, error)) { getRSDP = old }(getRSDP)
    57  	getRSDP = mockGetRSDP
    58  
    59  	defer func(old func() (int64, int64, error)) { getSMBIOSBase = old }(getSMBIOSBase)
    60  	getSMBIOSBase = mockGetSMBIOSBase
    61  
    62  	defer func(old kexecLoadFunc) { kexecLoad = old }(kexecLoad)
    63  	kexecLoad = mockKexecLoad
    64  
    65  	if err = fv.Load(true); err != nil {
    66  		t.Fatal(err)
    67  	}
    68  }
    69  
    70  func TestNewNotFound(t *testing.T) {
    71  	_, err := New("testdata/uefi_NOT_FOUND.fd")
    72  	want := "open testdata/uefi_NOT_FOUND.fd: no such file or directory"
    73  	if err.Error() != want {
    74  		t.Fatalf("Should be '%s', but get '%v'", want, err)
    75  	}
    76  }
    77  
    78  func TestNewInvalidPayload(t *testing.T) {
    79  	_, err := New("testdata/fv_with_invalid_sec.fd")
    80  	// for golang >= 1.7
    81  	want1 := "unrecognized PE machine"
    82  	// for golang < 1.7
    83  	want2 := "Unrecognised COFF file header"
    84  	if !(strings.Contains(err.Error(), want1) || strings.Contains(err.Error(), want2)) {
    85  		t.Fatalf("Should be '%s' or '%s', but get '%v'", want1, want2, err)
    86  	}
    87  }
    88  
    89  func TestLoadFvImageNotFound(t *testing.T) {
    90  	fv := &FVImage{name: "NOT_FOUND"}
    91  	err := fv.Load(true)
    92  
    93  	want := "open NOT_FOUND: no such file or directory"
    94  
    95  	if err.Error() != want {
    96  		t.Fatalf("Should be '%s', but get '%v'", want, err)
    97  	}
    98  }
    99  
   100  func TestLoadFvImageFailAtParseMemoryMap(t *testing.T) {
   101  	fv, err := New("testdata/fv_with_sec.fd")
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	defer func(old func() (kexec.MemoryMap, error)) { kexecParseMemoryMap = old }(kexecParseMemoryMap)
   107  	kexecParseMemoryMap = func() (kexec.MemoryMap, error) {
   108  		return nil, fmt.Errorf("PARSE_MEMORY_MAP_FAILED")
   109  	}
   110  
   111  	err = fv.Load(true)
   112  
   113  	want := "PARSE_MEMORY_MAP_FAILED"
   114  	if err.Error() != want {
   115  		t.Fatalf("want '%s', get '%v'", want, err)
   116  	}
   117  }
   118  
   119  func TestLoadFvImageFailAtGetRSDP(t *testing.T) {
   120  	fv, err := New("testdata/fv_with_sec.fd")
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	defer func(old func() (kexec.MemoryMap, error)) { kexecParseMemoryMap = old }(kexecParseMemoryMap)
   126  	kexecParseMemoryMap = mockKexecParseMemoryMap
   127  
   128  	defer func(old func() (*acpi.RSDP, error)) { getRSDP = old }(getRSDP)
   129  	getRSDP = func() (*acpi.RSDP, error) {
   130  		return nil, fmt.Errorf("RSDP_NOT_FOUND")
   131  	}
   132  
   133  	err = fv.Load(true)
   134  
   135  	want := "RSDP_NOT_FOUND"
   136  	if err.Error() != want {
   137  		t.Fatalf("want '%s', get '%v'", want, err)
   138  	}
   139  }
   140  
   141  func TestLoadFvImageFailAtGetSMBIOS(t *testing.T) {
   142  	fv, err := New("testdata/fv_with_sec.fd")
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	defer func(old func() (kexec.MemoryMap, error)) { kexecParseMemoryMap = old }(kexecParseMemoryMap)
   148  	kexecParseMemoryMap = mockKexecParseMemoryMap
   149  
   150  	defer func(old func() (*acpi.RSDP, error)) { getRSDP = old }(getRSDP)
   151  	getRSDP = mockGetRSDP
   152  
   153  	defer func(old func() (int64, int64, error)) { getSMBIOSBase = old }(getSMBIOSBase)
   154  	getSMBIOSBase = func() (int64, int64, error) {
   155  		t.Log("mock getSMBIOSBase()")
   156  		return 100, 200, fmt.Errorf("SMBIOS_NOT_FOUND")
   157  	}
   158  
   159  	err = fv.Load(true)
   160  
   161  	want := "SMBIOS_NOT_FOUND"
   162  	if err.Error() != want {
   163  		t.Fatalf("want '%s', get '%v'", want, err)
   164  	}
   165  }
   166  
   167  func TestLoadFvImageFailAtKexec(t *testing.T) {
   168  	fv, err := New("testdata/fv_with_sec.fd")
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	defer func(old func() (kexec.MemoryMap, error)) { kexecParseMemoryMap = old }(kexecParseMemoryMap)
   174  	kexecParseMemoryMap = mockKexecParseMemoryMap
   175  
   176  	defer func(old func() (*acpi.RSDP, error)) { getRSDP = old }(getRSDP)
   177  	getRSDP = mockGetRSDP
   178  
   179  	defer func(old func() (int64, int64, error)) { getSMBIOSBase = old }(getSMBIOSBase)
   180  	getSMBIOSBase = mockGetSMBIOSBase
   181  
   182  	defer func(old kexecLoadFunc) { kexecLoad = old }(kexecLoad)
   183  	kexecLoad = func(entry uintptr, segments kexec.Segments, flags uint64) error {
   184  		return fmt.Errorf("KEXEC_FAILED")
   185  	}
   186  
   187  	err = fv.Load(true)
   188  
   189  	want := "kexec.Load() error: KEXEC_FAILED"
   190  	if err.Error() != want {
   191  		t.Fatalf("want '%s', get '%v'", want, err)
   192  	}
   193  }