Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/mkubootimage Add support for writing "AArch64 Linux ...



details:   https://anonhg.NetBSD.org/src/rev/4ced7ddac63d
branches:  trunk
changeset: 829505:4ced7ddac63d
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Feb 04 15:44:51 2018 +0000

description:
Add support for writing "AArch64 Linux kernel image" format images.

These images begin with a 64-byte header that includes a load offset,
image size, some flags, and a small (2 word) area at the start for
executable code.

These images are compatible with U-Boot's "booti" command, and can be
used to make U-Boot relocate our kernel to a 2MB aligned base address.
After relocation, U-Boot will jump to the code at the beginning of the
header, where we encode a relative branch forward instruction to branch
to the beginning of the kernel at offset +0x40.

diffstat:

 usr.bin/mkubootimage/arm64.h        |   67 +++++++++++++
 usr.bin/mkubootimage/mkubootimage.1 |   27 ++++-
 usr.bin/mkubootimage/mkubootimage.c |  180 ++++++++++++++++++++++++++++++-----
 3 files changed, 241 insertions(+), 33 deletions(-)

diffs (truncated from 452 to 300 lines):

diff -r ba9bd6dbab8e -r 4ced7ddac63d usr.bin/mkubootimage/arm64.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/mkubootimage/arm64.h      Sun Feb 04 15:44:51 2018 +0000
@@ -0,0 +1,67 @@
+/* $NetBSD: arm64.h,v 1.1 2018/02/04 15:44:51 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _HAVE_ARM64_H
+#define _HAVE_ARM64_H
+
+/*
+ * AArch64 Linux kernel image header, as specified in
+ * https://www.kernel.org/doc/Documentation/arm64/booting.txt
+ */
+
+/* 64-byte kernel image header */
+struct arm64_image_header {
+       uint32_t        code0;          /* Executable code */
+       uint32_t        code1;          /* Executable code */
+       uint64_t        text_offset;    /* Image load offset */
+       uint64_t        image_size;     /* Effective image size */
+       uint64_t        flags;          /* kernel flags */
+       uint64_t        res2;           /* reserved */
+       uint64_t        res3;           /* reserved */
+       uint64_t        res4;           /* reserved */
+       uint32_t        magic;          /* Magic number ("ARM\x64") */
+       uint32_t        res5;           /* reserved (used for PE COFF offset) */
+};
+
+/* Kernel flags */
+#define        ARM64_FLAGS_ENDIAN_BE           __BIT(0)
+#define        ARM64_FLAGS_PAGE_SIZE           __BITS(2,1)
+#define         ARM64_FLAGS_PAGE_SIZE_UNSPEC           0
+#define         ARM64_FLAGS_PAGE_SIZE_4K               1
+#define         ARM64_FLAGS_PAGE_SIZE_16K              2
+#define         ARM64_FLAGS_PAGE_SIZE_64K              3
+#define        ARM64_FLAGS_PHYS_PLACEMENT      __BIT(3)
+#define         ARM64_FLAGS_PHYS_PLACEMENT_DRAM_BASE   0
+#define         ARM64_FLAGS_PHYS_PLACEMENT_ANY         1
+
+/* Magic */
+#define        ARM64_MAGIC     0x644d5241
+
+/* Executable code. Program relative branch forward 64 bytes. */
+#define        ARM64_CODE0     0x14000010
+
+#endif /* !_HAVE_ARM64_H */
diff -r ba9bd6dbab8e -r 4ced7ddac63d usr.bin/mkubootimage/mkubootimage.1
--- a/usr.bin/mkubootimage/mkubootimage.1       Sun Feb 04 11:08:16 2018 +0000
+++ b/usr.bin/mkubootimage/mkubootimage.1       Sun Feb 04 15:44:51 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: mkubootimage.1,v 1.11 2017/09/29 21:18:28 jmcneill Exp $
+.\"    $NetBSD: mkubootimage.1,v 1.12 2018/02/04 15:44:51 jmcneill Exp $
 .\"
 .\" Copyright (c) 2012 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd September 29, 2017
+.Dd February 4, 2018
 .Dt MKUBOOTIMAGE 1
 .Os
 .Sh NAME
@@ -41,6 +41,7 @@
 .Op Fl C Po bz2 Ns | Ns gz Ns | Ns lzma Ns | Ns lzo Ns | Ns none Pc
 .Op Fl E Ar address
 .Op Fl e Ar address
+.Op Fl f Po arm64 Ns | Ns uimg Pc
 .Op Fl m Ar magic
 .Fl n Ar image
 .Op Fl O Po freebsd Ns | Ns linux Ns | Ns netbsd Ns | Ns openbsd Pc
@@ -57,12 +58,16 @@
 .Bl -tag -width indent
 .It Fl A No ( arm Ns | Ns arm64 Ns | Ns i386 Ns | Ns mips Ns | Ns mips64 Ns | Ns or1k Ns | Ns powerpc Ns | Ns sh )
 Defines the architecture.
-This is required.
+This is required for 
+.Qq uimg
+format images.
 .It Fl a Ar address
 Sets the image load address.
 This is an integer between 0 and
 .Dv UINT32_MAX .
-This is required for all image types except for script, ramdisk, and kernel_noload.
+This is required for all
+.Qq uimg
+image types except for script, ramdisk, and kernel_noload.
 .It Fl C No ( bz2 Ns | Ns gz Ns | Ns lzma Ns | Ns lzo Ns | Ns none )
 Defines the compression.
 The default is
@@ -93,10 +98,16 @@
 are not set, the entry point defaults to the
 image load address
 .Pq Fl a .
