github.com/usbarmory/armory-boot@v0.0.0-20240307133412-208c66a380b9/sdp/imx.go (about)

     1  // https://github.com/usbarmory/armory-boot
     2  //
     3  // Copyright (c) WithSecure Corporation
     4  // https://foundry.withsecure.com
     5  //
     6  // Use of this source code is governed by the license
     7  // that can be found in the LICENSE file.
     8  
     9  package sdp
    10  
    11  import (
    12  	"bytes"
    13  	"encoding/binary"
    14  	"errors"
    15  )
    16  
    17  // Program image tags
    18  // (p309, 8.7 Program image, IMX6ULLRM).
    19  const (
    20  	TagIVT = 0xd1
    21  	TagDCD = 0xd2
    22  )
    23  
    24  // DCD constants
    25  // (p312, 8.7.2 Device Configuration Data (DCD), IMX6ULLRM).
    26  const (
    27  	// write command tag
    28  	WriteData = 0xcc
    29  	// DCD pointer offset within IVT
    30  	DCDOffset = 12
    31  	// maximum DCD size
    32  	DCDSize = 1768
    33  )
    34  
    35  // DCDHeader represents a DCD header
    36  // (p312, 8.7.2 Device Configuration Data (DCD), IMX6ULLRM).
    37  type DCDHeader struct {
    38  	Tag     uint8
    39  	Length  uint16
    40  	Version uint8
    41  }
    42  
    43  // IVT represents an IVT entry
    44  // (p311, 8.7.1.1 Image vector table structure, IMX6ULLRM).
    45  type IVT struct {
    46  	Tag      uint8
    47  	Length   uint16
    48  	Version  uint8
    49  	Entry    uint32
    50  	_        uint32
    51  	DCD      uint32
    52  	BootData uint32
    53  	Self     uint32
    54  	CSF      uint32
    55  	_        uint32
    56  }
    57  
    58  // ParseIVT extracts the Image Vector Table (IVT) from an imx format binary
    59  // image.
    60  func ParseIVT(imx []byte) (ivt *IVT, err error) {
    61  	ivt = &IVT{}
    62  
    63  	if err = binary.Read(bytes.NewReader(imx), binary.LittleEndian, ivt); err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	if ivt.Tag != TagIVT {
    68  		return nil, errors.New("could not find IVT tag")
    69  	}
    70  
    71  	return
    72  }
    73  
    74  // ParseDCD extracts the Device Configuration Data (DCD) from an imx format
    75  // binary image.
    76  func ParseDCD(imx []byte, ivt *IVT) (dcd []byte, err error) {
    77  	hdr := &DCDHeader{}
    78  	dcdStart := ivt.DCD - ivt.Self
    79  
    80  	if len(imx) < int(dcdStart+4) {
    81  		return nil, errors.New("could not parse DCD, insufficient length")
    82  	}
    83  
    84  	if err = binary.Read(bytes.NewReader(imx[dcdStart:dcdStart+4]), binary.BigEndian, hdr); err != nil {
    85  		return
    86  	}
    87  
    88  	if hdr.Tag != TagDCD {
    89  		return nil, errors.New("could not find DCD tag")
    90  	}
    91  
    92  	if hdr.Length > DCDSize || int(hdr.Length) > int(dcdStart)+len(imx) {
    93  		return nil, errors.New("could not parse DCD, invalid length")
    94  	}
    95  
    96  	dcd = imx[dcdStart : dcdStart+uint32(hdr.Length)]
    97  
    98  	return
    99  }