gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/bootloader/efi/efi_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package efi_test
    21  
    22  import (
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"strings"
    27  	"testing"
    28  
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/bootloader/bootloadertest"
    32  	"github.com/snapcore/snapd/bootloader/efi"
    33  	"github.com/snapcore/snapd/dirs"
    34  	"github.com/snapcore/snapd/osutil"
    35  	"github.com/snapcore/snapd/testutil"
    36  )
    37  
    38  type efiVarsSuite struct {
    39  	testutil.BaseTest
    40  
    41  	rootdir string
    42  }
    43  
    44  var _ = Suite(&efiVarsSuite{})
    45  
    46  func TestBoot(t *testing.T) { TestingT(t) }
    47  
    48  func (s *efiVarsSuite) SetUpTest(c *C) {
    49  	s.BaseTest.SetUpTest(c)
    50  
    51  	s.rootdir = c.MkDir()
    52  	dirs.SetRootDir(s.rootdir)
    53  	s.AddCleanup(func() { dirs.SetRootDir("") })
    54  
    55  	err := os.MkdirAll(filepath.Join(s.rootdir, "/sys/firmware/efi/efivars"), 0755)
    56  	c.Assert(err, IsNil)
    57  
    58  	efivarfsMount := `
    59  38 24 0:32 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:13 - efivarfs efivarfs rw
    60  `
    61  	restore := osutil.MockMountInfo(strings.TrimSpace(efivarfsMount))
    62  	s.AddCleanup(restore)
    63  }
    64  
    65  func (s *efiVarsSuite) TestNoEFISystem(c *C) {
    66  	// no efivarfs
    67  	osutil.MockMountInfo("")
    68  
    69  	_, _, err := efi.ReadVarBytes("my-cool-efi-var")
    70  	c.Check(err, Equals, efi.ErrNoEFISystem)
    71  
    72  	_, _, err = efi.ReadVarString("my-cool-efi-var")
    73  	c.Check(err, Equals, efi.ErrNoEFISystem)
    74  }
    75  
    76  func (s *efiVarsSuite) TestSizeError(c *C) {
    77  	// mock the efi var file
    78  	varPath := filepath.Join(s.rootdir, "/sys/firmware/efi/efivars", "my-cool-efi-var")
    79  	err := ioutil.WriteFile(varPath, []byte("\x06"), 0644)
    80  	c.Assert(err, IsNil)
    81  
    82  	_, _, err = efi.ReadVarBytes("my-cool-efi-var")
    83  	c.Check(err, ErrorMatches, `cannot read EFI var "my-cool-efi-var": unexpected size: 1`)
    84  }
    85  
    86  func (s *efiVarsSuite) TestReadVarBytes(c *C) {
    87  	// mock the efi var file
    88  	varPath := filepath.Join(s.rootdir, "/sys/firmware/efi/efivars", "my-cool-efi-var")
    89  	err := ioutil.WriteFile(varPath, []byte("\x06\x00\x00\x00\x01"), 0644)
    90  	c.Assert(err, IsNil)
    91  
    92  	data, attr, err := efi.ReadVarBytes("my-cool-efi-var")
    93  	c.Assert(err, IsNil)
    94  	c.Check(attr, Equals, efi.VariableBootServiceAccess|efi.VariableRuntimeAccess)
    95  	c.Assert(string(data), Equals, "\x01")
    96  }
    97  
    98  func (s *efiVarsSuite) TestReadVarString(c *C) {
    99  	// mock the efi var file
   100  	varPath := filepath.Join(s.rootdir, "/sys/firmware/efi/efivars", "my-cool-efi-var")
   101  	err := ioutil.WriteFile(varPath, []byte("\x06\x00\x00\x00A\x009\x00F\x005\x00C\x009\x004\x009\x00-\x00A\x00B\x008\x009\x00-\x005\x00B\x004\x007\x00-\x00A\x007\x00B\x00F\x00-\x005\x006\x00D\x00D\x002\x008\x00F\x009\x006\x00E\x006\x005\x00\x00\x00"), 0644)
   102  	c.Assert(err, IsNil)
   103  
   104  	data, attr, err := efi.ReadVarString("my-cool-efi-var")
   105  	c.Assert(err, IsNil)
   106  	c.Check(attr, Equals, efi.VariableBootServiceAccess|efi.VariableRuntimeAccess)
   107  	c.Assert(data, Equals, "A9F5C949-AB89-5B47-A7BF-56DD28F96E65")
   108  }
   109  
   110  func (s *efiVarsSuite) TestEmpty(c *C) {
   111  	// mock the efi var file
   112  	varPath := filepath.Join(s.rootdir, "/sys/firmware/efi/efivars", "my-cool-efi-var")
   113  	err := ioutil.WriteFile(varPath, []byte("\x06\x00\x00\x00"), 0644)
   114  	c.Assert(err, IsNil)
   115  
   116  	b, _, err := efi.ReadVarBytes("my-cool-efi-var")
   117  	c.Assert(err, IsNil)
   118  	c.Check(b, HasLen, 0)
   119  
   120  	v, _, err := efi.ReadVarString("my-cool-efi-var")
   121  	c.Assert(err, IsNil)
   122  	c.Check(v, HasLen, 0)
   123  }
   124  
   125  func (s *efiVarsSuite) TestMockVars(c *C) {
   126  	restore := efi.MockVars(map[string][]byte{
   127  		"a": []byte("\x01"),
   128  		"b": []byte("\x02"),
   129  	}, map[string]efi.VariableAttr{
   130  		"b": efi.VariableNonVolatile | efi.VariableRuntimeAccess | efi.VariableBootServiceAccess,
   131  	})
   132  	defer restore()
   133  
   134  	b, attr, err := efi.ReadVarBytes("a")
   135  	c.Assert(err, IsNil)
   136  	c.Check(attr, Equals, efi.VariableBootServiceAccess|efi.VariableRuntimeAccess)
   137  	c.Assert(string(b), Equals, "\x01")
   138  
   139  	b, attr, err = efi.ReadVarBytes("b")
   140  	c.Assert(err, IsNil)
   141  	c.Check(attr, Equals, efi.VariableBootServiceAccess|efi.VariableRuntimeAccess|efi.VariableNonVolatile)
   142  	c.Assert(string(b), Equals, "\x02")
   143  
   144  }
   145  
   146  func (s *efiVarsSuite) TestMockStringVars(c *C) {
   147  	restore := efi.MockVars(map[string][]byte{
   148  		"a": bootloadertest.UTF16Bytes("foo-bar-baz"),
   149  	}, nil)
   150  	defer restore()
   151  
   152  	v, attr, err := efi.ReadVarString("a")
   153  	c.Assert(err, IsNil)
   154  	c.Check(attr, Equals, efi.VariableBootServiceAccess|efi.VariableRuntimeAccess)
   155  	c.Assert(v, Equals, "foo-bar-baz")
   156  }
   157  
   158  func (s *efiVarsSuite) TestMockVarsNoEFISystem(c *C) {
   159  	restore := efi.MockVars(nil, nil)
   160  	defer restore()
   161  
   162  	_, _, err := efi.ReadVarBytes("a")
   163  	c.Check(err, Equals, efi.ErrNoEFISystem)
   164  }
   165  
   166  func (s *efiVarsSuite) TestStringOddSize(c *C) {
   167  	restore := efi.MockVars(map[string][]byte{
   168  		"a": []byte("\x0a"),
   169  	}, nil)
   170  	defer restore()
   171  
   172  	_, _, err := efi.ReadVarString("a")
   173  	c.Check(err, ErrorMatches, `EFI var "a" is not a valid UTF16 string, it has an extra byte`)
   174  }