github.com/linuxboot/fiano@v1.2.0/pkg/intel/metadata/cbnt/cbntbootpolicy/manifest_manifestcodegen.go (about) 1 // Copyright 2017-2021 the LinuxBoot Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build !manifestcodegen 6 // +build !manifestcodegen 7 8 // Code generated by "menifestcodegen". DO NOT EDIT. 9 // To reproduce: go run github.com/linuxboot/fiano/pkg/intel/metadata/common/manifestcodegen/cmd/manifestcodegen github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntbootpolicy 10 11 package cbntbootpolicy 12 13 import ( 14 "encoding/binary" 15 "fmt" 16 "io" 17 "strings" 18 19 "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt" 20 "github.com/linuxboot/fiano/pkg/intel/metadata/common/pretty" 21 ) 22 23 var ( 24 // Just to avoid errors in "import" above in case if it wasn't used below 25 _ = binary.LittleEndian 26 _ = (fmt.Stringer)(nil) 27 _ = (io.Reader)(nil) 28 _ = pretty.Header 29 _ = strings.Join 30 _ = cbnt.StructInfo{} 31 ) 32 33 // NewManifest returns a new instance of Manifest with 34 // all default values set. 35 func NewManifest() *Manifest { 36 s := &Manifest{} 37 // Recursively initializing a child structure: 38 s.BPMH = *NewBPMH() 39 // Recursively initializing a child structure: 40 s.PMSE = *NewSignature() 41 s.Rehash() 42 return s 43 } 44 45 // Validate (recursively) checks the structure if there are any unexpected 46 // values. It returns an error if so. 47 func (s *Manifest) Validate() error { 48 // Recursively validating a child structure: 49 if err := s.BPMH.Validate(); err != nil { 50 return fmt.Errorf("error on field 'BPMH': %w", err) 51 } 52 // See tag "rehashValue" 53 { 54 expectedValue := BPMH(s.rehashedBPMH()) 55 if s.BPMH != expectedValue { 56 return fmt.Errorf("field 'BPMH' expects write-value '%v', but has %v", expectedValue, s.BPMH) 57 } 58 } 59 // Recursively validating a child structure: 60 if err := s.PMSE.Validate(); err != nil { 61 return fmt.Errorf("error on field 'PMSE': %w", err) 62 } 63 64 return nil 65 } 66 67 // fieldIndexByStructID returns the position index within 68 // structure Manifest of the field by its StructureID 69 // (see document #575623, an example of StructureID value is "__KEYM__"). 70 func (_ Manifest) fieldIndexByStructID(structID string) int { 71 switch structID { 72 case StructureIDBPMH: 73 return 0 74 case StructureIDSE: 75 return 1 76 case StructureIDTXT: 77 return 2 78 case StructureIDReserved: 79 return 3 80 case StructureIDPCD: 81 return 4 82 case StructureIDPM: 83 return 5 84 case StructureIDSignature: 85 return 6 86 } 87 88 return -1 89 } 90 91 // fieldNameByIndex returns the name of the field by its position number 92 // within structure Manifest. 93 func (_ Manifest) fieldNameByIndex(fieldIndex int) string { 94 switch fieldIndex { 95 case 0: 96 return "BPMH" 97 case 1: 98 return "SE" 99 case 2: 100 return "TXTE" 101 case 3: 102 return "Res" 103 case 4: 104 return "PCDE" 105 case 5: 106 return "PME" 107 case 6: 108 return "PMSE" 109 } 110 111 return fmt.Sprintf("invalidFieldIndex_%d", fieldIndex) 112 } 113 114 // ReadFrom reads the Manifest from 'r' in format defined in the document #575623. 115 func (s *Manifest) ReadFrom(r io.Reader) (returnN int64, returnErr error) { 116 var missingFieldsByIndices = [7]bool{ 117 0: true, 118 6: true, 119 } 120 defer func() { 121 if returnErr != nil { 122 return 123 } 124 for fieldIndex, v := range missingFieldsByIndices { 125 if v { 126 returnErr = fmt.Errorf("field '%s' is missing", s.fieldNameByIndex(fieldIndex)) 127 break 128 } 129 } 130 }() 131 var totalN int64 132 previousFieldIndex := int(-1) 133 for { 134 var structInfo cbnt.StructInfo 135 err := binary.Read(r, binary.LittleEndian, &structInfo) 136 if err == io.EOF || err == io.ErrUnexpectedEOF { 137 return totalN, nil 138 } 139 if err != nil { 140 return totalN, fmt.Errorf("unable to read structure info at %d: %w", totalN, err) 141 } 142 totalN += int64(binary.Size(structInfo)) 143 144 structID := structInfo.ID.String() 145 fieldIndex := s.fieldIndexByStructID(structID) 146 if fieldIndex < 0 { 147 // TODO: report error "unknown structure ID: '"+structID+"'" 148 continue 149 } 150 if cbnt.StrictOrderCheck && fieldIndex < previousFieldIndex { 151 return totalN, fmt.Errorf("invalid order of fields (%d < %d): structure '%s' is out of order", fieldIndex, previousFieldIndex, structID) 152 } 153 missingFieldsByIndices[fieldIndex] = false 154 155 var n int64 156 switch structID { 157 case StructureIDBPMH: 158 if fieldIndex == previousFieldIndex { 159 return totalN, fmt.Errorf("field 'BPMH' is not a slice, but multiple elements found") 160 } 161 s.BPMH.SetStructInfo(structInfo) 162 n, err = s.BPMH.ReadDataFrom(r) 163 if err != nil { 164 return totalN, fmt.Errorf("unable to read field BPMH at %d: %w", totalN, err) 165 } 166 case StructureIDSE: 167 var el SE 168 el.SetStructInfo(structInfo) 169 n, err = el.ReadDataFrom(r) 170 s.SE = append(s.SE, el) 171 if err != nil { 172 return totalN, fmt.Errorf("unable to read field SE at %d: %w", totalN, err) 173 } 174 case StructureIDTXT: 175 if fieldIndex == previousFieldIndex { 176 return totalN, fmt.Errorf("field 'TXTE' is not a slice, but multiple elements found") 177 } 178 s.TXTE = &TXT{} 179 s.TXTE.SetStructInfo(structInfo) 180 n, err = s.TXTE.ReadDataFrom(r) 181 if err != nil { 182 return totalN, fmt.Errorf("unable to read field TXTE at %d: %w", totalN, err) 183 } 184 case StructureIDReserved: 185 if fieldIndex == previousFieldIndex { 186 return totalN, fmt.Errorf("field 'Res' is not a slice, but multiple elements found") 187 } 188 s.Res = &Reserved{} 189 s.Res.SetStructInfo(structInfo) 190 n, err = s.Res.ReadDataFrom(r) 191 if err != nil { 192 return totalN, fmt.Errorf("unable to read field Res at %d: %w", totalN, err) 193 } 194 case StructureIDPCD: 195 if fieldIndex == previousFieldIndex { 196 return totalN, fmt.Errorf("field 'PCDE' is not a slice, but multiple elements found") 197 } 198 s.PCDE = &PCD{} 199 s.PCDE.SetStructInfo(structInfo) 200 n, err = s.PCDE.ReadDataFrom(r) 201 if err != nil { 202 return totalN, fmt.Errorf("unable to read field PCDE at %d: %w", totalN, err) 203 } 204 case StructureIDPM: 205 if fieldIndex == previousFieldIndex { 206 return totalN, fmt.Errorf("field 'PME' is not a slice, but multiple elements found") 207 } 208 s.PME = &PM{} 209 s.PME.SetStructInfo(structInfo) 210 n, err = s.PME.ReadDataFrom(r) 211 if err != nil { 212 return totalN, fmt.Errorf("unable to read field PME at %d: %w", totalN, err) 213 } 214 case StructureIDSignature: 215 if fieldIndex == previousFieldIndex { 216 return totalN, fmt.Errorf("field 'PMSE' is not a slice, but multiple elements found") 217 } 218 s.PMSE.SetStructInfo(structInfo) 219 n, err = s.PMSE.ReadDataFrom(r) 220 if err != nil { 221 return totalN, fmt.Errorf("unable to read field PMSE at %d: %w", totalN, err) 222 } 223 default: 224 return totalN, fmt.Errorf("there is no field with structure ID '%s' in Manifest", structInfo.ID) 225 } 226 totalN += n 227 previousFieldIndex = fieldIndex 228 } 229 } 230 231 // RehashRecursive calls Rehash (see below) recursively. 232 func (s *Manifest) RehashRecursive() { 233 s.BPMH.Rehash() 234 if s.TXTE != nil { 235 s.TXTE.Rehash() 236 } 237 if s.Res != nil { 238 s.Res.Rehash() 239 } 240 if s.PCDE != nil { 241 s.PCDE.Rehash() 242 } 243 if s.PME != nil { 244 s.PME.Rehash() 245 } 246 s.PMSE.Rehash() 247 s.Rehash() 248 } 249 250 // Rehash sets values which are calculated automatically depending on the rest 251 // data. It is usually about the total size field of an element. 252 func (s *Manifest) Rehash() { 253 s.BPMH = BPMH(s.rehashedBPMH()) 254 } 255 256 // WriteTo writes the Manifest into 'w' in format defined in 257 // the document #575623. 258 func (s *Manifest) WriteTo(w io.Writer) (int64, error) { 259 totalN := int64(0) 260 s.Rehash() 261 262 // BPMH (ManifestFieldType: element) 263 { 264 n, err := s.BPMH.WriteTo(w) 265 if err != nil { 266 return totalN, fmt.Errorf("unable to write field 'BPMH': %w", err) 267 } 268 totalN += int64(n) 269 } 270 271 // SE (ManifestFieldType: elementList) 272 { 273 for idx := range s.SE { 274 n, err := s.SE[idx].WriteTo(w) 275 if err != nil { 276 return totalN, fmt.Errorf("unable to write field 'SE[%d]': %w", idx, err) 277 } 278 totalN += int64(n) 279 } 280 } 281 282 // TXTE (ManifestFieldType: element) 283 if s.TXTE != nil { 284 n, err := s.TXTE.WriteTo(w) 285 if err != nil { 286 return totalN, fmt.Errorf("unable to write field 'TXTE': %w", err) 287 } 288 totalN += int64(n) 289 } 290 291 // Res (ManifestFieldType: element) 292 if s.Res != nil { 293 n, err := s.Res.WriteTo(w) 294 if err != nil { 295 return totalN, fmt.Errorf("unable to write field 'Res': %w", err) 296 } 297 totalN += int64(n) 298 } 299 300 // PCDE (ManifestFieldType: element) 301 if s.PCDE != nil { 302 n, err := s.PCDE.WriteTo(w) 303 if err != nil { 304 return totalN, fmt.Errorf("unable to write field 'PCDE': %w", err) 305 } 306 totalN += int64(n) 307 } 308 309 // PME (ManifestFieldType: element) 310 if s.PME != nil { 311 n, err := s.PME.WriteTo(w) 312 if err != nil { 313 return totalN, fmt.Errorf("unable to write field 'PME': %w", err) 314 } 315 totalN += int64(n) 316 } 317 318 // PMSE (ManifestFieldType: element) 319 { 320 n, err := s.PMSE.WriteTo(w) 321 if err != nil { 322 return totalN, fmt.Errorf("unable to write field 'PMSE': %w", err) 323 } 324 totalN += int64(n) 325 } 326 327 return totalN, nil 328 } 329 330 // BPMHSize returns the size in bytes of the value of field BPMH 331 func (s *Manifest) BPMHTotalSize() uint64 { 332 return s.BPMH.TotalSize() 333 } 334 335 // SESize returns the size in bytes of the value of field SE 336 func (s *Manifest) SETotalSize() uint64 { 337 var size uint64 338 for idx := range s.SE { 339 size += s.SE[idx].TotalSize() 340 } 341 return size 342 } 343 344 // TXTESize returns the size in bytes of the value of field TXTE 345 func (s *Manifest) TXTETotalSize() uint64 { 346 return s.TXTE.TotalSize() 347 } 348 349 // ResSize returns the size in bytes of the value of field Res 350 func (s *Manifest) ResTotalSize() uint64 { 351 return s.Res.TotalSize() 352 } 353 354 // PCDESize returns the size in bytes of the value of field PCDE 355 func (s *Manifest) PCDETotalSize() uint64 { 356 return s.PCDE.TotalSize() 357 } 358 359 // PMESize returns the size in bytes of the value of field PME 360 func (s *Manifest) PMETotalSize() uint64 { 361 return s.PME.TotalSize() 362 } 363 364 // PMSESize returns the size in bytes of the value of field PMSE 365 func (s *Manifest) PMSETotalSize() uint64 { 366 return s.PMSE.TotalSize() 367 } 368 369 // BPMHOffset returns the offset in bytes of field BPMH 370 func (s *Manifest) BPMHOffset() uint64 { 371 return 0 372 } 373 374 // SEOffset returns the offset in bytes of field SE 375 func (s *Manifest) SEOffset() uint64 { 376 return s.BPMHOffset() + s.BPMHTotalSize() 377 } 378 379 // TXTEOffset returns the offset in bytes of field TXTE 380 func (s *Manifest) TXTEOffset() uint64 { 381 return s.SEOffset() + s.SETotalSize() 382 } 383 384 // ResOffset returns the offset in bytes of field Res 385 func (s *Manifest) ResOffset() uint64 { 386 return s.TXTEOffset() + s.TXTETotalSize() 387 } 388 389 // PCDEOffset returns the offset in bytes of field PCDE 390 func (s *Manifest) PCDEOffset() uint64 { 391 return s.ResOffset() + s.ResTotalSize() 392 } 393 394 // PMEOffset returns the offset in bytes of field PME 395 func (s *Manifest) PMEOffset() uint64 { 396 return s.PCDEOffset() + s.PCDETotalSize() 397 } 398 399 // PMSEOffset returns the offset in bytes of field PMSE 400 func (s *Manifest) PMSEOffset() uint64 { 401 return s.PMEOffset() + s.PMETotalSize() 402 } 403 404 // Size returns the total size of the Manifest. 405 func (s *Manifest) TotalSize() uint64 { 406 if s == nil { 407 return 0 408 } 409 410 var size uint64 411 size += s.BPMHTotalSize() 412 size += s.SETotalSize() 413 size += s.TXTETotalSize() 414 size += s.ResTotalSize() 415 size += s.PCDETotalSize() 416 size += s.PMETotalSize() 417 size += s.PMSETotalSize() 418 return size 419 } 420 421 // PrettyString returns the content of the structure in an easy-to-read format. 422 func (s *Manifest) PrettyString(depth uint, withHeader bool, opts ...pretty.Option) string { 423 var lines []string 424 if withHeader { 425 lines = append(lines, pretty.Header(depth, "Boot Policy Manifest", s)) 426 } 427 if s == nil { 428 return strings.Join(lines, "\n") 429 } 430 // ManifestFieldType is element 431 lines = append(lines, pretty.SubValue(depth+1, "BPMH: Header", "", &s.BPMH, opts...)...) 432 // ManifestFieldType is elementList 433 lines = append(lines, pretty.Header(depth+1, fmt.Sprintf("SE: Array of \"Boot Policy Manifest\" of length %d", len(s.SE)), s.SE)) 434 for i := 0; i < len(s.SE); i++ { 435 lines = append(lines, fmt.Sprintf("%sitem #%d: ", strings.Repeat(" ", int(depth+2)), i)+strings.TrimSpace(s.SE[i].PrettyString(depth+2, true))) 436 } 437 if depth < 1 { 438 lines = append(lines, "") 439 } 440 // ManifestFieldType is element 441 lines = append(lines, pretty.SubValue(depth+1, "TXTE", "", s.TXTE, opts...)...) 442 // ManifestFieldType is element 443 lines = append(lines, pretty.SubValue(depth+1, "Res", "", s.Res, opts...)...) 444 // ManifestFieldType is element 445 lines = append(lines, pretty.SubValue(depth+1, "PCDE: Platform Config Data", "", s.PCDE, opts...)...) 446 // ManifestFieldType is element 447 lines = append(lines, pretty.SubValue(depth+1, "PME: Platform Manufacturer", "", s.PME, opts...)...) 448 // ManifestFieldType is element 449 lines = append(lines, pretty.SubValue(depth+1, "PMSE: Signature", "", &s.PMSE, opts...)...) 450 if depth < 2 { 451 lines = append(lines, "") 452 } 453 return strings.Join(lines, "\n") 454 }