github.com/linuxboot/fiano@v1.2.0/pkg/intel/metadata/bg/bgbootpolicy/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 -package bg github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy 10 11 package bgbootpolicy 12 13 import ( 14 "encoding/binary" 15 "fmt" 16 "io" 17 "strings" 18 19 "github.com/linuxboot/fiano/pkg/intel/metadata/bg" 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 _ = bg.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 StructureIDPM: 77 return 2 78 case StructureIDSignature: 79 return 3 80 } 81 82 return -1 83 } 84 85 // fieldNameByIndex returns the name of the field by its position number 86 // within structure Manifest. 87 func (_ Manifest) fieldNameByIndex(fieldIndex int) string { 88 switch fieldIndex { 89 case 0: 90 return "BPMH" 91 case 1: 92 return "SE" 93 case 2: 94 return "PME" 95 case 3: 96 return "PMSE" 97 } 98 99 return fmt.Sprintf("invalidFieldIndex_%d", fieldIndex) 100 } 101 102 // ReadFrom reads the Manifest from 'r' in format defined in the document #575623. 103 func (s *Manifest) ReadFrom(r io.Reader) (returnN int64, returnErr error) { 104 var missingFieldsByIndices = [4]bool{ 105 0: true, 106 3: true, 107 } 108 defer func() { 109 if returnErr != nil { 110 return 111 } 112 for fieldIndex, v := range missingFieldsByIndices { 113 if v { 114 returnErr = fmt.Errorf("field '%s' is missing", s.fieldNameByIndex(fieldIndex)) 115 break 116 } 117 } 118 }() 119 var totalN int64 120 previousFieldIndex := int(-1) 121 for { 122 var structInfo bg.StructInfo 123 err := binary.Read(r, binary.LittleEndian, &structInfo) 124 if err == io.EOF || err == io.ErrUnexpectedEOF { 125 return totalN, nil 126 } 127 if err != nil { 128 return totalN, fmt.Errorf("unable to read structure info at %d: %w", totalN, err) 129 } 130 totalN += int64(binary.Size(structInfo)) 131 132 structID := structInfo.ID.String() 133 fieldIndex := s.fieldIndexByStructID(structID) 134 if fieldIndex < 0 { 135 // TODO: report error "unknown structure ID: '"+structID+"'" 136 continue 137 } 138 if bg.StrictOrderCheck && fieldIndex < previousFieldIndex { 139 return totalN, fmt.Errorf("invalid order of fields (%d < %d): structure '%s' is out of order", fieldIndex, previousFieldIndex, structID) 140 } 141 missingFieldsByIndices[fieldIndex] = false 142 143 var n int64 144 switch structID { 145 case StructureIDBPMH: 146 if fieldIndex == previousFieldIndex { 147 return totalN, fmt.Errorf("field 'BPMH' is not a slice, but multiple elements found") 148 } 149 s.BPMH.SetStructInfo(structInfo) 150 n, err = s.BPMH.ReadDataFrom(r) 151 if err != nil { 152 return totalN, fmt.Errorf("unable to read field BPMH at %d: %w", totalN, err) 153 } 154 case StructureIDSE: 155 var el SE 156 el.SetStructInfo(structInfo) 157 n, err = el.ReadDataFrom(r) 158 s.SE = append(s.SE, el) 159 if err != nil { 160 return totalN, fmt.Errorf("unable to read field SE at %d: %w", totalN, err) 161 } 162 case StructureIDPM: 163 if fieldIndex == previousFieldIndex { 164 return totalN, fmt.Errorf("field 'PME' is not a slice, but multiple elements found") 165 } 166 s.PME = &PM{} 167 s.PME.SetStructInfo(structInfo) 168 n, err = s.PME.ReadDataFrom(r) 169 if err != nil { 170 return totalN, fmt.Errorf("unable to read field PME at %d: %w", totalN, err) 171 } 172 case StructureIDSignature: 173 if fieldIndex == previousFieldIndex { 174 return totalN, fmt.Errorf("field 'PMSE' is not a slice, but multiple elements found") 175 } 176 s.PMSE.SetStructInfo(structInfo) 177 n, err = s.PMSE.ReadDataFrom(r) 178 if err != nil { 179 return totalN, fmt.Errorf("unable to read field PMSE at %d: %w", totalN, err) 180 } 181 default: 182 return totalN, fmt.Errorf("there is no field with structure ID '%s' in Manifest", structInfo.ID) 183 } 184 totalN += n 185 previousFieldIndex = fieldIndex 186 } 187 } 188 189 // RehashRecursive calls Rehash (see below) recursively. 190 func (s *Manifest) RehashRecursive() { 191 s.BPMH.Rehash() 192 if s.PME != nil { 193 s.PME.Rehash() 194 } 195 s.PMSE.Rehash() 196 s.Rehash() 197 } 198 199 // Rehash sets values which are calculated automatically depending on the rest 200 // data. It is usually about the total size field of an element. 201 func (s *Manifest) Rehash() { 202 s.BPMH = BPMH(s.rehashedBPMH()) 203 } 204 205 // WriteTo writes the Manifest into 'w' in format defined in 206 // the document #575623. 207 func (s *Manifest) WriteTo(w io.Writer) (int64, error) { 208 totalN := int64(0) 209 s.Rehash() 210 211 // BPMH (ManifestFieldType: element) 212 { 213 n, err := s.BPMH.WriteTo(w) 214 if err != nil { 215 return totalN, fmt.Errorf("unable to write field 'BPMH': %w", err) 216 } 217 totalN += int64(n) 218 } 219 220 // SE (ManifestFieldType: elementList) 221 { 222 for idx := range s.SE { 223 n, err := s.SE[idx].WriteTo(w) 224 if err != nil { 225 return totalN, fmt.Errorf("unable to write field 'SE[%d]': %w", idx, err) 226 } 227 totalN += int64(n) 228 } 229 } 230 231 // PME (ManifestFieldType: element) 232 if s.PME != nil { 233 n, err := s.PME.WriteTo(w) 234 if err != nil { 235 return totalN, fmt.Errorf("unable to write field 'PME': %w", err) 236 } 237 totalN += int64(n) 238 } 239 240 // PMSE (ManifestFieldType: element) 241 { 242 n, err := s.PMSE.WriteTo(w) 243 if err != nil { 244 return totalN, fmt.Errorf("unable to write field 'PMSE': %w", err) 245 } 246 totalN += int64(n) 247 } 248 249 return totalN, nil 250 } 251 252 // BPMHSize returns the size in bytes of the value of field BPMH 253 func (s *Manifest) BPMHTotalSize() uint64 { 254 return s.BPMH.TotalSize() 255 } 256 257 // SESize returns the size in bytes of the value of field SE 258 func (s *Manifest) SETotalSize() uint64 { 259 var size uint64 260 for idx := range s.SE { 261 size += s.SE[idx].TotalSize() 262 } 263 return size 264 } 265 266 // PMESize returns the size in bytes of the value of field PME 267 func (s *Manifest) PMETotalSize() uint64 { 268 return s.PME.TotalSize() 269 } 270 271 // PMSESize returns the size in bytes of the value of field PMSE 272 func (s *Manifest) PMSETotalSize() uint64 { 273 return s.PMSE.TotalSize() 274 } 275 276 // BPMHOffset returns the offset in bytes of field BPMH 277 func (s *Manifest) BPMHOffset() uint64 { 278 return 0 279 } 280 281 // SEOffset returns the offset in bytes of field SE 282 func (s *Manifest) SEOffset() uint64 { 283 return s.BPMHOffset() + s.BPMHTotalSize() 284 } 285 286 // PMEOffset returns the offset in bytes of field PME 287 func (s *Manifest) PMEOffset() uint64 { 288 return s.SEOffset() + s.SETotalSize() 289 } 290 291 // PMSEOffset returns the offset in bytes of field PMSE 292 func (s *Manifest) PMSEOffset() uint64 { 293 return s.PMEOffset() + s.PMETotalSize() 294 } 295 296 // Size returns the total size of the Manifest. 297 func (s *Manifest) TotalSize() uint64 { 298 if s == nil { 299 return 0 300 } 301 302 var size uint64 303 size += s.BPMHTotalSize() 304 size += s.SETotalSize() 305 size += s.PMETotalSize() 306 size += s.PMSETotalSize() 307 return size 308 } 309 310 // PrettyString returns the content of the structure in an easy-to-read format. 311 func (s *Manifest) PrettyString(depth uint, withHeader bool, opts ...pretty.Option) string { 312 var lines []string 313 if withHeader { 314 lines = append(lines, pretty.Header(depth, "Boot Policy Manifest", s)) 315 } 316 if s == nil { 317 return strings.Join(lines, "\n") 318 } 319 // ManifestFieldType is element 320 lines = append(lines, pretty.SubValue(depth+1, "BPMH: Header", "", &s.BPMH, opts...)...) 321 // ManifestFieldType is elementList 322 lines = append(lines, pretty.Header(depth+1, fmt.Sprintf("SE: Array of \"Boot Policy Manifest\" of length %d", len(s.SE)), s.SE)) 323 for i := 0; i < len(s.SE); i++ { 324 lines = append(lines, fmt.Sprintf("%sitem #%d: ", strings.Repeat(" ", int(depth+2)), i)+strings.TrimSpace(s.SE[i].PrettyString(depth+2, true))) 325 } 326 if depth < 1 { 327 lines = append(lines, "") 328 } 329 // ManifestFieldType is element 330 lines = append(lines, pretty.SubValue(depth+1, "PME: Platform Manufacturer", "", s.PME, opts...)...) 331 // ManifestFieldType is element 332 lines = append(lines, pretty.SubValue(depth+1, "PMSE: Signature", "", &s.PMSE, opts...)...) 333 if depth < 2 { 334 lines = append(lines, "") 335 } 336 return strings.Join(lines, "\n") 337 }