github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/image/image.go (about)

     1  // Copyright 2022 the u-root 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 image contains a parser for Arm64 Linux Image format. It
     6  // assumes little endian arm.
     7  package image
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/binary"
    12  	"errors"
    13  	"fmt"
    14  	"math"
    15  )
    16  
    17  const (
    18  	// Magic values used in Image header.
    19  	Magic = 0x644d5241
    20  )
    21  
    22  var (
    23  	kernelImageSize = uint64(math.Pow(2, 24)) // 16MB, a guess value similar to that used in kexec-tools.
    24  
    25  	errBadMagic     = errors.New("bad header magic")
    26  	errBadEndianess = errors.New("invalid Image endianess, expected little")
    27  )
    28  
    29  // Arm64Header is header for Arm64 Image.
    30  type Arm64Header struct {
    31  	Code0      uint32 `offset:"0x00"`
    32  	Code1      uint32 `offset:"0x04"`
    33  	TextOffset uint64 `offset:"0x08"`
    34  	ImageSize  uint64 `offset:"0x10"`
    35  	Flags      uint64 `offset:"0x18"`
    36  	Res2       uint64 `offset:"0x20"`
    37  	Res3       uint64 `offset:"0x28"`
    38  	Res4       uint64 `offset:"0x30"`
    39  	Magic      uint32 `offset:"0x38"`
    40  	Res5       uint32 `offset:"0x3c"`
    41  }
    42  
    43  // Image abstracts Arm64 Image.
    44  type Image struct {
    45  	Header Arm64Header
    46  	Data   []byte
    47  }
    48  
    49  // ParseFromBytes parse an Image from bytes slice.
    50  func ParseFromBytes(data []byte) (*Image, error) {
    51  	img := &Image{}
    52  
    53  	if err := binary.Read(bytes.NewBuffer(data), binary.LittleEndian, &img.Header); err != nil {
    54  		return img, fmt.Errorf("unmarshaling arm64 header: %w", err)
    55  	}
    56  
    57  	if img.Header.Magic != Magic {
    58  		return img, errBadMagic
    59  	}
    60  
    61  	if img.Header.ImageSize == 0 {
    62  		/* For 3.16 and older kernels. */
    63  		img.Header.TextOffset = 0x80000
    64  		img.Header.ImageSize = kernelImageSize
    65  	}
    66  
    67  	// v3.17: https://www.kernel.org/doc/Documentation/arm64/booting.txt
    68  	//
    69  	// NOTE(10000TB): For now assumes and support little endian arm.
    70  	// Error out if Image is not little endian.
    71  	if int(img.Header.Flags&0x1) != 0 {
    72  		return img, errBadEndianess
    73  	}
    74  
    75  	img.Data = data
    76  
    77  	return img, nil
    78  }