// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package efivarfs provides functions to read and manipulate UEFI runtime
// variables. It uses Linux's efivarfs [1] to access the variables and all
// functions generally require that this is mounted at
// "/sys/firmware/efi/efivars".
//
// [1] https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html
package efivarfs

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io/fs"
	"os"
	"strings"

	"github.com/google/uuid"
	"golang.org/x/text/encoding/unicode"
)

const (
	Path = "/sys/firmware/efi/efivars"
)

var (
	// ScopeGlobal is the scope of variables defined by the EFI specification
	// itself.
	ScopeGlobal = uuid.MustParse("8be4df61-93ca-11d2-aa0d-00e098032b8c")
	// ScopeSystemd is the scope of variables defined by Systemd/bootspec.
	ScopeSystemd = uuid.MustParse("4a67b082-0a4c-41cf-b6c7-440b29bb8c4f")
)

// Encoding defines the Unicode encoding used by UEFI, which is UCS-2 Little
// Endian. For BMP characters UTF-16 is equivalent to UCS-2. See the UEFI
// Spec 2.9, Sections 33.2.6 and 1.8.1.
var Encoding = unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)

// Attribute contains a bitset of EFI variable attributes.
type Attribute uint32

const (
	// If set the value of the variable is is persistent across resets and
	// power cycles. Variables without this set cannot be created or modified
	// after UEFI boot services are terminated.
	AttrNonVolatile Attribute = 1 << iota
	// If set allows access to this variable from UEFI boot services.
	AttrBootserviceAccess
	// If set allows access to this variable from an operating system after
	// UEFI boot services are terminated. Variables setting this must also
	// set AttrBootserviceAccess. This is automatically taken care of by Write
	// in this package.
	AttrRuntimeAccess
	// Marks a variable as being a hardware error record. See UEFI 2.10 section
	// 8.2.8 for more information about this.
	AttrHardwareErrorRecord
	// Deprecated, should not be used for new variables.
	AttrAuthenticatedWriteAccess
	// Variable requires special authentication to write. These variables
	// cannot be written with this package.
	AttrTimeBasedAuthenticatedWriteAccess
	// If set in a Write() call, tries to append the data instead of replacing
	// it completely.
	AttrAppendWrite
	// Variable requires special authentication to access and write. These
	// variables cannot be accessed with this package.
	AttrEnhancedAuthenticatedAccess
)

func varPath(scope uuid.UUID, varName string) string {
	return fmt.Sprintf("/sys/firmware/efi/efivars/%s-%s", varName, scope.String())
}

// Write writes the value of the named variable in the given scope.
func Write(scope uuid.UUID, varName string, attrs Attribute, value []byte) error {
	// Write attributes, see @linux//Documentation/filesystems:efivarfs.rst for format
	f, err := os.OpenFile(varPath(scope, varName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		e := err
		// Unwrap PathError here as we wrap our own parameter message around it
		var perr *fs.PathError
		if errors.As(err, &perr) {
			e = perr.Err
		}
		return fmt.Errorf("writing %q in scope %s: %w", varName, scope, e)
	}
	// Required by UEFI 2.10 Section 8.2.3:
	// Runtime access to a data variable implies boot service access. Attributes
	// that have EFI_VARIABLE_RUNTIME_ACCESS set must also have
	// EFI_VARIABLE_BOOTSERVICE_ACCESS set. The caller is responsible for
	// following this rule.
	if attrs&AttrRuntimeAccess != 0 {
		attrs |= AttrBootserviceAccess
	}
	// Linux wants everything in on write, so assemble an intermediate buffer
	buf := make([]byte, len(value)+4)
	binary.LittleEndian.PutUint32(buf[:4], uint32(attrs))
	copy(buf[4:], value)
	_, err = f.Write(buf)
	if err1 := f.Close(); err1 != nil && err == nil {
		err = err1
	}
	return err
}

// Read reads the value of the named variable in the given scope.
func Read(scope uuid.UUID, varName string) ([]byte, Attribute, error) {
	val, err := os.ReadFile(varPath(scope, varName))
	if err != nil {
		e := err
		// Unwrap PathError here as we wrap our own parameter message around it
		var perr *fs.PathError
		if errors.As(err, &perr) {
			e = perr.Err
		}
		return nil, Attribute(0), fmt.Errorf("reading %q in scope %s: %w", varName, scope, e)
	}
	if len(val) < 4 {
		return nil, Attribute(0), fmt.Errorf("reading %q in scope %s: malformed, less than 4 bytes long", varName, scope)
	}
	return val[4:], Attribute(binary.LittleEndian.Uint32(val[:4])), nil
}

// List lists all variable names present for a given scope sorted by their names
// in Go's "native" string sort order.
func List(scope uuid.UUID) ([]string, error) {
	vars, err := os.ReadDir(Path)
	if err != nil {
		return nil, fmt.Errorf("failed to list variable directory: %w", err)
	}
	var outVarNames []string
	suffix := fmt.Sprintf("-%v", scope)
	for _, v := range vars {
		if v.IsDir() {
			continue
		}
		if !strings.HasSuffix(v.Name(), suffix) {
			continue
		}
		outVarNames = append(outVarNames, strings.TrimSuffix(v.Name(), suffix))
	}
	return outVarNames, nil
}
