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

     1  // Copyright 2014-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 main
     6  
     7  import (
     8  	"bytes"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"log"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  
    17  	guid "github.com/google/uuid"
    18  	"github.com/mvdan/u-root-coreutils/pkg/efivarfs"
    19  )
    20  
    21  var (
    22  	flist   = flag.Bool("list", false, "List all efivars")
    23  	fread   = flag.String("read", "", "Read specified efivar. Variable must be of form -read Name-UUID")
    24  	fdelete = flag.String("delete", "", "Delete specified efivar. Variable must be of form -delete Name-UUID")
    25  	fwrite  = flag.String("write", "", "Write to specified efivar. Variable must be of form -write Name-UUID OR Name\n"+
    26  		"In the later case a UUID is being generated\n"+
    27  		"This command is used with -content to specify the data being written to the efivar.")
    28  	fcontent = flag.String("content", "", "Path to file to write to efivar. Used with -write e.g. -write Foo -content bar.json")
    29  )
    30  
    31  func main() {
    32  	flag.Parse()
    33  
    34  	if err := runpath(os.Stdout, efivarfs.DefaultVarFS, *flist, *fread, *fdelete, *fwrite, *fcontent); err != nil {
    35  		log.Fatalf("Operation failed: %v", err)
    36  	}
    37  }
    38  
    39  func runpath(out io.Writer, p string, list bool, read, delete, write, content string) error {
    40  	e, err := efivarfs.NewPath(p)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	return run(out, e, list, read, delete, write, content)
    46  }
    47  
    48  func run(out io.Writer, e efivarfs.EFIVar, list bool, read, delete, write, content string) error {
    49  	if list {
    50  		l, err := efivarfs.SimpleListVariables(e)
    51  		if err != nil {
    52  			return fmt.Errorf("list failed: %w", err)
    53  		}
    54  		for _, s := range l {
    55  			fmt.Fprintln(out, s)
    56  		}
    57  	}
    58  
    59  	if read != "" {
    60  		attr, data, err := efivarfs.SimpleReadVariable(e, read)
    61  		if err != nil {
    62  			return fmt.Errorf("read failed: %w", err)
    63  		}
    64  		b, err := io.ReadAll(data)
    65  		if err != nil {
    66  			return fmt.Errorf("reading buffer failed: %w", err)
    67  		}
    68  		fmt.Fprintf(out, "Name: %s, Attributes: %d, Data: %s", read, attr, b)
    69  	}
    70  
    71  	if delete != "" {
    72  		if err := efivarfs.SimpleRemoveVariable(e, delete); err != nil {
    73  			return fmt.Errorf("delete failed: %w", err)
    74  		}
    75  	}
    76  
    77  	if write != "" {
    78  		if strings.ContainsAny(write, "-") {
    79  			v := strings.SplitN(write, "-", 2)
    80  			if _, err := guid.Parse(v[1]); err != nil {
    81  				return fmt.Errorf("%q malformed: Must be either Name-GUID or just Name: %w", v[1], os.ErrInvalid)
    82  			}
    83  		}
    84  		path, err := filepath.Abs(content)
    85  		if err != nil {
    86  			return fmt.Errorf("could not resolve path: %w", err)
    87  		}
    88  		b, err := os.ReadFile(path)
    89  		if err != nil {
    90  			return fmt.Errorf("failed to read file: %w", err)
    91  		}
    92  		if !strings.ContainsAny(write, "-") {
    93  			write = write + "-" + guid.New().String()
    94  		}
    95  		if err = efivarfs.SimpleWriteVariable(e, write, 7, bytes.NewBuffer(b)); err != nil {
    96  			return fmt.Errorf("write failed: %w", err)
    97  		}
    98  	}
    99  	return nil
   100  }