github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/efivarfs/vars.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 efivarfs allows interaction with efivarfs of the
     6  // linux kernel.
     7  package efivarfs
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"strings"
    14  
    15  	guid "github.com/google/uuid"
    16  )
    17  
    18  // VariableAttributes is an uint32 identifying the variables attributes.
    19  type VariableAttributes uint32
    20  
    21  const (
    22  	// AttributeNonVolatile indicates a variable is non volatile.
    23  	AttributeNonVolatile VariableAttributes = 0x00000001
    24  	// AttributeBootserviceAccess indicates a variable is accessible during boot service.
    25  	AttributeBootserviceAccess VariableAttributes = 0x00000002
    26  	// AttributeRuntimeAccess indicates a variable is accessible during runtime.
    27  	AttributeRuntimeAccess VariableAttributes = 0x00000004
    28  	// AttributeHardwareErrorRecord indicates a variable holds hardware error records.
    29  	AttributeHardwareErrorRecord VariableAttributes = 0x00000008
    30  	// AttributeAuthenticatedWriteAccess indicates a variable needs authentication before write access.
    31  	AttributeAuthenticatedWriteAccess VariableAttributes = 0x00000010
    32  	// AttributeTimeBasedAuthenticatedWriteAccess indicates a variable needs time based authentication before write access.
    33  	AttributeTimeBasedAuthenticatedWriteAccess VariableAttributes = 0x00000020
    34  	// AttributeAppendWrite indicates data written to this variable is appended.
    35  	AttributeAppendWrite VariableAttributes = 0x00000040
    36  	// AttributeEnhancedAuthenticatedAccess indicate a variable uses the new authentication format.
    37  	AttributeEnhancedAuthenticatedAccess VariableAttributes = 0x00000080
    38  )
    39  
    40  // VariableDescriptor contains the name and GUID identifying a variable
    41  type VariableDescriptor struct {
    42  	Name string
    43  	GUID guid.UUID
    44  }
    45  
    46  var (
    47  	// ErrBadGUID is for any errors parsing GUIDs.
    48  	ErrBadGUID = errors.New("Bad GUID")
    49  )
    50  
    51  func guidParse(v string) ([]string, *guid.UUID, error) {
    52  	vs := strings.SplitN(v, "-", 2)
    53  	if len(vs) < 2 {
    54  		return nil, nil, fmt.Errorf("GUID must have name-GUID format: %w", ErrBadGUID)
    55  	}
    56  	g, err := guid.Parse(vs[1])
    57  	if err != nil {
    58  		return nil, nil, fmt.Errorf("%w:%v", ErrBadGUID, err)
    59  	}
    60  	return vs, &g, nil
    61  }
    62  
    63  // ReadVariable calls get() on the current efivarfs backend.
    64  func ReadVariable(e EFIVar, desc VariableDescriptor) (VariableAttributes, []byte, error) {
    65  	return e.Get(desc)
    66  }
    67  
    68  // SimpleReadVariable is like ReadVariables but takes the combined name and guid string
    69  // of the form name-guid and returns a bytes.Reader instead of a []byte.
    70  func SimpleReadVariable(e EFIVar, v string) (VariableAttributes, *bytes.Reader, error) {
    71  	vs, g, err := guidParse(v)
    72  	if err != nil {
    73  		return 0, nil, err
    74  	}
    75  	attrs, data, err := ReadVariable(e,
    76  		VariableDescriptor{
    77  			Name: vs[0],
    78  			GUID: *g,
    79  		},
    80  	)
    81  	return attrs, bytes.NewReader(data), err
    82  }
    83  
    84  // WriteVariable calls set() on the current efivarfs backend.
    85  func WriteVariable(e EFIVar, desc VariableDescriptor, attrs VariableAttributes, data []byte) error {
    86  	return e.Set(desc, attrs, data)
    87  }
    88  
    89  // SimpleWriteVariable is like WriteVariables but takes the combined name and guid string
    90  // of the form name-guid and returns a bytes.Buffer instead of a []byte.
    91  func SimpleWriteVariable(e EFIVar, v string, attrs VariableAttributes, data *bytes.Buffer) error {
    92  	vs, g, err := guidParse(v)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	return WriteVariable(e,
    97  		VariableDescriptor{
    98  			Name: vs[0],
    99  			GUID: *g,
   100  		}, attrs, data.Bytes(),
   101  	)
   102  }
   103  
   104  // RemoveVariable calls remove() on the current efivarfs backend.
   105  func RemoveVariable(e EFIVar, desc VariableDescriptor) error {
   106  	return e.Remove(desc)
   107  }
   108  
   109  // SimpleRemoveVariable is like RemoveVariable but takes the combined name and guid string
   110  // of the form name-guid.
   111  func SimpleRemoveVariable(e EFIVar, v string) error {
   112  	vs, g, err := guidParse(v)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	return RemoveVariable(e,
   117  		VariableDescriptor{
   118  			Name: vs[0],
   119  			GUID: *g,
   120  		},
   121  	)
   122  }
   123  
   124  // ListVariables calls list() on the current efivarfs backend.
   125  func ListVariables(e EFIVar) ([]VariableDescriptor, error) {
   126  	return e.List()
   127  }
   128  
   129  // SimpleListVariables is like ListVariables but returns a []string instead of a []VariableDescriptor.
   130  func SimpleListVariables(e EFIVar) ([]string, error) {
   131  	list, err := ListVariables(e)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	var out []string
   136  	for _, v := range list {
   137  		out = append(out, v.Name+"-"+v.GUID.String())
   138  	}
   139  	return out, nil
   140  }