<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/23869">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">util/cbfstool: Add ARM64 Image support<br><br>Add support for booting Linux ARM64 Image.<br><br>* Add new ARM64 trampoline code<br>* Add ARM64 Image detection<br>* Parse the Image and mark it relocateable if no loadaddress was given<br>* Place the trampoline 64 KiB before the Linux Image<br><br>Tested on qemu-armv8 and Linux 4.15.<br><br>Change-Id: I9a8183a87de4dc3a4c4f038fe5b4912ada5d75f9<br>---<br>M payloads/external/linux/Makefile.inc<br>A payloads/external/linux/arm64image_loader.h<br>A payloads/external/linux/linux_trampoline_arm64.S<br>A payloads/external/linux/linux_trampoline_arm64.c<br>M util/cbfstool/Makefile.inc<br>M util/cbfstool/cbfs-payload-linux.c<br>M util/cbfstool/cbfstool.c<br>M util/cbfstool/common.h<br>8 files changed, 358 insertions(+), 7 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/23869/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/payloads/external/linux/Makefile.inc b/payloads/external/linux/Makefile.inc</span><br><span>index c0a2b0c..e3c5924 100644</span><br><span>--- a/payloads/external/linux/Makefile.inc</span><br><span>+++ b/payloads/external/linux/Makefile.inc</span><br><span>@@ -4,6 +4,7 @@</span><br><span> ##</span><br><span> ## Copyright (C) 2009-2010 coresystems GmbH</span><br><span> ## Copyright (C) 2015 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+## Copyright 2018-present Facebook, Inc.</span><br><span> ##</span><br><span> ## This program is free software; you can redistribute it and/or modify</span><br><span> ## it under the terms of the GNU General Public License as published by</span><br><span>@@ -20,6 +21,14 @@</span><br><span> </span><br><span> linuxdir:=$(top)/payloads/external/linux</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ifneq ($(GCC_CC_arm64),)</span><br><span style="color: hsl(120, 100%, 40%);">+$(linuxdir)/linux_trampoline_arm64.c: $(linuxdir)/linux_trampoline_arm64.S $(top)/src/arch/arm64/include/*</span><br><span style="color: hsl(120, 100%, 40%);">+    $(MAKE) -C $(linuxdir) linux_trampoline_arm64.c \</span><br><span style="color: hsl(120, 100%, 40%);">+             HOSTCC="$(HOSTCC)" \</span><br><span style="color: hsl(120, 100%, 40%);">+                CC="$(GCC_CC_arm64)" \</span><br><span style="color: hsl(120, 100%, 40%);">+              OBJCOPY="$(OBJCOPY_arm64)" \</span><br><span style="color: hsl(120, 100%, 40%);">+                CFLAGS="$(CFLAGS_arm64) $(armv8_flags) -I$(top)/src/arch/arm64/include"</span><br><span style="color: hsl(120, 100%, 40%);">+endif</span><br><span> ifneq ($(GCC_CC_x86_32),)</span><br><span> $(linuxdir)/linux_trampoline_x86.c: $(linuxdir)/linux_trampoline_x86.S $(top)/src/arch/x86/include/*</span><br><span>        $(MAKE) -C $(linuxdir) linux_trampoline_x86.c \</span><br><span>diff --git a/payloads/external/linux/arm64image_loader.h b/payloads/external/linux/arm64image_loader.h</span><br><span>new file mode 100644</span><br><span>index 0000000..fdc5dee</span><br><span>--- /dev/null</span><br><span>+++ b/payloads/external/linux/arm64image_loader.h</span><br><span>@@ -0,0 +1,20 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018-present Facebook, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* trampoline */</span><br><span style="color: hsl(120, 100%, 40%);">+extern unsigned char linux_trampoline_arm64_bin[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern unsigned int linux_trampoline_arm64_bin_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAMPOLINE_SIZE (64 * KiB)</span><br><span>diff --git a/payloads/external/linux/linux_trampoline_arm64.S b/payloads/external/linux/linux_trampoline_arm64.S</span><br><span>new file mode 100644</span><br><span>index 0000000..c28f3a9</span><br><span>--- /dev/null</span><br><span>+++ b/payloads/external/linux/linux_trampoline_arm64.S</span><br><span>@@ -0,0 +1,120 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * linux_trampoline</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2013 Patrick Georgi <patrick@georgi-clan.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018-present Facebook, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* NOTE: THIS CODE MUST REMAIN POSITION INDEPENDENT</span><br><span style="color: hsl(120, 100%, 40%);">+ *       IT SHOULDN'T USE THE STACK</span><br><span style="color: hsl(120, 100%, 40%);">+ *       AND IN GENERAL EXPECT NOTHING BUT RAM TO WORK</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+.data</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAMPOLINE_SIZE (64 * 1024)</span><br><span style="color: hsl(120, 100%, 40%);">+#define HEADER_SIG 0x4f49424c // LBIO little endian</span><br><span style="color: hsl(120, 100%, 40%);">+#define CB_TAG_FORWARD 0x11</span><br><span style="color: hsl(120, 100%, 40%);">+#define CB_TAG_DEVICETREE 0x0033</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find the devicetree that should have been placed in a coreboot table.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Register usage:</span><br><span style="color: hsl(120, 100%, 40%);">+ * x0:    base pointer</span><br><span style="color: hsl(120, 100%, 40%);">+ * x1:    working register</span><br><span style="color: hsl(120, 100%, 40%);">+ * x2:    working register</span><br><span style="color: hsl(120, 100%, 40%);">+ * x3:    counter, initial value is the number of coreboot tables</span><br><span style="color: hsl(120, 100%, 40%);">+ * x4:    start of trampoline, to calculcate the kernel position</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+trampoline_start:</span><br><span style="color: hsl(120, 100%, 40%);">+   // Store entry point for later use</span><br><span style="color: hsl(120, 100%, 40%);">+   adr    x4, trampoline_start</span><br><span style="color: hsl(120, 100%, 40%);">+   // x0 contains pointer to coreboot tables</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Verify coreboot table header</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mov    w2, HEADER_SIG >> 16</span><br><span style="color: hsl(120, 100%, 40%);">+   lsl    w2, w2, 16</span><br><span style="color: hsl(120, 100%, 40%);">+   mov    w1, (HEADER_SIG & 0xffff)</span><br><span style="color: hsl(120, 100%, 40%);">+   orr    w2, w2, w1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // verify signature32 (header magic)</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 0]</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp    w1, w2</span><br><span style="color: hsl(120, 100%, 40%);">+   b.ne   _halt</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // verify header_bytes</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 4]</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp    w1, #0</span><br><span style="color: hsl(120, 100%, 40%);">+   b.eq   _halt</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // verify table_bytes</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 16]</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp    w1, #0</span><br><span style="color: hsl(120, 100%, 40%);">+   b.eq   _halt</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // TODO: Signature check</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Number of table entries goes into w3</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w3, [x0, 20]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Set pointer to first entry</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 4]</span><br><span style="color: hsl(120, 100%, 40%);">+   add    x0, x1, x0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // x0 contains the table entry pointer</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+tablescan:</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 0]</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp    w1, #CB_TAG_FORWARD</span><br><span style="color: hsl(120, 100%, 40%);">+   b.ne   devicetree</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 8]</span><br><span style="color: hsl(120, 100%, 40%);">+   add    x0, x0, x1</span><br><span style="color: hsl(120, 100%, 40%);">+   b      next</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+devicetree:</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 0]</span><br><span style="color: hsl(120, 100%, 40%);">+   cmp    w1, #CB_TAG_DEVICETREE</span><br><span style="color: hsl(120, 100%, 40%);">+   b.ne   next</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mov    x1, #8</span><br><span style="color: hsl(120, 100%, 40%);">+   add    x0, x0, x1</span><br><span style="color: hsl(120, 100%, 40%);">+   b      done</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+next:</span><br><span style="color: hsl(120, 100%, 40%);">+   // Increment table entries pointer</span><br><span style="color: hsl(120, 100%, 40%);">+   ldr    w1, [x0, 4]</span><br><span style="color: hsl(120, 100%, 40%);">+   add    x0, x0, x1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Decrement table entry counter</span><br><span style="color: hsl(120, 100%, 40%);">+   subs    w3, w3, #1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   b.ne   tablescan</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // not found, call the kernel without devicetree ?</span><br><span style="color: hsl(120, 100%, 40%);">+   b _halt</span><br><span style="color: hsl(120, 100%, 40%);">+done:</span><br><span style="color: hsl(120, 100%, 40%);">+   // devicetree pointer is in x0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // kernel entry point is trampoline_start + 64 KiB</span><br><span style="color: hsl(120, 100%, 40%);">+   // CBFSTOOL did make sure that the kernel is at the given offset</span><br><span style="color: hsl(120, 100%, 40%);">+   mov    x1, #(TRAMPOLINE_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+   add    x1, x1, x4</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Jump to kernel</span><br><span style="color: hsl(120, 100%, 40%);">+   br     x1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+_halt:</span><br><span style="color: hsl(120, 100%, 40%);">+   wfi</span><br><span style="color: hsl(120, 100%, 40%);">+   b _halt</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+trampoline_end:</span><br><span>diff --git a/payloads/external/linux/linux_trampoline_arm64.c b/payloads/external/linux/linux_trampoline_arm64.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b4bc2c6</span><br><span>--- /dev/null</span><br><span>+++ b/payloads/external/linux/linux_trampoline_arm64.c</span><br><span>@@ -0,0 +1,14 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* This file is automatically generated. Do not manually change */</span><br><span style="color: hsl(120, 100%, 40%);">+unsigned char linux_trampoline_arm64_bin[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  0x04, 0x00, 0x00, 0x10, 0x22, 0xe9, 0x89, 0x52, 0x42, 0x3c, 0x10, 0x53, 0x81, 0x49, 0x88, 0x52,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x42, 0x00, 0x01, 0x2a, 0x01, 0x00, 0x40, 0xb9, 0x3f, 0x00, 0x02, 0x6b, 0xc1, 0x03, 0x00, 0x54,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x01, 0x04, 0x40, 0xb9, 0x3f, 0x00, 0x00, 0x71, 0x60, 0x03, 0x00, 0x54, 0x01, 0x10, 0x40, 0xb9,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x3f, 0x00, 0x00, 0x71, 0x00, 0x03, 0x00, 0x54, 0x03, 0x14, 0x40, 0xb9, 0x01, 0x04, 0x40, 0xb9,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x20, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x40, 0xb9, 0x3f, 0x44, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x01, 0x08, 0x40, 0xb9, 0x00, 0x00, 0x01, 0x8b, 0x07, 0x00, 0x00, 0x14, 0x01, 0x00, 0x40, 0xb9,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x3f, 0xcc, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54, 0x01, 0x01, 0x80, 0xd2, 0x00, 0x00, 0x01, 0x8b,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x06, 0x00, 0x00, 0x14, 0x01, 0x04, 0x40, 0xb9, 0x00, 0x00, 0x01, 0x8b, 0x63, 0x04, 0x00, 0x71,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x21, 0xfe, 0xff, 0x54, 0x04, 0x00, 0x00, 0x14, 0x21, 0x00, 0xa0, 0xd2, 0x21, 0x00, 0x04, 0x8b,</span><br><span style="color: hsl(120, 100%, 40%);">+  0x20, 0x00, 0x1f, 0xd6, 0x7f, 0x20, 0x03, 0xd5, 0xff, 0xff, 0xff, 0x17</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+unsigned int linux_trampoline_arm64_bin_len = 156;</span><br><span>diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc</span><br><span>index 0575e1d..c1626c4 100644</span><br><span>--- a/util/cbfstool/Makefile.inc</span><br><span>+++ b/util/cbfstool/Makefile.inc</span><br><span>@@ -39,6 +39,7 @@</span><br><span> cbfsobj += valstr.o</span><br><span> # linux as payload</span><br><span> cbfsobj += linux_trampoline_x86.o</span><br><span style="color: hsl(120, 100%, 40%);">+cbfsobj += linux_trampoline_arm64.o</span><br><span> cbfsobj += cbfs-payload-linux.o</span><br><span> </span><br><span> # compression algorithms</span><br><span>diff --git a/util/cbfstool/cbfs-payload-linux.c b/util/cbfstool/cbfs-payload-linux.c</span><br><span>index 17e18ca..7e73db0 100644</span><br><span>--- a/util/cbfstool/cbfs-payload-linux.c</span><br><span>+++ b/util/cbfstool/cbfs-payload-linux.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span>  * cbfs-payload-linux</span><br><span>  *</span><br><span>  * Copyright (C) 2013 Patrick Georgi <patrick@georgi-clan.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright     2018-present Facebook, Inc.</span><br><span>  *</span><br><span>  * This program is free software; you can redistribute it and/or modify</span><br><span>  * it under the terms of the GNU General Public License as published by</span><br><span>@@ -20,18 +21,20 @@</span><br><span> #include "common.h"</span><br><span> #include "cbfs.h"</span><br><span> #include "bzimage_loader.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "arm64image_loader.h"</span><br><span> </span><br><span> /*</span><br><span>  * Current max number of segments include:</span><br><span>  *</span><br><span>  * 1. parameters</span><br><span>  * 2. kernel</span><br><span style="color: hsl(0, 100%, 40%);">- * 3. trampoline</span><br><span style="color: hsl(0, 100%, 40%);">- * 4. optional cmdline</span><br><span style="color: hsl(0, 100%, 40%);">- * 5. optional initrd</span><br><span style="color: hsl(0, 100%, 40%);">- * 6. terminating entry segment</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3. flags</span><br><span style="color: hsl(120, 100%, 40%);">+ * 4. trampoline</span><br><span style="color: hsl(120, 100%, 40%);">+ * 5. optional cmdline</span><br><span style="color: hsl(120, 100%, 40%);">+ * 6. optional initrd</span><br><span style="color: hsl(120, 100%, 40%);">+ * 7. terminating entry segment</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-#define MAX_NUM_SEGMENTS 6</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_NUM_SEGMENTS 7</span><br><span> </span><br><span> struct bzpayload {</span><br><span>    /* Input variables. */</span><br><span>@@ -39,6 +42,7 @@</span><br><span>   struct cbfs_payload_segment segs[MAX_NUM_SEGMENTS];</span><br><span>  struct buffer parameters;</span><br><span>    struct buffer kernel;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct buffer flags;</span><br><span>         struct buffer trampoline;</span><br><span>    struct buffer cmdline;</span><br><span>       struct buffer initrd;</span><br><span>@@ -93,6 +97,31 @@</span><br><span>          (header->header == BZI_SIGNATURE);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define ARM64_IMAGE_KERNEL_HEADER_MAGIC  0x644d5241</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct Arm64KernelHeader {</span><br><span style="color: hsl(120, 100%, 40%);">+      u32 code0;</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 code1;</span><br><span style="color: hsl(120, 100%, 40%);">+    u64 text_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+      u64 image_size;</span><br><span style="color: hsl(120, 100%, 40%);">+       u64 flags;</span><br><span style="color: hsl(120, 100%, 40%);">+    u64 res2;</span><br><span style="color: hsl(120, 100%, 40%);">+     u64 res3;</span><br><span style="color: hsl(120, 100%, 40%);">+     u64 res4;</span><br><span style="color: hsl(120, 100%, 40%);">+     u32 magic;</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 res5;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Return true if buffer looks like an ARM64 Image */</span><br><span style="color: hsl(120, 100%, 40%);">+int probe_for_ARM64Image_header(const struct buffer *input)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct Arm64KernelHeader *header =</span><br><span style="color: hsl(120, 100%, 40%);">+          (const struct Arm64KernelHeader *)input->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (input->size < sizeof(*header))</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     return (header->magic == ARM64_IMAGE_KERNEL_HEADER_MAGIC);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int bzp_init(struct bzpayload *bzp, enum comp_algo algo)</span><br><span> {</span><br><span>   memset(bzp, 0, sizeof(*bzp));</span><br><span>@@ -169,12 +198,23 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int bzp_add_flags(struct bzpayload *bzp,</span><br><span style="color: hsl(120, 100%, 40%);">+                    struct cbfs_payload_flags *flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ bzp_add_segment(bzp, &bzp->flags, flags, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   xdr_be.put64(&bzp->flags, flags->f.u);</span><br><span style="color: hsl(120, 100%, 40%);">+      xdr_be.put32(&bzp->flags, flags->align);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int bzp_init_output(struct bzpayload *bzp, const char *name)</span><br><span> {</span><br><span>   size_t sz = 0;</span><br><span> </span><br><span>   sz += buffer_size(&bzp->parameters);</span><br><span>  sz += buffer_size(&bzp->kernel);</span><br><span style="color: hsl(120, 100%, 40%);">+       sz += buffer_size(&bzp->flags);</span><br><span>       sz += buffer_size(&bzp->trampoline);</span><br><span>  sz += buffer_size(&bzp->cmdline);</span><br><span>     sz += buffer_size(&bzp->initrd);</span><br><span>@@ -371,3 +411,137 @@</span><br><span>      xdr_segs(output, bzp.segs, bzp.num_segments);</span><br><span>        return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add an ARM64 Linux Kernel Image as payload.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The trampoline will locate the devicetree and pass it as argument x0.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Memory map</span><br><span style="color: hsl(120, 100%, 40%);">+ *   ...</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | Usable DRAM                   |</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * --------------------------------| n * 2MiB + text-offset + image-size</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | Linux Kernel                  |</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * --------------------------------| n * 2MiB + text-offset</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | Trampoline                    |</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * --------------------------------| n * 2MiB + text-offset - 64 KiB (entry)</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | Usable DRAM                   |</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ * --------------------------------|</span><br><span style="color: hsl(120, 100%, 40%);">+ * | Devicetree                    |</span><br><span style="color: hsl(120, 100%, 40%);">+ * ------------------------------- | >= MAX((n - 256) * 2MiB, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ * |                               |</span><br><span style="color: hsl(120, 100%, 40%);">+ *    ...</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int parse_ARM64Image_to_payload(const struct buffer *input,</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct buffer *output, uint64_t load_address,</span><br><span style="color: hsl(120, 100%, 40%);">+                         enum comp_algo algo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct Arm64KernelHeader *header =</span><br><span style="color: hsl(120, 100%, 40%);">+          (const struct Arm64KernelHeader *)input->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct buffer tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct bzpayload bzp;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t offset, image_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct cbfs_payload_flags flags = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (bzp_init(&bzp, algo) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (linux_trampoline_arm64_bin_len > TRAMPOLINE_SIZE) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ERROR("FIXME: trampoline size is too big\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Prior to v3.17, the endianness of text_offset was not specified. In</span><br><span style="color: hsl(120, 100%, 40%);">+         * these cases image_size is zero and text_offset is 0x80000 in the</span><br><span style="color: hsl(120, 100%, 40%);">+    * endianness of the kernel.  Where image_size is non-zero image_size is</span><br><span style="color: hsl(120, 100%, 40%);">+       * little-endian and must be respected.  Where image_size is zero,</span><br><span style="color: hsl(120, 100%, 40%);">+     * text_offset can be assumed to be 0x80000.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (header->image_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+          offset = header->text_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+              image_size = header->image_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              offset = 0x80000;</span><br><span style="color: hsl(120, 100%, 40%);">+             // FIXME: How much space to reserve ?</span><br><span style="color: hsl(120, 100%, 40%);">+         image_size = input->size + 4 * MiB;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     /*</span><br><span style="color: hsl(120, 100%, 40%);">+    * The Image must be placed text_offset bytes from a 2MB aligned base</span><br><span style="color: hsl(120, 100%, 40%);">+  * address anywhere in usable system RAM and called there. The region</span><br><span style="color: hsl(120, 100%, 40%);">+  * between the 2 MB aligned base address and the start of the image has</span><br><span style="color: hsl(120, 100%, 40%);">+        * no special significance to the kernel, and may be used for other</span><br><span style="color: hsl(120, 100%, 40%);">+    * purposes. At least image_size bytes from the start of the image must</span><br><span style="color: hsl(120, 100%, 40%);">+        * be free for use by the kernel.</span><br><span style="color: hsl(120, 100%, 40%);">+      */</span><br><span style="color: hsl(120, 100%, 40%);">+    load_address = ALIGN_UP(load_address, 2 * MiB);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Reserve some extra space if the trampoline doesn't fit */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (offset < TRAMPOLINE_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+              offset += 2 * MiB;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (buffer_create(&tmp, image_size + offset, input->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ERROR("Failed to allocate a buffer\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Clear trampoline memory */</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(tmp.data, 0, tmp.size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Place trampoline right before kernel */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(tmp.data + offset - TRAMPOLINE_SIZE, linux_trampoline_arm64_bin,</span><br><span style="color: hsl(120, 100%, 40%);">+              linux_trampoline_arm64_bin_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Place kernel at offset, right after trampoline */</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(tmp.data + offset, input->data, input->size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (bzp_add_kernel(&bzp, &tmp, 0) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Dynamic load address, tell the align */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!load_address) {</span><br><span style="color: hsl(120, 100%, 40%);">+          flags.f.relocateable = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             flags.align = 2 * MiB;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              if (bzp_add_flags(&bzp, &flags))</span><br><span style="color: hsl(120, 100%, 40%);">+                      return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (bzp_init_output(&bzp, input->name) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!load_address) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* data block */</span><br><span style="color: hsl(120, 100%, 40%);">+              bzp_output_segment(&bzp, &bzp.flags, PAYLOAD_SEGMENT_FLAGS, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               ERROR("Adding flags\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* code block */</span><br><span style="color: hsl(120, 100%, 40%);">+      bzp_output_segment(&bzp, &bzp.kernel, PAYLOAD_SEGMENT_CODE,</span><br><span style="color: hsl(120, 100%, 40%);">+                      load_address);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Terminating entry segment. */</span><br><span style="color: hsl(120, 100%, 40%);">+      bzp_output_segment(&bzp, NULL, PAYLOAD_SEGMENT_ENTRY,</span><br><span style="color: hsl(120, 100%, 40%);">+                        load_address + offset - TRAMPOLINE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Set size of buffer taking into account potential compression. */</span><br><span style="color: hsl(120, 100%, 40%);">+   buffer_set_size(&bzp.output, bzp.offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Make passed-in output buffer be valid. */</span><br><span style="color: hsl(120, 100%, 40%);">+  buffer_clone(output, &bzp.output);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Serialize the segments with the correct encoding. */</span><br><span style="color: hsl(120, 100%, 40%);">+       xdr_segs(output, bzp.segs, bzp.num_segments);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       buffer_delete(&tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c</span><br><span>index 91b0290..899e32a 100644</span><br><span>--- a/util/cbfstool/cbfstool.c</span><br><span>+++ b/util/cbfstool/cbfstool.c</span><br><span>@@ -5,6 +5,7 @@</span><br><span>  *                 written by Patrick Georgi <patrick.georgi@coresystems.de></span><br><span>  * Copyright (C) 2012 Google, Inc.</span><br><span>  * Copyright (C) 2016 Siemens AG</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright     2018-present Facebook, Inc.</span><br><span>  *</span><br><span>  * This program is free software; you can redistribute it and/or modify</span><br><span>  * it under the terms of the GNU General Public License as published by</span><br><span>@@ -640,6 +641,11 @@</span><br><span>                 ret = parse_bzImage_to_payload(buffer, &output,</span><br><span>                          param.initrd, param.cmdline, param.compression);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  /* Try ARM64 Image */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ret != 0 && probe_for_ARM64Image_header(buffer))</span><br><span style="color: hsl(120, 100%, 40%);">+          ret = parse_ARM64Image_to_payload(buffer, &output,</span><br><span style="color: hsl(120, 100%, 40%);">+                                param.loadaddress, param.compression);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* Not a supported payload type */</span><br><span>   if (ret != 0) {</span><br><span>              ERROR("Not a supported payload type (ELF / FV).\n");</span><br><span>@@ -1169,7 +1175,7 @@</span><br><span>       {"add", "H:r:f:n:t:c:b:a:p:yvA:gh?", cbfs_add, true, true},</span><br><span>      {"add-flat-binary", "H:r:f:n:l:e:c:b:p:vA:gh?", cbfs_add_flat_binary,</span><br><span>                            true, true},</span><br><span style="color: hsl(0, 100%, 40%);">-    {"add-payload", "H:r:f:n:t:c:b:C:I:p:vA:gh?", cbfs_add_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+   {"add-payload", "H:r:f:n:t:c:b:C:I:p:l:vA:gh?", cbfs_add_payload,</span><br><span>                                true, true},</span><br><span>         {"add-stage", "a:H:r:f:n:t:c:b:P:S:p:yvA:gh?", cbfs_add_stage,</span><br><span>                           true, true},</span><br><span>@@ -1299,7 +1305,8 @@</span><br><span>                         "Add a component\n"</span><br><span>             " add-payload [-r image,regions] -f FILE -n NAME [-A hash] \\\n"</span><br><span>           "        [-c compression] [-b base-address] \\\n"</span><br><span style="color: hsl(0, 100%, 40%);">-             "        (linux specific: [-C cmdline] [-I initrd])           "</span><br><span style="color: hsl(120, 100%, 40%);">+             "        (linux specific: [-C cmdline] [-I initrd]         \\\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "         [-l loadaddress])                                   "</span><br><span>                       "Add a payload to the ROM\n"</span><br><span>            " add-stage [-r image,regions] -f FILE -n NAME [-A hash] \\\n"</span><br><span>             "        [-c compression] [-b base] [-S section-to-ignore] \\\n"</span><br><span>diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h</span><br><span>index 6e366a1..4361191 100644</span><br><span>--- a/util/cbfstool/common.h</span><br><span>+++ b/util/cbfstool/common.h</span><br><span>@@ -193,6 +193,12 @@</span><br><span> int parse_bzImage_to_payload(const struct buffer *input,</span><br><span>                           struct buffer *output, const char *initrd,</span><br><span>                           char *cmdline, enum comp_algo algo);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int probe_for_ARM64Image_header(const struct buffer *input);</span><br><span style="color: hsl(120, 100%, 40%);">+int parse_ARM64Image_to_payload(const struct buffer *input,</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct buffer *output, uint64_t load_address,</span><br><span style="color: hsl(120, 100%, 40%);">+                         enum comp_algo algo);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int parse_flat_binary_to_payload(const struct buffer *input,</span><br><span>                               struct buffer *output,</span><br><span>                               uint32_t loadaddress,</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/23869">change 23869</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/23869"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I9a8183a87de4dc3a4c4f038fe5b4912ada5d75f9 </div>
<div style="display:none"> Gerrit-Change-Number: 23869 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>