forked from kata-containers/kata-containers
-
Notifications
You must be signed in to change notification settings - Fork 4
/
ovmf.go
101 lines (89 loc) · 2.62 KB
/
ovmf.go
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
// Copyright contributors to AMD SEV/-ES in Go
//
// SPDX-License-Identifier: Apache-2.0
package sev
import (
"bytes"
"encoding/binary"
"errors"
"os"
)
// GUID 96b582de-1fb2-45f7-baea-a366c55a082d
var ovmfTableFooterGuid = guidLE{0xde, 0x82, 0xb5, 0x96, 0xb2, 0x1f, 0xf7, 0x45, 0xba, 0xea, 0xa3, 0x66, 0xc5, 0x5a, 0x08, 0x2d}
// GUID 00f771de-1a7e-4fcb-890e-68c77e2fb44e
var sevEsResetBlockGuid = guidLE{0xde, 0x71, 0xf7, 0x00, 0x7e, 0x1a, 0xcb, 0x4f, 0x89, 0x0e, 0x68, 0xc7, 0x7e, 0x2f, 0xb4, 0x4e}
type ovmfFooterTableEntry struct {
Size uint16
Guid guidLE
}
type ovmf struct {
table map[guidLE][]byte
}
func NewOvmf(filename string) (ovmf, error) {
buf, err := os.ReadFile(filename)
if err != nil {
return ovmf{}, err
}
table, err := parseFooterTable(buf)
if err != nil {
return ovmf{}, err
}
return ovmf{table}, nil
}
// Parse the OVMF footer table and return a map from GUID to entry value
func parseFooterTable(data []byte) (map[guidLE][]byte, error) {
table := make(map[guidLE][]byte)
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, ovmfFooterTableEntry{})
if err != nil {
return table, err
}
entryHeaderSize := buf.Len()
// The OVMF table ends 32 bytes before the end of the firmware binary
startOfFooterTable := len(data) - 32 - entryHeaderSize
footerBytes := bytes.NewReader(data[startOfFooterTable:])
var footer ovmfFooterTableEntry
err = binary.Read(footerBytes, binary.LittleEndian, &footer)
if err != nil {
return table, err
}
if footer.Guid != ovmfTableFooterGuid {
// No OVMF footer table
return table, nil
}
tableSize := int(footer.Size) - entryHeaderSize
if tableSize < 0 {
return table, nil
}
tableBytes := data[(startOfFooterTable - tableSize):startOfFooterTable]
for len(tableBytes) >= entryHeaderSize {
tsize := len(tableBytes)
entryBytes := bytes.NewReader(tableBytes[tsize-entryHeaderSize:])
var entry ovmfFooterTableEntry
err := binary.Read(entryBytes, binary.LittleEndian, &entry)
if err != nil {
return table, err
}
if int(entry.Size) < entryHeaderSize {
return table, errors.New("Invalid entry size")
}
entryData := tableBytes[tsize-int(entry.Size) : tsize-entryHeaderSize]
table[entry.Guid] = entryData
tableBytes = tableBytes[:tsize-int(entry.Size)]
}
return table, nil
}
func (o *ovmf) tableItem(guid guidLE) ([]byte, error) {
value, ok := o.table[guid]
if !ok {
return []byte{}, errors.New("OVMF footer table entry not found")
}
return value, nil
}
func (o *ovmf) sevEsResetEip() (uint32, error) {
value, err := o.tableItem(sevEsResetBlockGuid)
if err != nil {
return 0, err
}
return binary.LittleEndian.Uint32(value), nil
}