Skip to content

Commit

Permalink
powerpc: Add support for adding an ESM blob to the zImage wrapper
Browse files Browse the repository at this point in the history
For secure VMs, the signing tool will create a ticket called the "ESM blob"
for the Enter Secure Mode ultravisor call with the signatures of the kernel
and initrd among other things.

This adds support to the wrapper script for adding that blob via the "-e"
option to the zImage.pseries.

It also adds code to the zImage wrapper itself to retrieve and if necessary
relocate the blob, and pass its address to Linux via the device-tree, to be
later consumed by prom_init.

Signed-off-by: Benjamin Herrenschmidt <[email protected]>
[ bauerman: Minor adjustments to some comments. ]
Signed-off-by: Thiago Jung Bauermann <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
ozbenh authored and mpe committed Aug 29, 2019
1 parent 136bc03 commit 528229d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
41 changes: 41 additions & 0 deletions arch/powerpc/boot/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,46 @@ static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
return (struct addr_range){(void *)initrd_addr, initrd_size};
}

#ifdef __powerpc64__
static void prep_esm_blob(struct addr_range vmlinux, void *chosen)
{
unsigned long esm_blob_addr, esm_blob_size;

/* Do we have an ESM (Enter Secure Mode) blob? */
if (_esm_blob_end <= _esm_blob_start)
return;

printf("Attached ESM blob at 0x%p-0x%p\n\r",
_esm_blob_start, _esm_blob_end);
esm_blob_addr = (unsigned long)_esm_blob_start;
esm_blob_size = _esm_blob_end - _esm_blob_start;

/*
* If the ESM blob is too low it will be clobbered when the
* kernel relocates to its final location. In this case,
* allocate a safer place and move it.
*/
if (esm_blob_addr < vmlinux.size) {
void *old_addr = (void *)esm_blob_addr;

printf("Allocating 0x%lx bytes for esm_blob ...\n\r",
esm_blob_size);
esm_blob_addr = (unsigned long)malloc(esm_blob_size);
if (!esm_blob_addr)
fatal("Can't allocate memory for ESM blob !\n\r");
printf("Relocating ESM blob 0x%lx <- 0x%p (0x%lx bytes)\n\r",
esm_blob_addr, old_addr, esm_blob_size);
memmove((void *)esm_blob_addr, old_addr, esm_blob_size);
}

/* Tell the kernel ESM blob address via device tree. */
setprop_val(chosen, "linux,esm-blob-start", (u32)(esm_blob_addr));
setprop_val(chosen, "linux,esm-blob-end", (u32)(esm_blob_addr + esm_blob_size));
}
#else
static inline void prep_esm_blob(struct addr_range vmlinux, void *chosen) { }
#endif

/* A buffer that may be edited by tools operating on a zImage binary so as to
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
* The buffer is put in it's own section so that tools may locate it easier.
Expand Down Expand Up @@ -214,6 +254,7 @@ void start(void)
vmlinux = prep_kernel();
initrd = prep_initrd(vmlinux, chosen,
loader_info.initrd_addr, loader_info.initrd_size);
prep_esm_blob(vmlinux, chosen);
prep_cmdline(chosen);

printf("Finalizing device tree...");
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/boot/ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ extern char _initrd_start[];
extern char _initrd_end[];
extern char _dtb_start[];
extern char _dtb_end[];
extern char _esm_blob_start[];
extern char _esm_blob_end[];

static inline __attribute__((const))
int __ilog2_u32(u32 n)
Expand Down
24 changes: 21 additions & 3 deletions arch/powerpc/boot/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# -i initrd specify initrd file
# -d devtree specify device-tree blob
# -s tree.dts specify device-tree source file (needs dtc installed)
# -e esm_blob specify ESM blob for secure images
# -c cache $kernel.strip.gz (use if present & newer, else make)
# -C prefix specify command prefix for cross-building tools
# (strip, objcopy, ld)
Expand All @@ -37,6 +38,7 @@ platform=of
initrd=
dtb=
dts=
esm_blob=
cacheit=
binary=
compression=.gz
Expand All @@ -60,9 +62,9 @@ tmpdir=.

usage() {
echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2
echo ' [-D datadir] [-W workingdir] [-Z (gz|xz|none)]' >&2
echo ' [--no-compression] [vmlinux]' >&2
echo ' [-d devtree] [-s tree.dts] [-e esm_blob]' >&2
echo ' [-c] [-C cross-prefix] [-D datadir] [-W workingdir]' >&2
echo ' [-Z (gz|xz|none)] [--no-compression] [vmlinux]' >&2
exit 1
}

Expand Down Expand Up @@ -105,6 +107,11 @@ while [ "$#" -gt 0 ]; do
[ "$#" -gt 0 ] || usage
dtb="$1"
;;
-e)
shift
[ "$#" -gt 0 ] || usage
esm_blob="$1"
;;
-s)
shift
[ "$#" -gt 0 ] || usage
Expand Down Expand Up @@ -218,9 +225,16 @@ objflags=-S
tmp=$tmpdir/zImage.$$.o
ksection=.kernel:vmlinux.strip
isection=.kernel:initrd
esection=.kernel:esm_blob
link_address='0x400000'
make_space=y


if [ -n "$esm_blob" -a "$platform" != "pseries" ]; then
echo "ESM blob not support on non-pseries platforms" >&2
exit 1
fi

case "$platform" in
of)
platformo="$object/of.o $object/epapr.o"
Expand Down Expand Up @@ -477,6 +491,10 @@ if [ -n "$dtb" ]; then
fi
fi

if [ -n "$esm_blob" ]; then
addsec $tmp "$esm_blob" $esection
fi

if [ "$platform" != "miboot" ]; then
if [ -n "$link_address" ] ; then
text_start="-Ttext $link_address"
Expand Down
8 changes: 8 additions & 0 deletions arch/powerpc/boot/zImage.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ SECTIONS
_initrd_end = .;
}

. = ALIGN(4096);
.kernel:esm_blob :
{
_esm_blob_start = .;
*(.kernel:esm_blob)
_esm_blob_end = .;
}

#ifdef CONFIG_PPC64_BOOT_WRAPPER
. = ALIGN(256);
.got :
Expand Down

0 comments on commit 528229d

Please sign in to comment.