File: device.go

package info (click to toggle)
golang-github-foxboron-go-uefi 0.0~git20250207.69fb7db-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,140 kB
  • sloc: makefile: 29; sh: 14
file content (129 lines) | stat: -rw-r--r-- 2,891 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package device

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"

	"github.com/foxboron/go-uefi/efi/attributes"
	"github.com/foxboron/go-uefi/efi/util"
)

//	Section 3.1.3 Load Options
//
// Page 71
type EFILoadOption struct {
	Attributes         attributes.Attributes
	FilePathListLength uint16
	Description        string
	FilePath           []EFIDevicePaths
	OptionalData       []byte // TODO: Implement
}

func (e *EFILoadOption) Unmarshal(b *bytes.Buffer) error {
	elo, err := ParseEFILoadOption(b)
	if err != nil {
		return err
	}
	elo.FilePath, err = ParseDevicePath(b)
	if err != nil {
		return fmt.Errorf("could parse device path: %w", err)
	}
	*e = *elo
	return nil
}

// Section 10.3 Device Path Nodes
// Page 286
type DevicePathType uint8

const (
	_ DevicePathType = iota
	Hardware
	ACPI
	MessagingDevicePath
	MediaDevicePath
	BIOSBootSpecificationDevicePath
	EndOfHardwareDevicePath DevicePathType = 127
)

// Section 10.3.1 Generic Device Path Structures
// Page 287
type DevicePathSubType uint8

// Table 45. Device Path End Structure
// Subtypes of EndofHardwareDevicePath
const (
	NewDevicePath   DevicePathSubType = 1
	NoNewDevicePath DevicePathSubType = 255
)

// Section 10.2 EFI Device Path Protocol
// Page 285
type EFIDevicePath struct {
	Type    DevicePathType
	SubType DevicePathSubType
	Length  [2]uint8
}

type EFIDevicePaths interface {
	Format() string
}

func (e EFIDevicePath) Format() string {
	return "No format"
}

func ParseDevicePath(f io.Reader) ([]EFIDevicePaths, error) {
	var ret []EFIDevicePaths
	for {
		var efidevice EFIDevicePath
		if err := binary.Read(f, binary.LittleEndian, &efidevice); err != nil {
			log.Fatalf("Failed to parse EFI Device Path: %s", err)
		}
		switch efidevice.Type {
		case Hardware:
			d := ParseHardwareDevicePath(f, &efidevice)
			ret = append(ret, d)
		case ACPI:
			d := ParseACPIDevicePath(f, &efidevice)
			ret = append(ret, d)
		case MediaDevicePath:
			d, err := ParseMediaDevicePath(f, &efidevice)
			if err != nil {
				return nil, err
			}
			ret = append(ret, d)
		case MessagingDevicePath:
			d := ParseMessagingDevicePath(f, &efidevice)
			ret = append(ret, d)
		case EndOfHardwareDevicePath:
			// log.Printf("Reached end of HardwareDevicePath: %+v\n", efidevice)
			goto end
		default:
			// log.Printf("Not implemented EFIDevicePath type: %+v\n", efidevice)
			goto end
		}
	}
end:
	return ret, nil
}

func ParseEFILoadOption(f *bytes.Buffer) (*EFILoadOption, error) {
	var bootentry EFILoadOption
	for _, b := range []interface{}{&bootentry.Attributes, &bootentry.FilePathListLength} {
		if err := binary.Read(f, binary.LittleEndian, b); err != nil {
			return nil, fmt.Errorf("can't parse EFI Load Option: %w", err)
		}
	}

	b := util.ReadNullString(f)
	s, err := util.ParseUtf16Var(bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}
	bootentry.Description = s
	return &bootentry, nil
}