+.It Fl f No ( arm64 Ns | Ns uimg )
+Defines the output image format type.
+The default is
+.Qq uimg .
 .It Fl h
 Display the usage and exit.
 .It Fl m Ar magic
-Set the magic.
+Set the magic used for
+.Qq uimg
+format images.
 This is an integer between 0 and
 .Dv UINT32_MAX .
 The default is
@@ -110,7 +121,9 @@
 .Qq netbsd .
 .It Fl T No ( fs Ns | Ns kernel Ns | Ns kernel_noload Ns | Ns ramdisk Ns | Ns standalone Ns | Ns script )
 Defines the image type.
-This is required.
+This is required for
+.Qq uimg
+format images.
 .El
 .Pp
 The required
@@ -161,7 +174,7 @@
 The
 .Nm
 utility was originally written by
-.An Jared D. McNeill .
+.An Jared McNeill .
 This manual page was written by
 .An Jeremy C. Reed .
 .\" .Sh CAVEATS
diff -r ba9bd6dbab8e -r 4ced7ddac63d usr.bin/mkubootimage/mkubootimage.c
--- a/usr.bin/mkubootimage/mkubootimage.c       Sun Feb 04 11:08:16 2018 +0000
+++ b/usr.bin/mkubootimage/mkubootimage.c       Sun Feb 04 15:44:51 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mkubootimage.c,v 1.22 2017/11/05 11:07:32 jmcneill Exp $ */
+/* $NetBSD: mkubootimage.c,v 1.23 2018/02/04 15:44:51 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2010 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -30,15 +30,17 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: mkubootimage.c,v 1.22 2017/11/05 11:07:32 jmcneill Exp $");
+__RCSID("$NetBSD: mkubootimage.c,v 1.23 2018/02/04 15:44:51 jmcneill Exp $");
 
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/endian.h>
+#include <sys/param.h>
 #include <sys/uio.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -48,11 +50,18 @@
 #include <unistd.h>
 
 #include "uboot.h"
+#include "arm64.h"
 
 #ifndef __arraycount
 #define __arraycount(__x)      (sizeof(__x) / sizeof(__x[0]))
 #endif
 
+enum image_format {
+       FMT_UNKNOWN,
+       FMT_UIMG,       /* Legacy U-Boot image */
+       FMT_ARM64,      /* Linux ARM64 image (booti) */
+};
+
 extern uint32_t crc32(const void *, size_t);
 extern uint32_t crc32v(const struct iovec *, int);
 
@@ -64,6 +73,41 @@
 static uint32_t image_entrypoint = 0;
 static char *image_name;
 static uint32_t image_magic = IH_MAGIC;
+static enum image_format image_format = FMT_UIMG;
+
+static const struct uboot_image_format {
+       enum image_format format;
+       const char *name;
+} uboot_image_format[] = {
+       { FMT_UIMG,             "uimg" },
+       { FMT_ARM64,            "arm64" },
+};
+
+static enum image_format
+get_image_format(const char *name)
+{
+       unsigned int i;
+
+       for (i = 0; i < __arraycount(uboot_image_format); i++) {
+               if (strcmp(uboot_image_format[i].name, name) == 0)
+                       return uboot_image_format[i].format;
+       }
+
+       return FMT_UNKNOWN;
+}
+
+static const char *
+get_image_format_name(enum image_format format)
+{
+       unsigned int i;
+
+       for (i = 0; i < __arraycount(uboot_image_format); i++) {
+               if (uboot_image_format[i].format == format)
+                       return uboot_image_format[i].name;
+       }
+
+       return "Unknown";
+}
 
 static const struct uboot_os {
        enum uboot_image_os os;
@@ -225,13 +269,14 @@
        fprintf(stderr, " -O <openbsd|netbsd|freebsd|linux>");
        fprintf(stderr, " -T <standalone|kernel|kernel_noload|ramdisk|fs|script>");
        fprintf(stderr, " -a <addr> [-e <ep>] [-m <magic>] -n <name>");
+       fprintf(stderr, " [-f <uimg|arm64>]");
        fprintf(stderr, " <srcfile> <dstfile>\n");
 
        exit(EXIT_FAILURE);
 }
 
 static void
-dump_header(struct uboot_image_header *hdr)
+dump_header_uimg(struct uboot_image_header *hdr)
 {
        time_t tm = ntohl(hdr->ih_time);
 
@@ -254,7 +299,7 @@
 }
 
 static int
-generate_header(struct uboot_image_header *hdr, int kernel_fd)
+generate_header_uimg(struct uboot_image_header *hdr, int kernel_fd)
 {
        uint8_t *p;
        struct stat st;
@@ -310,13 +355,56 @@
        crc = crc32((void *)hdr, sizeof(*hdr));
        hdr->ih_hcrc = htonl(crc);
 
-       dump_header(hdr);
+       dump_header_uimg(hdr);
+
+       return 0;
+}
+
+static void
+dump_header_arm64(struct arm64_image_header *hdr)
+{
+       printf(" magic:       0x%" PRIx32 "\n", le32toh(hdr->magic));
+       printf(" text offset: 0x%" PRIx64 "\n", le64toh(hdr->text_offset));
+       printf(" image size:  %" PRIu64 "\n", le64toh(hdr->image_size));
+       printf(" flags:       0x%" PRIx64 "\n", le64toh(hdr->flags));
+}
+
+static int
+generate_header_arm64(struct arm64_image_header *hdr, int kernel_fd)
+{
+       struct stat st;
+       uint32_t flags;
+       int error;
+
+       error = fstat(kernel_fd, &st);
+       if (error == -1) {
+               perror("stat");
+               return errno;
+       }
+



Home | Main Index | Thread Index | Old Index