From 0d8261b506933c245b79ca6a57422dc81d8989c1 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 22 May 2018 11:53:51 +0200 Subject: [PATCH] pc-bios/s390-ccw/net: Try to load pxelinux.cfg file accoring to the UUID With the STSI instruction, we can get the UUID of the current VM instance, so we can support loading pxelinux config files via UUID in the file name, too. Acked-by: Christian Borntraeger Tested-by: Viktor Mihajlovski Signed-off-by: Thomas Huth --- pc-bios/s390-ccw/netmain.c | 56 +++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c index c059546480..0392131c27 100644 --- a/pc-bios/s390-ccw/netmain.c +++ b/pc-bios/s390-ccw/netmain.c @@ -44,6 +44,9 @@ extern char _start[]; #define KERNEL_MAX_SIZE ((long)_start) #define ARCH_COMMAND_LINE_SIZE 896 /* Taken from Linux kernel */ +/* STSI 3.2.2 offset of first vmdb + offset of uuid inside vmdb */ +#define STSI322_VMDB_UUID_OFFSET ((8 + 12) * 4) + char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE))); IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE))); static char cfgbuf[2048]; @@ -235,6 +238,56 @@ static void net_release(filename_ip_t *fn_ip) } } +/** + * Retrieve the Universally Unique Identifier of the VM. + * @return UUID string, or NULL in case of errors + */ +static const char *get_uuid(void) +{ + register int r0 asm("0"); + register int r1 asm("1"); + uint8_t *mem, *buf, uuid[16]; + int i, cc, chk = 0; + static char uuid_str[37]; + + mem = malloc(2 * PAGE_SIZE); + if (!mem) { + puts("Out of memory ... can not get UUID."); + return NULL; + } + buf = (uint8_t *)(((uint64_t)mem + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); + memset(buf, 0, PAGE_SIZE); + + /* Get SYSIB 3.2.2 */ + r0 = (3 << 28) | 2; + r1 = 2; + asm volatile(" stsi 0(%[addr])\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=d" (cc) + : "d" (r0), "d" (r1), [addr] "a" (buf) + : "cc", "memory"); + if (cc) { + return NULL; + } + + for (i = 0; i < 16; i++) { + uuid[i] = buf[STSI322_VMDB_UUID_OFFSET + i]; + chk |= uuid[i]; + } + free(mem); + if (!chk) { + return NULL; + } + + sprintf(uuid_str, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], + uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); + + return uuid_str; +} + /** * Load a kernel with initrd (i.e. with the information that we've got from * a pxelinux.cfg config file) @@ -285,7 +338,8 @@ static int net_try_pxelinux_cfg(filename_ip_t *fn_ip) struct pl_cfg_entry entries[MAX_PXELINUX_ENTRIES]; int num_ent, def_ent = 0; - num_ent = pxelinux_load_parse_cfg(fn_ip, mac, NULL, DEFAULT_TFTP_RETRIES, + num_ent = pxelinux_load_parse_cfg(fn_ip, mac, get_uuid(), + DEFAULT_TFTP_RETRIES, cfgbuf, sizeof(cfgbuf), entries, MAX_PXELINUX_ENTRIES, &def_ent); if (num_ent > 0) {