Page MenuHomeFreeBSD

D31191.id92231.diff
No OneTemporary

D31191.id92231.diff

Index: sys/conf/Makefile.arm64
===================================================================
--- sys/conf/Makefile.arm64
+++ sys/conf/Makefile.arm64
@@ -23,6 +23,7 @@
.if !defined(S)
S= ../../..
.endif
+.include "src.lua.mk"
.include "$S/conf/kern.pre.mk"
INCLUDES+= -I$S/contrib/libfdt -I$S/contrib/device-tree/include
@@ -74,14 +75,14 @@
# stripped and a custom binary head blob is prepended), saving the
# output in a temp file. We also strip arm "marker" symbols which are
# used only by elf toolchains. Read the symbols from kernel.full and pass
-# them to arm_kernel_boothdr.awk, which generates a binary header blob
+# them to kernel_boothdr.lua, which generates a binary header blob
# that goes on the front of the stripped kernel. Cat the header blob
# and the temp file together to make the kernel.bin file.
${KERNEL_KO}.bin: ${FULLKERNEL}
@${OBJCOPY} --wildcard --strip-symbol='$$[adtx]*' \
--output-target=binary ${.ALLSRC} ${.TARGET}.temp
- @{ readelf -s ${.ALLSRC} | \
- ${AWK} -f $S/tools/arm_kernel_boothdr.awk -v hdrtype=v8booti && \
+ @{
+ ${LUA} $S/tools/kernel_boothdr.lua ${.ALLSRC} v8booti && \
cat ${.TARGET}.temp; \
} > ${.TARGET}
@rm ${.TARGET}.temp
Index: sys/conf/Makefile.riscv
===================================================================
--- sys/conf/Makefile.riscv
+++ sys/conf/Makefile.riscv
@@ -24,6 +24,7 @@
.if !defined(S)
S= ../../..
.endif
+.include "src.lua.mk"
.include "$S/conf/kern.pre.mk"
INCLUDES+= -I$S/contrib/libfdt -I$S/contrib/device-tree/include
@@ -37,6 +38,24 @@
KERNEL_LMA?= 0x80200000
LDFLAGS+= --defsym='kernel_lma=${KERNEL_LMA}'
+# Use a custom SYSTEM_LD command to generate the elf kernel, so we can
+# set the text segment start address, and also strip the "arm mapping
+# symbols" which have names like $a.0 and $d.2; see the document
+# "ELF for the ARM architecture" for more info on the mapping symbols.
+SYSTEM_LD= \
+ ${SYSTEM_LD_BASECMD} \
+ --defsym='text_start=kernbase + SIZEOF_HEADERS' \
+ -o ${.TARGET} ${SYSTEM_OBJS} vers.o; \
+ $(OBJCOPY) \
+ --wildcard \
+ --strip-symbol='$$[adtx]*' \
+ ${.TARGET}
+
+# Generate the .bin (booti images) kernel as an extra build output.
+# The targets and rules to generate these appear near the end of the file.
+KERNEL_EXTRA+= ${KERNEL_KO}.bin
+KERNEL_EXTRA_INSTALL+= ${KERNEL_KO}.bin
+
.if !empty(DDB_ENABLED)
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
.endif
@@ -59,3 +78,21 @@
%RULES
.include "$S/conf/kern.post.mk"
+
+# Create a kernel.bin file...
+# Copy the kernel to u-boot's booti image format (the elf headers are
+# stripped and a custom binary head blob is prepended), saving the
+# output in a temp file. We also strip arm "marker" symbols which are
+# used only by elf toolchains. Read the symbols from kernel.full and pass
+# them to kernel_boothdr.lua, which generates a binary header blob
+# that goes on the front of the stripped kernel. Cat the header blob
+# and the temp file together to make the kernel.bin file.
+${KERNEL_KO}.bin: ${FULLKERNEL}
+ @${OBJCOPY} --wildcard --strip-symbol='$$[adtx]*' \
+ --output-target=binary ${.ALLSRC} ${.TARGET}.temp
+ @{
+ ${LUA} $S/tools/kernel_boothdr.lua ${.ALLSRC} riscvbooti && \
+ cat ${.TARGET}.temp; \
+ } > ${.TARGET}
+ @rm ${.TARGET}.temp
+ @echo "created ${.TARGET} from ${.ALLSRC}"
Index: sys/conf/ldscript.riscv
===================================================================
--- sys/conf/ldscript.riscv
+++ sys/conf/ldscript.riscv
@@ -6,9 +6,9 @@
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = kernbase;
+ . = text_start;
/* The load address kernel_lma is set using --defsym= on the command line. */
- .text : AT(kernel_lma)
+ .text :
{
*(.text)
*(.stub)
Index: sys/tools/arm_kernel_boothdr.awk
===================================================================
--- sys/tools/arm_kernel_boothdr.awk
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/usr/bin/awk -f
-#-
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
-#
-# Copyright 2019 Ian Lepore <ian@freebsd.org>
-#
-# 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. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
-#
-# $FreeBSD$
-
-BEGIN {
- # Init global vars.
- gBytesOut = 0; # How many output bytes we've written so far
- gKernbase = 0; # Address of first byte of loaded kernel image
- gStart = 0; # Address of _start symbol
- gStartOff = 0; # Offset of _start symbol from start of image
- gEnd = 0; # Address of _end symbol
- gEndOff = 0; # Offset of _end symbol from start of image
-
- # The type of header we're writing is set using -v hdrtype= on
- # the command line, ensure we got a valid value for it.
- if (hdrtype != "v7jump" &&
- hdrtype != "v8jump" &&
- hdrtype != "v8booti") {
- print "arm_kernel_boothdr.awk: " \
- "missing or invalid '-v hdrtype=' argument" >"/dev/stderr"
- gHdrType = "error_reported"
- exit 1
- }
-
- gHdrType = hdrtype
-}
-
-function addr_to_offset(addr) {
- # Turn an address into an offset from the start of the loaded image.
- return addr % gKernbase
-}
-
-function hexstr_to_num(str) {
-
- # Prepend a 0x onto the string, then coerce it to a number by doing
- # arithmetic with it, which makes awk run it through strtod(),
- # which handles hex numbers that have a 0x prefix.
-
- return 0 + ("0x" str)
-}
-
-function write_le32(num) {
-
- for (i = 0; i < 4; i++) {
- printf("%c", num % 256);
- num /= 256
- }
- gBytesOut += 4
-}
-
-function write_le64(num) {
-
- for (i = 0; i < 8; i++) {
- printf("%c", num % 256);
- num /= 256
- }
- gBytesOut += 8
-}
-
-function write_padding() {
-
- # Write enough padding bytes so that the header fills all the
- # remaining space before the _start symbol.
-
- while (gBytesOut++ < gStartOff) {
- printf("%c", 0);
- }
-}
-
-function write_v7jump() {
-
- # Write the machine code for "b _start"...
- # 0xea is armv7 "branch always" and the low 24 bits is the signed
- # offset from the current PC, in words. We know the gStart offset
- # is in the first 2mb, so it'll fit in 24 bits.
-
- write_le32(hexstr_to_num("ea000000") + (gStartOff / 4) - 2)
-}
-
-function write_v8jump() {
-
- # Write the machine code for "b _start"...
- # 0x14 is armv8 "branch always" and the low 26 bits is the signed
- # offset from the current PC, in words. We know the gStart offset
- # is in the first 2mb, so it'll fit in 26 bits.
-
- write_le32(hexstr_to_num("14000000") + (gStartOff / 4))
-}
-
-function write_v8booti() {
-
- # We are writing this struct...
- #
- # struct Image_header {
- # uint32_t code0; /* Executable code */
- # uint32_t code1; /* Executable code */
- # uint64_t text_offset; /* Image load offset, LE */
- # uint64_t image_size; /* Effective Image size, LE */
- # uint64_t flags; /* Kernel flags, LE */
- # uint64_t res1[3]; /* reserved */
- # uint32_t magic; /* Magic number */
- # uint32_t res2;
- # };
- #
- # We write 'b _start' into code0. The image size is everything from
- # the start of the loaded image to the offset given by the _end symbol.
-
- write_v8jump() # code0
- write_le32(0) # code1
- write_le64(0) # text_offset
- write_le64(gEndOff) # image_size
- write_le64(0) # flags
- write_le64(0) # res1[0]
- write_le64(0) # res1[1]
- write_le64(0) # res1[2]
- write_le32(hexstr_to_num("644d5241")) # magic (LE "ARMd" (d is 0x64))
- write_le32(0) # res2
-}
-
-/kernbase/ {
- # If the symbol name is exactly "kernbase" save its address.
- if ($8 == "kernbase") {
- gKernbase = hexstr_to_num($2)
- }
-}
-
-/_start/ {
- # If the symbol name is exactly "_start" save its address.
- if ($8 == "_start") {
- gStart = hexstr_to_num($2)
- }
-}
-
-/_end/ {
- # If the symbol name is exactly "_end" remember its value.
- if ($8 == "_end") {
- gEnd = hexstr_to_num($2)
- }
-}
-
-END {
- # Note that this function runs even if BEGIN calls exit(1)!
- if (gHdrType == "error_reported") {
- exit 1
- }
-
- # Make sure we got all three required symbols.
- if (gKernbase == 0 || gStart == 0 || gEnd == 0) {
- print "arm_kernel_boothdr.awk: " \
- "missing kernbase/_start/_end symbol(s)" >"/dev/stderr"
- exit 1
- }
-
- gStartOff = addr_to_offset(gStart)
- gEndOff = addr_to_offset(gEnd)
-
- if (gHdrType == "v7jump") {
- write_v7jump()
- } else if (gHdrType == "v8jump") {
- write_v8jump()
- } else if (gHdrType == "v8booti") {
- write_v8booti()
- }
- write_padding()
-}
Index: sys/tools/kernel_boothdr.lua
===================================================================
--- /dev/null
+++ sys/tools/kernel_boothdr.lua
@@ -0,0 +1,157 @@
+--
+-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+--
+-- Copyright (c) 2021 Conclusive Engineering Sp. z o. o.
+--
+-- 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. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+--
+-- $FreeBSD$
+--
+
+function printf(s, ...)
+ return io.stderr:write(s:format(...))
+end
+
+function write_packed(fmt, ...)
+ io.write(fmt:pack(...))
+ g_written = g_written + fmt:packsize(...)
+end
+
+function read_symbols(kernel)
+ local pipe = io.popen("nm " .. kernel)
+
+ for line in pipe:lines() do
+ address, t, name = line:match("(%x+)%s(%g)%s(%g+)")
+
+ if name == "_start" then
+ g_start = tonumber(address, 16)
+ elseif name == "_end" then
+ g_end = tonumber(address, 16)
+ elseif name == "kernbase" then
+ g_kernbase = tonumber(address, 16)
+ end
+ end
+
+ pipe:close()
+
+ if g_start == nil or g_end == nil or g_kernbase == nil then
+ printf("error: failed to read nm output\n");
+ os.exit(1)
+ end
+end
+
+function addr_to_offset(addr)
+ return math.abs(math.fmod(g_kernbase, addr))
+end
+
+function write_armv7_jump()
+ local insn = 0xea000000 | (g_start_off / 4) - 2
+ write_packed("<I4", insn)
+end
+
+function write_armv8_jump()
+ local insn = 0x14000000 | g_start_off / 4
+ write_packed("<I4", insn)
+end
+
+function write_riscv_jump()
+ local insn = 0x0000006f
+ local imm1912 = (g_start_off >> 12) & 0xff
+ local imm11 = (g_start_off) >> 11 & 0x1
+ local imm1001 = (g_start_off) >> 1 & 0x3ff
+ local imm20 = (g_start_off) >> 20 & 0x1
+
+ write_packed("<I4", insn |
+ (imm1912 << 12) |
+ (imm11 << 20) |
+ (imm1001 << 21) |
+ (imm20 << 31))
+end
+
+function write_armv8_booti()
+ write_armv8_jump() -- code0
+ write_packed("<I4", 0) -- code1
+ write_packed("<I8", 0) -- text_offset
+ write_packed("<I8", g_end_off) -- image_size
+ write_packed("<I8", 0) -- flags
+ write_packed("<I8", 0) -- res1[0]
+ write_packed("<I8", 0) -- res1[1]
+ write_packed("<I8", 0) -- res1[2]
+ write_packed("<c4", "ARM\x64") -- magic
+ write_packed("<I4", 0)
+end
+
+function write_riscv_booti()
+ write_riscv_jump() -- code0
+ write_packed("<I4", 0) -- code1
+ write_packed("<I8", 0) -- text_offset
+ write_packed("<I8", g_end_off) -- image_size
+ write_packed("<I8", 0) -- flags
+ write_packed("<I8", 0) -- res1[0]
+ write_packed("<I8", 0) -- res1[1]
+ write_packed("<I8", 0x5643534952) -- res1[2]
+ write_packed("<c4", "RSC\x05") -- magic
+ write_packed("<I4", 0)
+end
+
+function write_padding()
+ while g_written < g_start_off do
+ write_packed("x")
+ end
+end
+
+if #arg ~= 2 then
+ printf("usage: %s <input file> <v7jump|v8jump|v8booti|riscvbooti>\n", arg[0])
+ os.exit(1)
+end
+
+read_symbols(arg[1])
+g_written = 0
+g_start_off = addr_to_offset(g_start)
+g_end_off = addr_to_offset(g_end)
+
+if arg[2] == "v7jump" then
+ write_armv7_jump()
+ write_padding()
+ return
+end
+
+if arg[2] == "v8jump" then
+ write_armv8_jump()
+ write_padding()
+ return
+end
+
+if arg[2] == "v8booti" then
+ write_armv8_booti()
+ write_padding()
+ return
+end
+
+if arg[2] == "riscvbooti" then
+ write_riscv_booti()
+ write_padding()
+ return
+end
+
+printf("error: unknown action %s\n", arg[2])
+os.exit(1)

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 22, 1:18 AM (5 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27114687
Default Alt Text
D31191.id92231.diff (14 KB)

Event Timeline