github.com/linuxboot/fiano@v1.2.0/pkg/cbfs/payload.go (about)

     1  // Copyright 2018-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  package cbfs
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"log"
    11  )
    12  
    13  func init() {
    14  	if err := RegisterFileReader(&SegReader{Type: TypeSELF, Name: "Payload", New: NewPayloadRecord}); err != nil {
    15  		log.Fatal(err)
    16  	}
    17  }
    18  
    19  func NewPayloadRecord(f *File) (ReadWriter, error) {
    20  	p := &PayloadRecord{File: *f}
    21  	return p, nil
    22  }
    23  
    24  func (p *PayloadRecord) Read(in io.ReadSeeker) error {
    25  	for {
    26  		var h PayloadHeader
    27  		if err := Read(in, &h); err != nil {
    28  			Debug("PayloadHeader read: %v", err)
    29  			return err
    30  		}
    31  		Debug("Got PayloadHeader %s", h.String())
    32  		p.Segs = append(p.Segs, h)
    33  		if h.Type == SegEntry {
    34  			break
    35  		}
    36  	}
    37  	// Seek to offset (after the header); the remainder is the actual payload.
    38  	offset, err := in.Seek(0, io.SeekCurrent)
    39  	if err != nil {
    40  		return fmt.Errorf("Finding location in stream: %v", err)
    41  	}
    42  	bodySize := int64(p.Size) - offset
    43  	Debug("Payload size: %v, body size: %v, offset: %v", p.Size, bodySize, offset)
    44  	if bodySize < 0 {
    45  		// This should not happen. Tolerate a potential error.
    46  		return nil
    47  	}
    48  	// This _may_ happen. E.g. with the test payload here. Silently ignore.
    49  	if bodySize == 0 {
    50  		Debug("Payload empty, nothing to read")
    51  		return nil
    52  	}
    53  	p.FData = make([]byte, bodySize)
    54  	n, err := in.Read(p.FData)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	Debug("Payload read %d bytes", n)
    59  	return nil
    60  }
    61  
    62  func (h *PayloadRecord) String() string {
    63  	s := recString(h.File.Name, h.RecordStart, h.Type.String(), h.Size, "none")
    64  	for i, seg := range h.Segs {
    65  		s += "\n"
    66  		s += recString(fmt.Sprintf(" Seg #%d", i), seg.Offset, seg.Type.String(), seg.Size, seg.Compression.String())
    67  	}
    68  	return s
    69  }
    70  
    71  func (r *PayloadHeader) String() string {
    72  	return fmt.Sprintf("Type %#x Compression %#x Offset %#x LoadAddress %#x Size %#x MemSize %#x",
    73  		r.Type,
    74  		r.Compression,
    75  		r.Offset,
    76  		r.LoadAddress,
    77  		r.Size,
    78  		r.MemSize)
    79  }
    80  
    81  func (r *PayloadRecord) Write(w io.Writer) error {
    82  	if err := Write(w, r.Segs); err != nil {
    83  		return err
    84  	}
    85  	return Write(w, r.FData)
    86  }
    87  
    88  func (r *PayloadRecord) GetFile() *File {
    89  	return &r.File
    90  }