-
Notifications
You must be signed in to change notification settings - Fork 2
/
fet.go
165 lines (136 loc) · 4.13 KB
/
fet.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
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package amdfw
import (
"bytes"
"encoding/binary"
"fmt"
)
const FETSignature = uint32(0x55AA55AA)
const FETDefaultOffset = uint32(0x20000)
type FirmwareEntryTable struct {
Location uint32
Signature uint32
ImcRomBase *uint32
GecRomBase *uint32
XHCRomBase *uint32
PSPDirBase *uint32
NewPSPDirBase *uint32
BHDDirBase *uint32
NewBHDDirBase *uint32
}
type binaryFet struct {
Signature uint32
ImcRomBase uint32
GecRomBase uint32
XHCRomBase uint32
PSPDirBase uint32
NewPSPDirBase uint32
BHDDirBase uint32
NewBHDDirBase uint32
}
type binaryShortFet struct {
Signature uint32
ImcRomBase uint32
GecRomBase uint32
XHCRomBase uint32
}
// Looks for the FET Signature at the often used offsets.
func FindFirmwareEntryTable(firmware []byte) (uint32, error) {
for _, addr := range []uint32{FETDefaultOffset, 0, 0x820000, 0xC20000, 0xE20000, 0xF20000} {
err := checkValidFirmwareEntryTable(firmware, uint32(addr))
if err == nil {
return addr, nil
}
}
return 0, fmt.Errorf("No FirmwareTable found")
}
// Looks for the FET Signature everywhere (slow)
func FindFirmwareEntryTableByScan(firmware []byte) (uint32, error) {
end := len(firmware)
for addr := 0; addr <= end-4; addr++ {
err := checkValidFirmwareEntryTable(firmware, uint32(addr))
if err == nil {
return uint32(addr), nil
}
}
return 0, fmt.Errorf("No FirmwareTable found")
}
func checkValidFirmwareEntryTable(firmware []byte, address uint32) error {
if int(address) > len(firmware)+binary.Size(FirmwareEntryTable{}) {
return fmt.Errorf("Not AMD Table Header: Address out of bounds")
}
potentialMagic := binary.LittleEndian.Uint32(firmware[address:])
if potentialMagic == FETSignature {
return nil
}
return fmt.Errorf("Not AMD Table Header")
}
// Parses the FET at the given Address
// Default address is 0x20000 but some PSP versions appear to be able to search on different offsets
func ParseFirmwareEntryTable(firmware []byte, address uint32) (*FirmwareEntryTable, error) {
if err := checkValidFirmwareEntryTable(firmware, address); err != nil {
return nil, fmt.Errorf("Could not find FirmwareEntryTable Signature: %v", err)
}
tempTable := binaryFet{}
if err := binary.Read(bytes.NewReader(firmware[address:]), binary.LittleEndian, &tempTable); err != nil {
return nil, fmt.Errorf("Could not read FirmwareEntryTable: %v", err)
}
fet := FirmwareEntryTable{
Signature: tempTable.Signature,
ImcRomBase: &tempTable.ImcRomBase,
GecRomBase: &tempTable.GecRomBase,
XHCRomBase: &tempTable.XHCRomBase,
PSPDirBase: &tempTable.PSPDirBase,
NewPSPDirBase: &tempTable.NewPSPDirBase,
BHDDirBase: &tempTable.BHDDirBase,
NewBHDDirBase: &tempTable.NewBHDDirBase,
Location: uint32(address),
}
// Not a full AMDFirmwareEntryTable. XHCI Rom is following...
if *fet.PSPDirBase&0xFFFF == 0x55AA {
fet.PSPDirBase = nil
fet.NewPSPDirBase = nil
fet.BHDDirBase = nil
fet.NewBHDDirBase = nil
}
return &fet, nil
}
// Writes FET into existing image
func (fet *FirmwareEntryTable) Write(baseImage []byte, address uint32) error {
var tempTable interface{}
if fet.PSPDirBase == nil &&
fet.NewPSPDirBase == nil &&
fet.NewBHDDirBase == nil &&
fet.BHDDirBase == nil {
tempTable = binaryShortFet{
Signature: fet.Signature,
ImcRomBase: *fet.ImcRomBase,
GecRomBase: *fet.GecRomBase,
XHCRomBase: *fet.XHCRomBase,
}
} else {
tempTable = binaryFet{
Signature: fet.Signature,
ImcRomBase: *fet.ImcRomBase,
GecRomBase: *fet.GecRomBase,
XHCRomBase: *fet.XHCRomBase,
PSPDirBase: *fet.PSPDirBase,
NewPSPDirBase: *fet.NewPSPDirBase,
BHDDirBase: *fet.BHDDirBase,
NewBHDDirBase: *fet.NewBHDDirBase,
}
}
fetSize := binary.Size(tempTable)
if len(baseImage) < int(address)+fetSize {
return fmt.Errorf("BaseImage to small to insert FET")
}
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, tempTable)
if err != nil {
return fmt.Errorf("Writing binary failed: %v", err)
}
bytesCopied := copy(baseImage[address:], buf.Bytes())
if bytesCopied != fetSize {
return fmt.Errorf("Writing binary failed: Not all Bytes copied!")
}
return nil
}