From cb09b5033de1b1efa3d8728d8ed0cf88e5f7a078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:54:04 -0300 Subject: [PATCH] feat(genesis): report IBM Z identity --- .../files/xcat-genesis-console/src/console.h | 1 + .../files/xcat-genesis-console/src/state.c | 35 ++++++++++++- .../files/xcat-genesis-console/src/support.c | 36 +++++++++++++ .../files/genesis-discover | 51 +++++++++++++++++-- 4 files changed, 117 insertions(+), 6 deletions(-) diff --git a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/console.h b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/console.h index 80987474d..8a9624448 100644 --- a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/console.h +++ b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/console.h @@ -107,6 +107,7 @@ void xcat_set_text(char *destination, size_t size, const char *format, ...); char *xcat_read_allocated_line(const char *path); bool xcat_read_line(const char *path, char *value, size_t size); bool xcat_read_key(const char *path, const char *key, char *value, size_t size); +bool xcat_read_colon_key(const char *path, const char *key, char *value, size_t size); bool xcat_safe_name(const char *value); bool xcat_cmdline_value(const char *cmdline, const char *key, char *value, size_t size); unsigned long long xcat_read_uptime(void); diff --git a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/state.c b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/state.c index 231495ebc..d9a8cdcd3 100644 --- a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/state.c +++ b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/state.c @@ -201,6 +201,8 @@ static void set_boot_loader(const char *cmdline, char *loader, size_t size) { xcat_set_text(loader, size, "PXELINUX"); else if (strcmp(value, "elilo") == 0) xcat_set_text(loader, size, "ELILO"); + else if (strcmp(value, "s390-ccw") == 0) + xcat_set_text(loader, size, "QEMU TFTP loader"); else xcat_set_text(loader, size, "unrecognized"); } else if (xcat_cmdline_value(cmdline, "BOOTIF", value, sizeof(value))) { @@ -216,6 +218,15 @@ static bool useful_identity(const char *value) { strcmp(value, "unknown") != 0; } +static void set_s390_identity(const char *proc_root, struct console_state *state) { + char path[VALUE_SIZE * 2]; + + snprintf(path, sizeof(path), "%s/sysinfo", proc_root); + if (!useful_identity(state->uuid) && + !xcat_read_colon_key(path, "VM00 UUID", state->uuid, sizeof(state->uuid))) + xcat_read_colon_key(path, "LPAR UUID", state->uuid, sizeof(state->uuid)); +} + static void split_action(const char *destiny, char *action, size_t action_size, char *target, size_t target_size) { const char *separator = strchr(destiny, '='); @@ -291,8 +302,12 @@ void xcat_load_console_state(struct console_state *state) { char path[VALUE_SIZE * 2]; char release_name[64] = "xCAT Genesis"; char release_version[32] = ""; +#ifdef XCAT_CONSOLE_TEST + const char *test_architecture = getenv("XCAT_TEST_ARCH"); +#endif bool xcat_configured; bool interface_selected; + bool s390_ccw_boot; memset(state, 0, sizeof(*state)); xcat_configured = xcat_cmdline_value(cmdline_text, "xcatd", state->xcat_endpoint, @@ -332,6 +347,16 @@ void xcat_load_console_state(struct console_state *state) { xcat_set_text(state->architecture, sizeof(state->architecture), "unknown"); xcat_set_text(state->kernel, sizeof(state->kernel), "unknown"); } +#ifdef XCAT_CONSOLE_TEST + if (test_architecture != NULL) + xcat_set_text(state->architecture, sizeof(state->architecture), "%s", + test_architecture); +#endif + + s390_ccw_boot = strcmp(state->architecture, "s390x") == 0 && + xcat_cmdline_value(cmdline_text, "xcat.bootloader", value, + sizeof(value)) && + strcmp(value, "s390-ccw") == 0; snprintf(path, sizeof(path), "%s/firmware/efi", sys_root); if (strncmp(state->architecture, "ppc64", 5) == 0) { @@ -345,6 +370,9 @@ void xcat_load_console_state(struct console_state *state) { access(path, F_OK) == 0 ? "UEFI" : "Device Tree"); } else if (strncmp(state->architecture, "riscv", 5) == 0) { xcat_set_text(state->firmware, sizeof(state->firmware), "OpenSBI"); + } else if (strcmp(state->architecture, "s390x") == 0) { + xcat_set_text(state->firmware, sizeof(state->firmware), "%s", + s390_ccw_boot ? "s390-ccw BIOS" : "not reported"); } else { snprintf(path, sizeof(path), "%s/firmware/efi", sys_root); xcat_set_text(state->firmware, sizeof(state->firmware), "%s", @@ -365,7 +393,12 @@ void xcat_load_console_state(struct console_state *state) { if (!useful_identity(state->serial)) xcat_set_text(state->serial, sizeof(state->serial), "not reported"); snprintf(path, sizeof(path), "%s/class/dmi/id/product_uuid", sys_root); - if (!xcat_read_line(path, state->uuid, sizeof(state->uuid)) || !useful_identity(state->uuid)) + xcat_read_line(path, state->uuid, sizeof(state->uuid)); + if (strcmp(state->architecture, "s390x") == 0) { + xcat_set_text(state->serial, sizeof(state->serial), "not reported"); + set_s390_identity(proc_root, state); + } + if (!useful_identity(state->uuid)) xcat_set_text(state->uuid, sizeof(state->uuid), "not reported"); interface_selected = diff --git a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/support.c b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/support.c index 5890b7cbd..5a710b435 100644 --- a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/support.c +++ b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-core/xcat-genesis-console/files/xcat-genesis-console/src/support.c @@ -123,6 +123,42 @@ bool xcat_read_key(const char *path, const char *key, char *value, size_t size) return found; } +bool xcat_read_colon_key(const char *path, const char *key, char *value, size_t size) { + FILE *stream; + char *line = NULL; + size_t capacity = 0; + size_t key_length = strlen(key); + bool found = false; + + if (key_length == 0 || size == 0) + return false; + stream = fopen(path, "r"); + if (stream == NULL) + return false; + while (getline(&line, &capacity, stream) >= 0) { + char *start; + char *end; + size_t line_length = strlen(line); + + if (line_length <= key_length || strncmp(line, key, key_length) != 0 || + line[key_length] != ':') + continue; + start = line + key_length + 1; + while (isspace((unsigned char)*start)) + start++; + end = start + strlen(start); + while (end > start && isspace((unsigned char)end[-1])) + end--; + *end = '\0'; + xcat_copy_printable(value, size, start); + found = true; + break; + } + free(line); + fclose(stream); + return found; +} + bool xcat_safe_name(const char *value) { const unsigned char *cursor = (const unsigned char *)value; diff --git a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-xcat/xcat-genesis-discovery/files/genesis-discover b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-xcat/xcat-genesis-discovery/files/genesis-discover index 9140cd99a..8346b4c06 100755 --- a/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-xcat/xcat-genesis-discovery/files/genesis-discover +++ b/xCAT-genesis-builder/oe/meta-xcat-genesis/recipes-xcat/xcat-genesis-discovery/files/genesis-discover @@ -73,6 +73,14 @@ read_value() { tr -d '\000\r\n' <"$value_file" | head -c 512 } +read_sysinfo_value() { + local name=$1 + + awk -F ':' -v name="$name" \ + '$1 == name {sub(/^[[:space:]]+/, "", $2); sub(/[[:space:]]+$/, "", $2); print $2; exit}' \ + "$proc_root/sysinfo" 2>/dev/null || true +} + send_packet() { if [[ -n ${XCAT_DISCOVERY_SEND_COMMAND:-} ]]; then "$XCAT_DISCOVERY_SEND_COMMAND" "$compressed_packet" "$XCATMASTER" "$XCATPORT" @@ -125,12 +133,29 @@ system_vendor=$(read_value "$sys_root/sys/devices/virtual/dmi/id/sys_vendor" || serial=$(read_value "$sys_root/sys/devices/virtual/dmi/id/product_serial" || true) uuid=$(read_value "$sys_root/sys/devices/virtual/dmi/id/product_uuid" || true) machine_type= +s390_virtual= [[ -z $system_vendor && -z $product_name ]] \ || machine_type=${system_vendor:+$system_vendor:}$product_name platform=$(awk -F ':' \ '/^platform[[:space:]]*:/ {sub(/^[[:space:]]+/, "", $2); print $2; exit}' \ "$proc_root/cpuinfo" 2>/dev/null || true) -if [[ -z $product_name ]]; then +if [[ $architecture == s390x ]]; then + system_vendor=$(read_sysinfo_value Manufacturer) + product_type=$(read_sysinfo_value Type) + product_model=$(read_sysinfo_value Model) + product_model=${product_model##* } + product_name=${product_type}${product_model:+-$product_model} + machine_type=$product_name + serial= + uuid=$(read_sysinfo_value 'VM00 UUID') + [[ -n $uuid ]] || uuid=$(read_sysinfo_value 'LPAR UUID') + platform=$(read_sysinfo_value 'VM00 Control Program') + if [[ -n $platform ]]; then + s390_virtual=1 + else + platform=LPAR + fi +elif [[ -z $product_name ]]; then product_name=$(read_value "$proc_root/device-tree/model" || true) [[ -n $product_name ]] \ || product_name=$(read_value \ @@ -148,12 +173,28 @@ node_type= case "$system_vendor $product_name" in *KVM*|*QEMU*|*VMware*|*VirtualBox*|*Bochs*|*Hyper-V*) node_type=virtual ;; esac +[[ -z $s390_virtual ]] || node_type=virtual -cpu_count=$(awk '/^(processor|cpu)[[:space:]]*:/ {count++} END {print count + 0}' \ +cpu_count=$(awk ' + /^processor([[:space:]]+[0-9]+)?[[:space:]]*:/ {processors++} + /^cpu[[:space:]]*:/ {cpus++} + END {print (processors > 0 ? processors : cpus + 0)}' \ "$proc_root/cpuinfo" 2>/dev/null || printf '0') -cpu_type=$(awk -F ':' \ - '/^(model name|cpu)[[:space:]]*:/ {sub(/^[[:space:]]+/, "", $2); print $2; exit}' \ - "$proc_root/cpuinfo" 2>/dev/null || true) +cpu_type=$(awk -F ':' ' + /^model name[[:space:]]*:/ && model == "" { + sub(/^[[:space:]]+/, "", $2); model = $2 + } + /^cpu[[:space:]]*:/ && cpu == "" { + sub(/^[[:space:]]+/, "", $2); cpu = $2 + } + /^vendor_id[[:space:]]*:/ && vendor == "" { + sub(/^[[:space:]]+/, "", $2); vendor = $2 + } + END { + if (model != "") print model + else if (cpu != "") print cpu + else if (vendor != "") print vendor + }' "$proc_root/cpuinfo" 2>/dev/null || true) memory=$(awk '/^MemTotal:/ {printf "%.0fMB", $2 / 1024; exit}' \ "$proc_root/meminfo" 2>/dev/null || true) disk_size=$(lsblk -b -dn -o NAME,SIZE,TYPE 2>/dev/null \