// 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.

// This package was written with the aim of easing efivarfs integration.
//
// https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html
package efivarfs

import (
	"bytes"
	"fmt"
	"os"
	"path/filepath"

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

const (
	Path       = "/sys/firmware/efi/efivars"
	GlobalGuid = "8be4df61-93ca-11d2-aa0d-00e098032b8c"
)

// 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)

// ExtractString returns EFI variable data based on raw variable file contents.
// It returns string-represented data, or an error.
func ExtractString(contents []byte) (string, error) {
	// Fail if total length is shorter than attribute length.
	if len(contents) < 4 {
		return "", fmt.Errorf("contents too short.")
	}
	// Skip attributes, see @linux//Documentation/filesystems:efivarfs.rst for format
	efiVarData := contents[4:]
	espUUIDNullTerminated, err := Encoding.NewDecoder().Bytes(efiVarData)
	if err != nil {
		// Pass the decoding error unwrapped.
		return "", err
	}
	// Remove the null suffix.
	return string(bytes.TrimSuffix(espUUIDNullTerminated, []byte{0})), nil
}

// ReadLoaderDevicePartUUID reads the ESP UUID from an EFI variable. It
// depends on efivarfs being already mounted.
func ReadLoaderDevicePartUUID() (uuid.UUID, error) {
	// Read the EFI variable file containing the ESP UUID.
	espUuidPath := filepath.Join(Path, "LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f")
	efiVar, err := os.ReadFile(espUuidPath)
	if err != nil {
		return uuid.Nil, fmt.Errorf("couldn't read the LoaderDevicePartUUID file at %q: %w", espUuidPath, err)
	}
	contents, err := ExtractString(efiVar)
	if err != nil {
		return uuid.Nil, fmt.Errorf("couldn't decode an EFI variable: %w", err)
	}
	out, err := uuid.Parse(contents)
	if err != nil {
		return uuid.Nil, fmt.Errorf("value in LoaderDevicePartUUID could not be parsed as UUID: %w", err)
	}
	return out, nil
}

// CreateBootEntry creates an EFI boot entry variable and returns its
// non-negative index on success. It may return an io error.
func CreateBootEntry(be *BootEntry) (int, error) {
	// Find the index by looking up the first empty slot.
	var ep string
	var n int
	for ; ; n++ {
		en := fmt.Sprintf("Boot%04x-%s", n, GlobalGuid)
		ep = filepath.Join(Path, en)
		_, err := os.Stat(ep)
		if os.IsNotExist(err) {
			break
		}
		if err != nil {
			return -1, err
		}
	}

	// Create the boot variable.
	bem, err := be.Marshal()
	if err != nil {
		return -1, fmt.Errorf("while marshaling the EFI boot entry: %w", err)
	}
	if err := os.WriteFile(ep, bem, 0644); err != nil {
		return -1, fmt.Errorf("while creating a boot entry variable: %w", err)
	}
	return n, nil
}

// SetBootOrder replaces contents of the boot order variable with the order
// specified in ord. It may return an io error.
func SetBootOrder(ord *BootOrder) error {
	op := filepath.Join(Path, fmt.Sprintf("BootOrder-%s", GlobalGuid))
	if err := os.WriteFile(op, ord.Marshal(), 0644); err != nil {
		return fmt.Errorf("while creating a boot order variable: %w", err)
	}
	return nil
}
