-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathcmd.go
More file actions
268 lines (229 loc) · 7.1 KB
/
Copy pathcmd.go
File metadata and controls
268 lines (229 loc) · 7.1 KB
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
package main
import (
"encoding/json"
"fmt"
"os"
"regexp"
"slices"
"sort"
"strconv"
"strings"
"github.com/9elements/converged-security-suite/v2/pkg/intel"
"github.com/9elements/converged-security-suite/v2/pkg/test"
"github.com/9elements/converged-security-suite/v2/pkg/tools"
log "github.com/sirupsen/logrus"
"github.com/9elements/go-linux-lowlevel-hw/pkg/hwapi"
a "github.com/logrusorgru/aurora"
)
type context struct {
interactive bool
logpath string
}
type listCmd struct{}
type markdownCmd struct{}
type versionCmd struct{}
type execTestsCmd struct {
Set string `required:"" default:"all" help:"Select subset of tests. Options: all, static, runtime, or choose tests by number e.g. --set=1,3,4"`
Strict bool `required:"" default:"false" short:"s" help:"Enable strict mode. This enables more tests and checks."`
Interactive bool `optional:"" short:"i" help:"Interactive mode. Errors will stop the testing."`
Config string `optional:"" short:"c" help:"Path/Filename to config file."`
Firmware string `optional:"" short:"f" help:"Path/Filename to firmware to test with."`
}
var cli struct {
ManifestStrictOrderCheck bool `help:"Enable checking of manifest elements order"`
ExecTests execTestsCmd `cmd:"" help:"Executes tests given be TestNo or TestSet"`
List listCmd `cmd:"" help:"Lists all tests"`
Markdown markdownCmd `cmd:"" help:"Output test implementation state as Markdown"`
Version versionCmd `cmd:"" help:"Prints the version of the program"`
}
func (e *execTestsCmd) Run(ctx *context) error {
ret := false
bgver := intel.RuntimeBGVersion()
log.Infof("Runtime BG/CBnT version: %s", bgver)
if bgver == intel.Unknown {
log.Warn("Unable to map CPU model to Boot Guard/CBnT generation")
}
data, err := os.ReadFile(e.Firmware)
if err != nil {
return fmt.Errorf("can't read firmware file")
}
preset := test.PreSet{
Firmware: data,
HostBridgeDeviceID: 0x00,
Strict: e.Strict,
}
switch e.Set {
case "all":
log.Info("For more information about the documents and chapters, run: bg-suite markdown")
ret = run("All", getTests(), &preset, e.Interactive)
case "static":
ret = run("Static", getStaticTest(), &preset, e.Interactive)
case "runtime":
ret = run("Runtime", getRuntimeTest(), &preset, e.Interactive)
default:
var tests []*test.Test
// Regex to detect if the set is a list of numbers
numbers := regexp.MustCompile(`^(\d+)(,\d+)*$`)
num := numbers.FindAllString(e.Set, -1)
if num == nil {
return fmt.Errorf("no valid test set given")
}
num = strings.Split(e.Set, ",")
// Add Tests to the list
for i := range num {
testno, err := strconv.ParseUint(num[i], 10, 64)
if err != nil {
return fmt.Errorf("no valid test set given")
}
tests = append(tests, getTests()[testno])
}
ret = run("Custom Set", tests, &preset, e.Interactive)
}
if !ret {
return fmt.Errorf("tests ran with errors")
}
return nil
}
func (l *listCmd) Run(ctx *context) error {
tests := getTests()
for i := range tests {
if tests[i].Description != "" {
log.Infof("Test No: %v, %v - %v", i, tests[i].Name, tests[i].Description)
continue
}
log.Infof("Test No: %v, %v", i, tests[i].Name)
}
return nil
}
func (m *markdownCmd) Run(ctx *context) error {
var teststate string
tests := getTests()
log.Info("Id | Test | Description | Implemented | Document | Chapter")
log.Info("------------|------------|------------|------------|------------|------------")
for i := range tests {
if tests[i].Status == test.Implemented {
teststate = ":white_check_mark:"
} else if tests[i].Status == test.NotImplemented {
teststate = ":x:"
} else {
teststate = ":clock1:"
}
docID := tests[i].SpecificationDocumentID
if docID != "" {
docID = "Document " + docID
}
log.Infof("%02d | %-48s | %-52s | %-22s | %-28s | %-56s", i, tests[i].Name, tests[i].Description, teststate, docID, tests[i].SpecificationChapter)
}
return nil
}
func (v *versionCmd) Run(ctx *context) error {
tools.ShowVersion(programDesc, gittag, gitcommit)
return nil
}
func getTests() []*test.Test {
var tests []*test.Test
bgver := intel.RuntimeBGVersion()
for i := range test.TestsBootGuard {
if strings.HasPrefix(test.TestsBootGuard[i].Name, "[RUNTIME]") {
if slices.Contains(test.TestsBootGuard[i].SupportedVersion, bgver) {
tests = append(tests, test.TestsBootGuard[i])
}
continue
}
tests = append(tests, test.TestsBootGuard[i])
}
return tests
}
func getStaticTest() []*test.Test {
var tests []*test.Test
for i := range test.TestsBootGuard {
if !strings.HasPrefix(test.TestsBootGuard[i].Name, "[RUNTIME]") {
tests = append(tests, test.TestsBootGuard[i])
}
}
return tests
}
func getRuntimeTest() []*test.Test {
var tests []*test.Test
bgver := intel.RuntimeBGVersion()
for i := range test.TestsBootGuard {
if strings.HasPrefix(test.TestsBootGuard[i].Name, "[RUNTIME]") {
if slices.Contains(test.TestsBootGuard[i].SupportedVersion, bgver) {
tests = append(tests, test.TestsBootGuard[i])
}
}
}
return tests
}
func run(testGroup string, tests []*test.Test, preset *test.PreSet, interactive bool) bool {
result := false
hwAPI := hwapi.GetAPI()
log.Infof("%s tests", a.Bold(a.Gray(20-1, testGroup).BgGray(4-1)))
log.Info("--------------------------------------------------")
for idx := range tests {
if len(testnos) > 0 {
// SearchInt returns an index where to "insert" idx
i := sort.SearchInts(testnos, idx)
if i >= len(testnos) {
continue
}
// still here? i must be within testnos.
if testnos[i] != idx {
continue
}
}
if !tests[idx].Run(hwAPI, preset) && tests[idx].Required && interactive {
result = true
break
}
}
if !interactive {
var t []temptest
bgVersion := string(intel.RuntimeBGVersion())
for index := range tests {
if tests[index].Status != test.NotImplemented {
ttemp := temptest{
Testnumber: index,
Testname: tests[index].Name,
Description: tests[index].Description,
BgVersion: bgVersion,
Result: tests[index].Result.String(),
Error: tests[index].ErrorText,
Status: tests[index].Status.String(),
}
t = append(t, ttemp)
}
}
data, _ := json.MarshalIndent(t, "", "")
err := os.WriteFile(logfile, data, 0o664)
if err != nil {
log.Errorf("Error writing log file: %v", err)
}
// If not interactive, we just print the results and return
result = true
}
for index := range tests {
var s string
if tests[index].Status == test.NotImplemented {
continue
}
if tests[index].Result == test.ResultNotRun {
continue
}
s += fmt.Sprintf("%02d - ", index)
s += fmt.Sprintf("%-40s: ", a.Bold(tests[index].Name))
if tests[index].Result == test.ResultPass {
s += fmt.Sprintf("%-20s", a.Bold(a.Green(tests[index].Result)))
} else {
s += fmt.Sprintf("%-20s", a.Bold(a.Red(tests[index].Result)))
result = false
}
if tests[index].ErrorText != "" {
s += fmt.Sprintf(" (%s)", tests[index].ErrorText)
} else if len(tests[index].ErrorText) == 0 && tests[index].Result == test.ResultFail {
s += fmt.Sprintf(" (No error text given)")
}
log.Infof("%s", s)
}
return result
}