From 6320ffa20b232acee0914914f6bc0746622f4acb245fd6c2b4f70219a757c775 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Thu, 4 Jan 2024 16:53:48 +0000 Subject: [PATCH] Accepting request 1136886 from home:michals - Add support for new rtas kernel interface for VPD and sysparm (jsc#PED-4541). * 0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch * 0002-librtas-move-VPD-code-into-separate-module.patch * 0003-librtas-move-system-parameter-code-to-separate-modul.patch * 0004-librtas-vendor-papr-miscdev.h.patch * 0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch * 0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch * link-lpthread.patch * tests: activate-firmware-regress vpdupdate-regress OBS-URL: https://build.opensuse.org/request/show/1136886 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/librtas?expand=0&rev=67 --- ...-low-level-RTAS-call-APIs-internally.patch | 79 +++++ ...s-move-VPD-code-into-separate-module.patch | 197 ++++++++++++ ...tem-parameter-code-to-separate-modul.patch | 230 ++++++++++++++ 0004-librtas-vendor-papr-miscdev.h.patch | 48 +++ ...d-prefer-dev-papr-vpd-when-available.patch | 279 +++++++++++++++++ ...prefer-dev-papr-sysparm-when-availab.patch | 286 ++++++++++++++++++ activate-firmware-regress | 118 ++++++++ librtas-doc.spec | 12 +- librtas.changes | 13 + librtas.spec | 16 +- link-lpthread.patch | 15 + vpdupdate-regress | 145 +++++++++ 12 files changed, 1435 insertions(+), 3 deletions(-) create mode 100644 0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch create mode 100644 0002-librtas-move-VPD-code-into-separate-module.patch create mode 100644 0003-librtas-move-system-parameter-code-to-separate-modul.patch create mode 100644 0004-librtas-vendor-papr-miscdev.h.patch create mode 100644 0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch create mode 100644 0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch create mode 100644 activate-firmware-regress create mode 100644 link-lpthread.patch create mode 100644 vpdupdate-regress diff --git a/0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch b/0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch new file mode 100644 index 0000000..920e918 --- /dev/null +++ b/0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch @@ -0,0 +1,79 @@ +From 0d48bdca32cbf7a83bcaa5a27e3454d24055e0cb Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Sat, 12 Aug 2023 12:41:36 -0500 +Subject: [PATCH 1/6] librtas: expose low-level RTAS call APIs internally + +Make these functions available outside of syscall_calls.c, marking +them hidden so that they aren't exposed in the library ABI. + +The implementations of librtas APIs will move into separate C files as +they gain support for new interfaces offered by the kernel. + +Signed-off-by: Nathan Lynch +--- + librtas_src/internal.h | 5 +++++ + librtas_src/syscall_calls.c | 11 ++++++----- + 2 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/librtas_src/internal.h b/librtas_src/internal.h +index 3b6ba88..97411d3 100644 +--- a/librtas_src/internal.h ++++ b/librtas_src/internal.h +@@ -52,6 +52,11 @@ int read_entire_file(int fd, char **buf, size_t *len); + int rtas_token(const char *call_name); + int sanity_check(void); + ++#define CALL_AGAIN 1 ++unsigned int handle_delay(int status, uint64_t * elapsed); ++int rtas_call_no_delay(const char *name, int ninputs, int nrets, ...); ++int rtas_call(const char *name, int ninputs, int nrets, ...); ++ + #define BITS32_LO(_num) (uint32_t) (_num & 0xffffffffll) + #define BITS32_HI(_num) (uint32_t) (_num >> 32) + #define BITS64(_high, _low) (uint64_t) (((uint64_t) _high << 32) | _low) +diff --git a/librtas_src/syscall_calls.c b/librtas_src/syscall_calls.c +index 1e09217..eabc5ea 100644 +--- a/librtas_src/syscall_calls.c ++++ b/librtas_src/syscall_calls.c +@@ -32,8 +32,6 @@ + #include "internal.h" + #include "librtas.h" + +-#define CALL_AGAIN 1 +- + int dbg_lvl = 0; + static uint64_t rtas_timeout_ms; + +@@ -65,7 +63,8 @@ int sanity_check(void) + * CALL_AGAIN if the status is delay related + * RTAS_TIMEOUT if the requested timeout has been exceeded + */ +-static unsigned int handle_delay(int status, uint64_t * elapsed) ++__attribute__((visibility("hidden"))) ++unsigned int handle_delay(int status, uint64_t * elapsed) + { + int order = status - EXTENDED_DELAY_MIN; + unsigned long ms = 0; +@@ -213,7 +212,8 @@ static int _rtas_call(int delay_handling, int token, int ninputs, + return 0; + } + +-static int rtas_call_no_delay(const char *name, int ninputs, int nrets, ...) ++__attribute__((visibility("hidden"))) ++int rtas_call_no_delay(const char *name, int ninputs, int nrets, ...) + { + va_list ap; + int rc, token; +@@ -229,7 +229,8 @@ static int rtas_call_no_delay(const char *name, int ninputs, int nrets, ...) + return rc; + } + +-static int rtas_call(const char *name, int ninputs, int nrets, ...) ++__attribute__((visibility("hidden"))) ++int rtas_call(const char *name, int ninputs, int nrets, ...) + { + va_list ap; + int rc, token; +-- +2.42.0 + diff --git a/0002-librtas-move-VPD-code-into-separate-module.patch b/0002-librtas-move-VPD-code-into-separate-module.patch new file mode 100644 index 0000000..fb16937 --- /dev/null +++ b/0002-librtas-move-VPD-code-into-separate-module.patch @@ -0,0 +1,197 @@ +From 12a2764fd7efe7c52b53579a67edb641d662f54f Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Sat, 12 Aug 2023 12:44:38 -0500 +Subject: [PATCH 2/6] librtas: move VPD code into separate module + +This code will gain the ability to retrieve VPD using a different +interface exposed by newer kernels. This will be a lot of additional +code, so move it out of syscall_calls.c. + +Signed-off-by: Nathan Lynch +--- + Makefile.am | 1 + + librtas_src/syscall_calls.c | 67 ------------------------------ + librtas_src/vpd.c | 81 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 82 insertions(+), 67 deletions(-) + create mode 100644 librtas_src/vpd.c + +diff --git a/Makefile.am b/Makefile.am +index c4bf09d..37df243 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -28,6 +28,7 @@ LIBRTAS_LIBRARY_VERSION = $(LIBRTAS_CURRENT):$(LIBRTAS_REVISION):$(LIBRTAS_AGE) + lib_LTLIBRARIES += librtas.la + librtas_la_LDFLAGS = -version-info $(LIBRTAS_LIBRARY_VERSION) + librtas_la_SOURCES = \ ++ librtas_src/vpd.c \ + librtas_src/ofdt.c \ + librtas_src/syscall_calls.c \ + librtas_src/syscall_rmo.c +diff --git a/librtas_src/syscall_calls.c b/librtas_src/syscall_calls.c +index eabc5ea..05f3c7c 100644 +--- a/librtas_src/syscall_calls.c ++++ b/librtas_src/syscall_calls.c +@@ -753,73 +753,6 @@ int rtas_get_time(uint32_t *year, uint32_t *month, uint32_t *day, + return rc ? rc : status; + } + +-/** +- * rtas_get_vpd +- * @brief Interface to the ibm,get-vpd rtas call +- * +- * @param loc_code location code +- * @param workarea additional args to rtas call +- * @param size +- * @param sequence +- * @param seq_next +- * @param bytes_ret +- * @return 0 on success, !0 otherwise +- */ +-int rtas_get_vpd(char *loc_code, char *workarea, size_t size, +- unsigned int sequence, unsigned int *seq_next, +- unsigned int *bytes_ret) +-{ +- uint32_t kernbuf_pa; +- uint32_t loc_pa = 0; +- uint32_t rmo_pa = 0; +- uint64_t elapsed = 0; +- void *kernbuf; +- void *rmobuf; +- void *locbuf; +- int rc, status; +- +- rc = sanity_check(); +- if (rc) +- return rc; +- +- rc = rtas_get_rmo_buffer(size + WORK_AREA_SIZE, &rmobuf, &rmo_pa); +- if (rc) +- return rc; +- +- kernbuf = rmobuf + WORK_AREA_SIZE; +- kernbuf_pa = rmo_pa + WORK_AREA_SIZE; +- locbuf = rmobuf; +- loc_pa = rmo_pa; +- +- /* If user didn't set loc_code, copy a NULL string */ +- strncpy(locbuf, loc_code ? loc_code : "", WORK_AREA_SIZE); +- +- *seq_next = htobe32(sequence); +- do { +- sequence = *seq_next; +- rc = rtas_call_no_delay("ibm,get-vpd", 4, 3, htobe32(loc_pa), +- htobe32(kernbuf_pa), htobe32(size), +- sequence, &status, seq_next, +- bytes_ret); +- if (rc < 0) +- break; +- +- rc = handle_delay(status, &elapsed); +- } while (rc == CALL_AGAIN); +- +- if (rc == 0) +- memcpy(workarea, kernbuf, size); +- +- (void) rtas_free_rmo_buffer(rmobuf, rmo_pa, size + WORK_AREA_SIZE); +- +- *seq_next = be32toh(*seq_next); +- *bytes_ret = be32toh(*bytes_ret); +- +- dbg("(%s, 0x%p, %zu, %u) = %d, %u, %u\n", loc_code ? loc_code : "NULL", +- workarea, size, sequence, status, *seq_next, *bytes_ret); +- return rc ? rc : status; +-} +- + /** + * rtas_lpar_perftools + * @brief Interface to the ibm,lpar-perftools rtas call +diff --git a/librtas_src/vpd.c b/librtas_src/vpd.c +new file mode 100644 +index 0000000..b2689fb +--- /dev/null ++++ b/librtas_src/vpd.c +@@ -0,0 +1,81 @@ ++// SPDX-License-Identifier: LGPL-2.1-or-later ++ ++// Support for accessing IBM Power systems Vital Product Data (VPD) ++// via the rtas() syscall. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "internal.h" ++#include "librtas.h" ++ ++/** ++ * rtas_get_vpd ++ * @brief Interface to the ibm,get-vpd rtas call ++ * ++ * @param loc_code location code ++ * @param workarea additional args to rtas call ++ * @param size ++ * @param sequence ++ * @param seq_next ++ * @param bytes_ret ++ * @return 0 on success, !0 otherwise ++ */ ++int rtas_get_vpd(char *loc_code, char *workarea, size_t size, ++ unsigned int sequence, unsigned int *seq_next, ++ unsigned int *bytes_ret) ++{ ++ uint32_t kernbuf_pa; ++ uint32_t loc_pa = 0; ++ uint32_t rmo_pa = 0; ++ uint64_t elapsed = 0; ++ void *kernbuf; ++ void *rmobuf; ++ void *locbuf; ++ int rc, status; ++ ++ rc = sanity_check(); ++ if (rc) ++ return rc; ++ ++ rc = rtas_get_rmo_buffer(size + WORK_AREA_SIZE, &rmobuf, &rmo_pa); ++ if (rc) ++ return rc; ++ ++ kernbuf = rmobuf + WORK_AREA_SIZE; ++ kernbuf_pa = rmo_pa + WORK_AREA_SIZE; ++ locbuf = rmobuf; ++ loc_pa = rmo_pa; ++ ++ /* If user didn't set loc_code, copy a NULL string */ ++ strncpy(locbuf, loc_code ? loc_code : "", WORK_AREA_SIZE); ++ ++ *seq_next = htobe32(sequence); ++ do { ++ sequence = *seq_next; ++ rc = rtas_call_no_delay("ibm,get-vpd", 4, 3, htobe32(loc_pa), ++ htobe32(kernbuf_pa), htobe32(size), ++ sequence, &status, seq_next, ++ bytes_ret); ++ if (rc < 0) ++ break; ++ ++ rc = handle_delay(status, &elapsed); ++ } while (rc == CALL_AGAIN); ++ ++ if (rc == 0) ++ memcpy(workarea, kernbuf, size); ++ ++ (void) rtas_free_rmo_buffer(rmobuf, rmo_pa, size + WORK_AREA_SIZE); ++ ++ *seq_next = be32toh(*seq_next); ++ *bytes_ret = be32toh(*bytes_ret); ++ ++ dbg("(%s, 0x%p, %zu, %u) = %d, %u, %u\n", loc_code ? loc_code : "NULL", ++ workarea, size, sequence, status, *seq_next, *bytes_ret); ++ return rc ? rc : status; ++} +-- +2.42.0 + diff --git a/0003-librtas-move-system-parameter-code-to-separate-modul.patch b/0003-librtas-move-system-parameter-code-to-separate-modul.patch new file mode 100644 index 0000000..30b2da6 --- /dev/null +++ b/0003-librtas-move-system-parameter-code-to-separate-modul.patch @@ -0,0 +1,230 @@ +From 80dfb541257cb88519855543324478cbb0f1f1b3 Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Mon, 25 Sep 2023 11:32:33 -0500 +Subject: [PATCH 3/6] librtas: move system parameter code to separate module + +This code will gain the ability to access system parameters using a +different interface exposed by newer kernels. This will involve adding +a nontrivial amount of code, so move it out of syscall_calls.c. + +Signed-off-by: Nathan Lynch +--- + Makefile.am | 3 +- + librtas_src/syscall_calls.c | 84 ----------------------------------- + librtas_src/sysparm.c | 88 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 90 insertions(+), 85 deletions(-) + create mode 100644 librtas_src/sysparm.c + +diff --git a/Makefile.am b/Makefile.am +index 37df243..1385ac7 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -31,7 +31,8 @@ librtas_la_SOURCES = \ + librtas_src/vpd.c \ + librtas_src/ofdt.c \ + librtas_src/syscall_calls.c \ +- librtas_src/syscall_rmo.c ++ librtas_src/syscall_rmo.c \ ++ librtas_src/sysparm.c + + library_include_HEADERS += librtas_src/librtas.h + noinst_HEADERS += librtas_src/internal.h +diff --git a/librtas_src/syscall_calls.c b/librtas_src/syscall_calls.c +index 05f3c7c..b28af2d 100644 +--- a/librtas_src/syscall_calls.c ++++ b/librtas_src/syscall_calls.c +@@ -674,44 +674,6 @@ int rtas_get_sensor(int sensor, int index, int *state) + return rc ? rc : status; + } + +-/** +- * rtas_get_sysparm +- * @brief Interface to the ibm,get-system-parameter rtas call +- * +- * On successful completion the data parameter will contain the system +- * parameter results +- * +- * @param parameter system parameter to retrieve +- * @param length data buffer length +- * @param data reference to buffer to return parameter in +- * @return 0 on success, !0 otherwise +- */ +-int rtas_get_sysparm(unsigned int parameter, unsigned int length, char *data) +-{ +- uint32_t kernbuf_pa; +- void *kernbuf; +- int rc, status; +- +- rc = sanity_check(); +- if (rc) +- return rc; +- +- rc = rtas_get_rmo_buffer(length, &kernbuf, &kernbuf_pa); +- if (rc) +- return rc; +- +- rc = rtas_call("ibm,get-system-parameter", 3, 1, htobe32(parameter), +- htobe32(kernbuf_pa), htobe32(length), &status); +- +- if (rc == 0) +- memcpy(data, kernbuf, length); +- +- (void)rtas_free_rmo_buffer(kernbuf, kernbuf_pa, length); +- +- dbg("(%u, %u, %p) = %d\n", parameter, length, data, rc ? rc : status); +- return rc ? rc : status; +-} +- + /** + * rtas_get_time + * @brief Interface to get-time-of-day rtas call +@@ -1109,52 +1071,6 @@ int rtas_set_poweron_time(uint32_t year, uint32_t month, uint32_t day, + return rc ? rc : status; + } + +-/** +- * rtas_set_sysparm +- * @brief Interface to the ibm,set-system-parameter rtas call +- * +- * @param parameter +- * @param data +- * @return 0 on success, !0 otherwise +- */ +-int rtas_set_sysparm(unsigned int parameter, char *data) +-{ +- uint32_t kernbuf_pa; +- void *kernbuf; +- int rc, status; +- uint16_t size; +- +- rc = sanity_check(); +- if (rc) +- return rc; +- /* +- * We have to copy the contents of @data to a RMO buffer. The +- * caller has encoded the data length in the first two bytes +- * of @data in MSB order, and we can't assume any +- * alignment. So interpret @data as: +- * +- * struct { +- * unsigned char len_msb; +- * unsigned char len_lsb; +- * char [(len_msb << 8) + len_lsb]; +- * } +- */ +- size = 2 + (((unsigned char)data[0] << 8) | (unsigned char)data[1]); +- rc = rtas_get_rmo_buffer(size, &kernbuf, &kernbuf_pa); +- if (rc) +- return rc; +- +- memcpy(kernbuf, data, size); +- +- rc = rtas_call("ibm,set-system-parameter", 2, 1, htobe32(parameter), +- htobe32(kernbuf_pa), &status); +- +- (void)rtas_free_rmo_buffer(kernbuf, kernbuf_pa, size); +- +- dbg("(%u, %p) = %d\n", parameter, data, rc ? rc : status); +- return rc ? rc : status; +-} +- + /** + * rtas_set_time + * @brief Interface to the set-time-of-day rtas call +diff --git a/librtas_src/sysparm.c b/librtas_src/sysparm.c +new file mode 100644 +index 0000000..40af55e +--- /dev/null ++++ b/librtas_src/sysparm.c +@@ -0,0 +1,88 @@ ++#include ++#include ++#include "internal.h" ++#include "librtas.h" ++ ++/** ++ * rtas_get_sysparm ++ * @brief Interface to the ibm,get-system-parameter rtas call ++ * ++ * On successful completion the data parameter will contain the system ++ * parameter results ++ * ++ * @param parameter system parameter to retrieve ++ * @param length data buffer length ++ * @param data reference to buffer to return parameter in ++ * @return 0 on success, !0 otherwise ++ */ ++int rtas_get_sysparm(unsigned int parameter, unsigned int length, char *data) ++{ ++ uint32_t kernbuf_pa; ++ void *kernbuf; ++ int rc, status; ++ ++ rc = sanity_check(); ++ if (rc) ++ return rc; ++ ++ rc = rtas_get_rmo_buffer(length, &kernbuf, &kernbuf_pa); ++ if (rc) ++ return rc; ++ ++ rc = rtas_call("ibm,get-system-parameter", 3, 1, htobe32(parameter), ++ htobe32(kernbuf_pa), htobe32(length), &status); ++ ++ if (rc == 0) ++ memcpy(data, kernbuf, length); ++ ++ (void)rtas_free_rmo_buffer(kernbuf, kernbuf_pa, length); ++ ++ dbg("(%u, %u, %p) = %d\n", parameter, length, data, rc ? rc : status); ++ return rc ? rc : status; ++} ++ ++/** ++ * rtas_set_sysparm ++ * @brief Interface to the ibm,set-system-parameter rtas call ++ * ++ * @param parameter ++ * @param data ++ * @return 0 on success, !0 otherwise ++ */ ++int rtas_set_sysparm(unsigned int parameter, char *data) ++{ ++ uint32_t kernbuf_pa; ++ void *kernbuf; ++ int rc, status; ++ uint16_t size; ++ ++ rc = sanity_check(); ++ if (rc) ++ return rc; ++ /* ++ * We have to copy the contents of @data to a RMO buffer. The ++ * caller has encoded the data length in the first two bytes ++ * of @data in MSB order, and we can't assume any ++ * alignment. So interpret @data as: ++ * ++ * struct { ++ * unsigned char len_msb; ++ * unsigned char len_lsb; ++ * char [(len_msb << 8) + len_lsb]; ++ * } ++ */ ++ size = 2 + (((unsigned char)data[0] << 8) | (unsigned char)data[1]); ++ rc = rtas_get_rmo_buffer(size, &kernbuf, &kernbuf_pa); ++ if (rc) ++ return rc; ++ ++ memcpy(kernbuf, data, size); ++ ++ rc = rtas_call("ibm,set-system-parameter", 2, 1, htobe32(parameter), ++ htobe32(kernbuf_pa), &status); ++ ++ (void)rtas_free_rmo_buffer(kernbuf, kernbuf_pa, size); ++ ++ dbg("(%u, %p) = %d\n", parameter, data, rc ? rc : status); ++ return rc ? rc : status; ++} +-- +2.42.0 + diff --git a/0004-librtas-vendor-papr-miscdev.h.patch b/0004-librtas-vendor-papr-miscdev.h.patch new file mode 100644 index 0000000..916d277 --- /dev/null +++ b/0004-librtas-vendor-papr-miscdev.h.patch @@ -0,0 +1,48 @@ +From ba86b513cbed32f5cdf8840b727457688a0737fb Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Mon, 25 Sep 2023 11:41:22 -0500 +Subject: [PATCH 4/6] librtas: vendor papr-miscdev.h + +This is a common header used by other kernel uapi headers that we will +copy into the source tree. + +Signed-off-by: Nathan Lynch +--- + Makefile.am | 4 +++- + librtas_src/papr-miscdev.h | 9 +++++++++ + 2 files changed, 12 insertions(+), 1 deletion(-) + create mode 100644 librtas_src/papr-miscdev.h + +diff --git a/Makefile.am b/Makefile.am +index 1385ac7..d0cabfb 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -35,7 +35,9 @@ librtas_la_SOURCES = \ + librtas_src/sysparm.c + + library_include_HEADERS += librtas_src/librtas.h +-noinst_HEADERS += librtas_src/internal.h ++noinst_HEADERS += \ ++ librtas_src/internal.h \ ++ librtas_src/papr-miscdev.h + + # See "Updating library version information" in the libtool manual for + # how to maintain these values. They are *not* tied to the release +diff --git a/librtas_src/papr-miscdev.h b/librtas_src/papr-miscdev.h +new file mode 100644 +index 0000000..c0b1072 +--- /dev/null ++++ b/librtas_src/papr-miscdev.h +@@ -0,0 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note ++#ifndef _UAPI_PAPR_MISCDEV_H_ ++#define _UAPI_PAPR_MISCDEV_H_ ++ ++enum { ++ PAPR_MISCDEV_IOC_ID = 0xb2, ++}; ++ ++#endif /* _UAPI_PAPR_MISCDEV_H_ */ +-- +2.42.0 + diff --git a/0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch b/0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch new file mode 100644 index 0000000..6a83f03 --- /dev/null +++ b/0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch @@ -0,0 +1,279 @@ +From 3fffa2c147a69fac72b0159be967ecbe9c751dfb Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Sat, 12 Aug 2023 13:27:39 -0500 +Subject: [PATCH 5/6] librtas/vpd: prefer /dev/papr-vpd when available + +Change rtas_get_vpd() to prefer the /dev/papr-vpd character device as +proposed for the kernel here: + +https://lore.kernel.org/linuxppc-dev/20230822-papr-sys_rtas-vs-lockdown-v1-0-932623cf3c7b@linux.ibm.com/ + +On the first invocation of rtas_get_vpd(), probe for the new ABI and +initialize an internal function pointer according to the result. Use +pthread_once() to ensure that this probe step is performed atomically +and only once. It would not make sense to re-probe (and potentially +update the implementation) on every call, since the implementations +differ in the way state for the call sequence is maintained. + +Assuming the new ABI is available: upon first call to rtas_get_vpd(), +open /dev/papr-vpd and obtain a file descriptor using the +PAPR_VPD_CREATE_HANDLE ioctl() command. This file descriptor is a +reference to the VPD returned from a complete ibm,get-vpd call +sequence. Subsequent calls sequentially read the VPD from the fd, +which is closed once EOF is reached. + +To existing users of rtas_get_vpd(), the new implementation is +indistinguishable from the old one, with one exception: + +* When using the rtas() syscall on current systems, RTAS advances the + sequence number by a fixed interval on each call in a sequence. This + is visible in the values returned in the 'seq_next' out parameter. + +* When using /dev/papr-vpd, the value returned in 'seq_next' does not + change between calls; librtas treats it as a "handle" for a sequence + in progress. + +In PAPR there is no meaning attached to the value returned in the +'seq_next' out parameter, and there is no requirement that it must +change or increment on each call. No user should be relying on the +behavior of this aspect of the interface to judge the status of a +sequence. + +I have verified that an unmodified vpdupdate command from a distro +lsvpd package works correctly when linked to a librtas.so with this +change. This is the primary (and perhaps only) user of rtas_get_vpd(). + +For now, carry a copy of the kernel uapi header. + +Signed-off-by: Nathan Lynch +--- + Makefile.am | 3 +- + librtas_src/papr-vpd.h | 22 ++++++ + librtas_src/vpd.c | 155 ++++++++++++++++++++++++++++++++++++----- + 3 files changed, 161 insertions(+), 19 deletions(-) + create mode 100644 librtas_src/papr-vpd.h + +diff --git a/Makefile.am b/Makefile.am +index d0cabfb..d3513e9 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -37,7 +37,8 @@ librtas_la_SOURCES = \ + library_include_HEADERS += librtas_src/librtas.h + noinst_HEADERS += \ + librtas_src/internal.h \ +- librtas_src/papr-miscdev.h ++ librtas_src/papr-miscdev.h \ ++ librtas_src/papr-vpd.h + + # See "Updating library version information" in the libtool manual for + # how to maintain these values. They are *not* tied to the release +diff --git a/librtas_src/papr-vpd.h b/librtas_src/papr-vpd.h +new file mode 100644 +index 0000000..b57cf30 +--- /dev/null ++++ b/librtas_src/papr-vpd.h +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note ++#ifndef _UAPI_PAPR_VPD_H_ ++#define _UAPI_PAPR_VPD_H_ ++ ++#include ++#include "papr-miscdev.h" ++ ++struct papr_location_code { ++ /* ++ * PAPR+ 12.3.2.4 Converged Location Code Rules - Length ++ * Restrictions. 79 characters plus nul. ++ */ ++ char str[80]; ++}; ++ ++/* ++ * ioctl for /dev/papr-vpd. Returns a VPD handle fd corresponding to ++ * the location code. ++ */ ++#define PAPR_VPD_IOC_CREATE_HANDLE _IOW(PAPR_MISCDEV_IOC_ID, 0, struct papr_location_code) ++ ++#endif /* _UAPI_PAPR_VPD_H_ */ +diff --git a/librtas_src/vpd.c b/librtas_src/vpd.c +index b2689fb..544560f 100644 +--- a/librtas_src/vpd.c ++++ b/librtas_src/vpd.c +@@ -1,33 +1,33 @@ + // SPDX-License-Identifier: LGPL-2.1-or-later + + // Support for accessing IBM Power systems Vital Product Data (VPD) +-// via the rtas() syscall. ++// via /dev/papr-vpd or the legacy rtas() syscall. + +-#include ++#include ++#include ++#include ++#include + #include + #include +-#include ++#include ++#include ++#include ++#include ++#include + #include ++#include ++#include + #include ++#include + + #include "internal.h" + #include "librtas.h" ++#include "papr-vpd.h" + +-/** +- * rtas_get_vpd +- * @brief Interface to the ibm,get-vpd rtas call +- * +- * @param loc_code location code +- * @param workarea additional args to rtas call +- * @param size +- * @param sequence +- * @param seq_next +- * @param bytes_ret +- * @return 0 on success, !0 otherwise +- */ +-int rtas_get_vpd(char *loc_code, char *workarea, size_t size, +- unsigned int sequence, unsigned int *seq_next, +- unsigned int *bytes_ret) ++static int ++get_vpd_syscall_fallback(const char *loc_code, char *workarea, size_t size, ++ unsigned int sequence, unsigned int *seq_next, ++ unsigned int *bytes_ret) + { + uint32_t kernbuf_pa; + uint32_t loc_pa = 0; +@@ -79,3 +79,122 @@ int rtas_get_vpd(char *loc_code, char *workarea, size_t size, + workarea, size, sequence, status, *seq_next, *bytes_ret); + return rc ? rc : status; + } ++ ++static bool get_vpd_can_use_chardev(void) ++{ ++ struct stat statbuf; ++ ++ if (stat("/dev/papr-vpd", &statbuf)) ++ return false; ++ ++ if (!S_ISCHR(statbuf.st_mode)) ++ return false; ++ ++ if (close(open("/dev/papr-vpd", O_RDONLY))) ++ return false; ++ ++ return true; ++} ++ ++#define DEVPATH "/dev/papr-vpd" ++ ++static int vpd_fd_new(const char *loc_code) ++{ ++ const int devfd = open(DEVPATH, O_WRONLY); ++ struct papr_location_code lc = {}; ++ int fd = -1; ++ ++ if (devfd < 0) ++ return -1; ++ ++ if (!loc_code) ++ loc_code = ""; ++ ++ if (sizeof(lc.str) < strlen(loc_code)) ++ goto close_devfd; ++ ++ strncpy(lc.str, loc_code, sizeof(lc.str)); ++ fd = ioctl(devfd, PAPR_VPD_IOC_CREATE_HANDLE, &lc); ++close_devfd: ++ close(devfd); ++ return fd; ++} ++ ++static int ++get_vpd_chardev(const char *loc_code, char *workarea, size_t size, ++ unsigned int sequence, unsigned int *seq_next, ++ unsigned int *bytes_ret) ++{ ++ int fd = (sequence == 1) ? vpd_fd_new(loc_code) : (int)sequence; ++ ++ /* ++ * Ensure we return a fd > 0 in seq_next. ++ */ ++ if (fd == 1) { ++ int newfd = dup(fd); ++ close(fd); ++ fd = newfd; ++ } ++ ++ if (fd < 0) ++ return -3; /* Synthesize ibm,get-vpd "parameter error" */ ++ ++ int rtas_status = 0; ++ ssize_t res = read(fd, workarea, size); ++ if (res < 0) { ++ rtas_status = -1; /* Synthesize ibm,get-vpd "hardware error" */ ++ close(fd); ++ } else if (res == 0 || res < (ssize_t)size) { ++ rtas_status = 0; /* Done with sequence, no more data */ ++ close(fd); ++ if (seq_next) ++ *seq_next = 1; ++ if (bytes_ret) ++ *bytes_ret = res; ++ } else { ++ rtas_status = 1; /* More data available, call again */ ++ if (seq_next) ++ *seq_next = fd; ++ if (bytes_ret) ++ *bytes_ret = res; ++ } ++ ++ return rtas_status; ++} ++ ++static int (*get_vpd_fn)(const char *loc_code, ++ char *workarea, ++ size_t size, ++ unsigned int sequence, ++ unsigned int *seq_next, ++ unsigned int *bytes_ret); ++ ++static void get_vpd_fn_setup(void) ++{ ++ get_vpd_fn = get_vpd_can_use_chardev() ? ++ get_vpd_chardev : get_vpd_syscall_fallback; ++} ++ ++/** ++ * rtas_get_vpd ++ * @brief Interface to the ibm,get-vpd rtas call ++ * ++ * @param loc_code location code ++ * @param workarea additional args to rtas call ++ * @param size ++ * @param sequence ++ * @param seq_next ++ * @param bytes_ret ++ * @return 0 on success, !0 otherwise ++ */ ++int rtas_get_vpd(char *loc_code, char *workarea, size_t size, ++ unsigned int sequence, unsigned int *seq_next, ++ unsigned int *bytes_ret) ++{ ++ static pthread_once_t get_vpd_fn_once = PTHREAD_ONCE_INIT; ++ ++ pthread_once(&get_vpd_fn_once, get_vpd_fn_setup); ++ ++ return get_vpd_fn(loc_code, workarea, size, sequence, ++ seq_next, bytes_ret); ++} +-- +2.42.0 + diff --git a/0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch b/0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch new file mode 100644 index 0000000..b64dee0 --- /dev/null +++ b/0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch @@ -0,0 +1,286 @@ +From c98bf4d902821cfeb83cd6037a36a0bf208f842c Mon Sep 17 00:00:00 2001 +From: Nathan Lynch +Date: Mon, 25 Sep 2023 11:42:26 -0500 +Subject: [PATCH 6/6] librtas/sysparm: prefer /dev/papr-sysparm when available + +Change rtas_get_sysparm() and rtas_set_sysparm() to prefer the +/dev/papr-sysparm character device as proposed for the kernel here: + +[[[ FIXME ]]] + +On the first invocation of either function, probe for the new ABI and +initialize internal function pointers according to the result. Use +pthread_once() to ensure that this initialization step is performed +atomically and only once. + +When /dev/papr-sysparm is available, use its PAPR_SYSPARM_IOC_GET and +PAPR_SYSPARM_IOC_SET ioctl commands to retrieve and update system +parameters. Most of the complexity of calling RTAS is handled +internally to the kernel and the ioctl follows Linux conventions, +returning 0 on success or -1 w/errno on failure. On failure, +back-convert the errno to an RTAS status value that callers will +recognize. + +For now, carry a copy of the kernel uapi header. + +Signed-off-by: Nathan Lynch +--- + Makefile.am | 1 + + librtas_src/papr-sysparm.h | 58 +++++++++++++++ + librtas_src/sysparm.c | 144 ++++++++++++++++++++++++++++++++++++- + 3 files changed, 201 insertions(+), 2 deletions(-) + create mode 100644 librtas_src/papr-sysparm.h + +diff --git a/Makefile.am b/Makefile.am +index d3513e9..29b3b76 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -38,6 +38,7 @@ library_include_HEADERS += librtas_src/librtas.h + noinst_HEADERS += \ + librtas_src/internal.h \ + librtas_src/papr-miscdev.h \ ++ librtas_src/papr-sysparm.h \ + librtas_src/papr-vpd.h + + # See "Updating library version information" in the libtool manual for +diff --git a/librtas_src/papr-sysparm.h b/librtas_src/papr-sysparm.h +new file mode 100644 +index 0000000..e0c0ebb +--- /dev/null ++++ b/librtas_src/papr-sysparm.h +@@ -0,0 +1,58 @@ ++// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note ++#ifndef _UAPI_PAPR_SYSPARM_H_ ++#define _UAPI_PAPR_SYSPARM_H_ ++ ++#include ++#include ++#include "papr-miscdev.h" ++ ++enum { ++ PAPR_SYSPARM_MAX_INPUT = 1024, ++ PAPR_SYSPARM_MAX_OUTPUT = 4000, ++}; ++ ++struct papr_sysparm_io_block { ++ __u32 parameter; ++ __u16 length; ++ char data[PAPR_SYSPARM_MAX_OUTPUT]; ++}; ++ ++/** ++ * PAPR_SYSPARM_IOC_GET - Retrieve the value of a PAPR system parameter. ++ * ++ * Uses _IOWR because of one corner case: Retrieving the value of the ++ * "OS Service Entitlement Status" parameter (60) requires the caller ++ * to supply input data (a date string) in the buffer passed to ++ * firmware. So the @length and @data of the incoming ++ * papr_sysparm_io_block are always used to initialize the work area ++ * supplied to ibm,get-system-parameter. No other parameters are known ++ * to parameterize the result this way, and callers are encouraged ++ * (but not required) to zero-initialize @length and @data in the ++ * common case. ++ * ++ * On error the contents of the ioblock are indeterminate. ++ * ++ * Return: ++ * 0: Success; @length is the length of valid data in @data, not to exceed @PAPR_SYSPARM_MAX_OUTPUT. ++ * -EIO: Platform error. (-1) ++ * -EINVAL: Incorrect data length or format. (-9999) ++ * -EPERM: The calling partition is not allowed to access this parameter. (-9002) ++ * -EOPNOTSUPP: Parameter not supported on this platform (-3) ++ */ ++#define PAPR_SYSPARM_IOC_GET _IOWR(PAPR_MISCDEV_IOC_ID, 1, struct papr_sysparm_io_block) ++ ++/** ++ * PAPR_SYSPARM_IOC_SET - Update the value of a PAPR system parameter. ++ * ++ * The contents of the ioblock are unchanged regardless of success. ++ * ++ * Return: ++ * 0: Success; the parameter has been updated. ++ * -EIO: Platform error. (-1) ++ * -EINVAL: Incorrect data length or format. (-9999) ++ * -EPERM: The calling partition is not allowed to access this parameter. (-9002) ++ * -EOPNOTSUPP: Parameter not supported on this platform (-3) ++ */ ++#define PAPR_SYSPARM_IOC_SET _IOW(PAPR_MISCDEV_IOC_ID, 2, struct papr_sysparm_io_block) ++ ++#endif /* _UAPI_PAPR_SYSPARM_H_ */ +diff --git a/librtas_src/sysparm.c b/librtas_src/sysparm.c +index 40af55e..b4d2054 100644 +--- a/librtas_src/sysparm.c ++++ b/librtas_src/sysparm.c +@@ -1,7 +1,16 @@ ++#include ++#include ++#include ++#include + #include + #include ++#include ++#include + #include "internal.h" + #include "librtas.h" ++#include "papr-sysparm.h" ++ ++static const char sysparm_devpath[] = "/dev/papr-sysparm"; + + /** + * rtas_get_sysparm +@@ -15,7 +24,8 @@ + * @param data reference to buffer to return parameter in + * @return 0 on success, !0 otherwise + */ +-int rtas_get_sysparm(unsigned int parameter, unsigned int length, char *data) ++static int ++get_sysparm_syscall_fallback(unsigned int parameter, unsigned int length, char *data) + { + uint32_t kernbuf_pa; + void *kernbuf; +@@ -49,7 +59,8 @@ int rtas_get_sysparm(unsigned int parameter, unsigned int length, char *data) + * @param data + * @return 0 on success, !0 otherwise + */ +-int rtas_set_sysparm(unsigned int parameter, char *data) ++static int ++set_sysparm_syscall_fallback(unsigned int parameter, char *data) + { + uint32_t kernbuf_pa; + void *kernbuf; +@@ -86,3 +97,132 @@ int rtas_set_sysparm(unsigned int parameter, char *data) + dbg("(%u, %p) = %d\n", parameter, data, rc ? rc : status); + return rc ? rc : status; + } ++ ++static bool sysparm_can_use_chardev(void) ++{ ++ struct stat statbuf; ++ ++ if (stat(sysparm_devpath, &statbuf)) ++ return false; ++ ++ if (!S_ISCHR(statbuf.st_mode)) ++ return false; ++ ++ if (close(open(sysparm_devpath, O_RDONLY))) ++ return false; ++ ++ return true; ++} ++ ++/* ++ * Only to be used when converting an actual error from a syscall. ++ */ ++static int chardev_backconvert_errno(int saved_errno) ++{ ++ const struct { ++ int linux_errno; ++ int rtas_status; ++ } map[] = { ++#define errno_to_status(e, s) { .linux_errno = (e), .rtas_status = (s), } ++ errno_to_status(EINVAL, -9999), ++ errno_to_status(EPERM, -9002), ++ errno_to_status(EOPNOTSUPP, -3), ++ errno_to_status(EIO, -1), ++ errno_to_status(EFAULT, -1), ++#undef errno_to_status ++ }; ++ ++ for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); ++i) ++ if (map[i].linux_errno == saved_errno) ++ return map[i].rtas_status; ++ return -1; ++} ++ ++static int get_sysparm_chardev(unsigned int parameter, unsigned int length, char *data) ++{ ++ const int fd = open(sysparm_devpath, O_RDWR); ++ struct papr_sysparm_io_block buf = { ++ .parameter = parameter, ++ }; ++ ++ if (fd < 0) { ++ /* ++ * Really shouldn't get here without misconfiguration, ++ * e.g. removal of /dev/papr-sysparm. Synthesize a ++ * hardware/platform error. ++ */ ++ return -1; ++ } ++ ++ /* ++ * It might make sense to have special handling for parameter ++ * 60 (OS Service Entitlement Status), which takes input data, ++ * but librtas has never handled that one correctly. So ignore ++ * it for now and don't copy incoming data into the block we ++ * pass to PAPR_SYSPARM_IOC_GET. ++ */ ++ ++ const int res = ioctl(fd, PAPR_SYSPARM_IOC_GET, &buf); ++ const int saved_errno = errno; ++ (void)close(fd); ++ ++ if (res != 0) ++ return chardev_backconvert_errno(saved_errno); ++ ++ const uint16_t result_size_msb = htobe16(buf.length); ++ memcpy(data, &result_size_msb, sizeof(result_size_msb)); ++ length -= sizeof(result_size_msb); ++ data += sizeof(result_size_msb); ++ ++ /* ++ * Copy no more than min(@length, sizeof(buf.data)). ++ */ ++ const size_t copy_size = sizeof(buf.data) < length ? ++ sizeof(buf.data) : length; ++ memcpy(data, buf.data, copy_size); ++ return 0; ++} ++ ++static int set_sysparm_chardev(unsigned int parameter, char *data) ++{ ++ const int fd = open(sysparm_devpath, O_RDWR); ++ struct papr_sysparm_io_block buf = { ++ .parameter = parameter, ++ .length = (((unsigned char)data[0] << 8) | (unsigned char)data[1]), ++ }; ++ ++ memcpy(buf.data, data + 2, buf.length); ++ ++ const int res = ioctl(fd, PAPR_SYSPARM_IOC_SET, &buf); ++ const int saved_errno = errno; ++ (void)close(fd); ++ ++ return res == 0 ? 0 : chardev_backconvert_errno(saved_errno); ++} ++ ++static int (*get_sysparm_fn)(unsigned int parameter, unsigned int length, char *data); ++static int (*set_sysparm_fn)(unsigned int parameter, char *data); ++ ++static void sysparm_fn_setup(void) ++{ ++ const bool use_chardev = sysparm_can_use_chardev(); ++ ++ get_sysparm_fn = use_chardev ? ++ get_sysparm_chardev : get_sysparm_syscall_fallback; ++ set_sysparm_fn = use_chardev ? ++ set_sysparm_chardev : set_sysparm_syscall_fallback; ++} ++ ++static pthread_once_t sysparm_fn_setup_once = PTHREAD_ONCE_INIT; ++ ++int rtas_get_sysparm(unsigned int parameter, unsigned int length, char *data) ++{ ++ pthread_once(&sysparm_fn_setup_once, sysparm_fn_setup); ++ return get_sysparm_fn(parameter, length, data); ++} ++ ++int rtas_set_sysparm(unsigned int parameter, char *data) ++{ ++ pthread_once(&sysparm_fn_setup_once, sysparm_fn_setup); ++ return set_sysparm_fn(parameter, data); ++} +-- +2.42.0 + diff --git a/activate-firmware-regress b/activate-firmware-regress new file mode 100644 index 0000000..ec8adc6 --- /dev/null +++ b/activate-firmware-regress @@ -0,0 +1,118 @@ +#!/bin/bash + +# Created by argbash-init v2.10.0 +# ARG_OPTIONAL_SINGLE([old],[],[old librtas DSO],[/lib64/librtas.so.2]) +# ARG_OPTIONAL_SINGLE([new],[],[new librtas DSO],[$PWD/.libs/librtas.so.2]) +# ARG_HELP([Test the activate_firmware command against a development build of librtas]) +# ARGBASH_GO() +# needed because of Argbash --> m4_ignore([ +### START OF CODE GENERATED BY Argbash v2.10.0 one line above ### +# Argbash is a bash code generator used to get arguments parsing right. +# Argbash is FREE SOFTWARE, see https://argbash.io for more info + + +die() +{ + local _ret="${2:-1}" + test "${_PRINT_HELP:-no}" = yes && print_help >&2 + echo "$1" >&2 + exit "${_ret}" +} + + +begins_with_short_option() +{ + local first_option all_short_options='h' + first_option="${1:0:1}" + test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 +} + +# THE DEFAULTS INITIALIZATION - OPTIONALS +_arg_old="/lib64/librtas.so.2" +_arg_new="$PWD/.libs/librtas.so.2" + + +print_help() +{ + printf '%s\n' "Test the activate_firmware command against a development build of librtas" + printf 'Usage: %s [--old ] [--new ] [-h|--help]\n' "$0" + printf '\t%s\n' "--old: old librtas DSO (default: '/lib64/librtas.so.2')" + printf '\t%s\n' "--new: new librtas DSO (default: '$PWD/.libs/librtas.so.2')" + printf '\t%s\n' "-h, --help: Prints help" +} + + +parse_commandline() +{ + while test $# -gt 0 + do + _key="$1" + case "$_key" in + --old) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_old="$2" + shift + ;; + --old=*) + _arg_old="${_key##--old=}" + ;; + --new) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_new="$2" + shift + ;; + --new=*) + _arg_new="${_key##--new=}" + ;; + -h|--help) + print_help + exit 0 + ;; + -h*) + print_help + exit 0 + ;; + *) + _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 + ;; + esac + shift + done +} + +parse_commandline "$@" + +# OTHER STUFF GENERATED BY Argbash + +### END OF CODE GENERATED BY Argbash (sortof) ### ]) +# [ <-- needed because of Argbash + +set -eu +set -o pipefail + +workdir="$(mktemp -d)" + +uak_old="${workdir}/uak.old" +uak_new="${workdir}/uak.new" + +preload_sanitizers=/lib64/libasan.so.8:/lib64/libubsan.so.1 + +export LD_PRELOAD="${preload_sanitizers}":"$_arg_old" +activate_firmware -e > "$uak_old" + +export LD_PRELOAD="${preload_sanitizers}":"$_arg_new" +activate_firmware -e > "$uak_new" + +export -n LSAN_OPTIONS ASAN_OPTIONS LD_PRELOAD + +cmp "$uak_old" "$uak_new" || { + echo "error: Update Access Key information differs" + diff -u "$uak_old" "$uak_new" + exit 1 +} + +echo "Tested $(type -P activate_firmware) with ${_arg_old} and ${_arg_new}, no differences detected." + +test -d "$workdir" && rm -fr "$workdir" + +# ] <-- needed because of Argbash diff --git a/librtas-doc.spec b/librtas-doc.spec index 9ffff19..c06b006 100644 --- a/librtas-doc.spec +++ b/librtas-doc.spec @@ -24,12 +24,22 @@ License: LGPL-2.1-or-later Group: Documentation/Other URL: https://github.com/ibm-power-utilities/librtas Source0: https://github.com/ibm-power-utilities/librtas/archive/v%{version}.tar.gz#/librtas-%{version}.tar.gz +Source2: activate-firmware-regress +Source3: vpdupdate-regress Patch0: librtas.fix_doc_path.patch +Patch1: 0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch +Patch2: 0002-librtas-move-VPD-code-into-separate-module.patch +Patch3: 0003-librtas-move-system-parameter-code-to-separate-modul.patch +Patch4: 0004-librtas-vendor-papr-miscdev.h.patch +Patch5: 0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch +Patch6: 0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch +Patch7: link-lpthread.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: doxygen BuildRequires: fdupes BuildRequires: libtool +BuildRequires: pkgconfig ExclusiveArch: ppc ppc64 ppc64le %description @@ -41,7 +51,7 @@ This package provides librtas documentation %build ./autogen.sh %configure -%make_build CFLAGS="%{optflags} -fPIC -g -I $PWD/librtasevent_src" LIB_DIR="%{_libdir}" +make -O V=1 VERBOSE=1 CFLAGS="%{optflags} -fPIC -g -I $PWD/librtasevent_src" LIB_DIR="%{_libdir}" %{?_smp_mflags} %install rm -rf doc/*/latex diff --git a/librtas.changes b/librtas.changes index 8f16457..d15ffa5 100644 --- a/librtas.changes +++ b/librtas.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Mon Nov 20 16:14:19 UTC 2023 - Michal Suchanek + +- Add support for new rtas kernel interface for VPD and sysparm (jsc#PED-4541). + * 0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch + * 0002-librtas-move-VPD-code-into-separate-module.patch + * 0003-librtas-move-system-parameter-code-to-separate-modul.patch + * 0004-librtas-vendor-papr-miscdev.h.patch + * 0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch + * 0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch + * link-lpthread.patch + * tests: activate-firmware-regress vpdupdate-regress + ------------------------------------------------------------------- Mon Nov 20 14:50:54 UTC 2023 - Michal Suchanek diff --git a/librtas.spec b/librtas.spec index b9f0592..76e22f8 100644 --- a/librtas.spec +++ b/librtas.spec @@ -26,10 +26,20 @@ Group: System/Libraries URL: https://github.com/ibm-power-utilities/librtas Source0: https://github.com/ibm-power-utilities/librtas/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Source1: baselibs.conf +Source2: activate-firmware-regress +Source3: vpdupdate-regress Patch0: librtas.fix_doc_path.patch +Patch1: 0001-librtas-expose-low-level-RTAS-call-APIs-internally.patch +Patch2: 0002-librtas-move-VPD-code-into-separate-module.patch +Patch3: 0003-librtas-move-system-parameter-code-to-separate-modul.patch +Patch4: 0004-librtas-vendor-papr-miscdev.h.patch +Patch5: 0005-librtas-vpd-prefer-dev-papr-vpd-when-available.patch +Patch6: 0006-librtas-sysparm-prefer-dev-papr-sysparm-when-availab.patch +Patch7: link-lpthread.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool +BuildRequires: pkgconfig ExclusiveArch: ppc ppc64 ppc64le %description @@ -80,16 +90,17 @@ contents of RTAS events. %global _lto_cflags %{_lto_cflags} -ffat-lto-objects ./autogen.sh %configure -%make_build CFLAGS="%{optflags} -fPIC -g -I $PWD/librtasevent_src" LIB_DIR="%{_libdir}" +make -O V=1 VERBOSE=1 CFLAGS="%{optflags} -fPIC -g -I $PWD/librtasevent_src" LIB_DIR="%{_libdir}" %{?_smp_mflags} %install rm -rf doc/*/latex make install DESTDIR=%{buildroot} LIB_DIR="%{_libdir}" # documents are in -doc subpackage -rm -rf %{buildroot}/%{_docdir} +rm -rf %{buildroot}%{_docdir} /sbin/ldconfig -n %{buildroot}%{_libdir} chmod -x %{buildroot}%{_libdir}/*.a find %{buildroot} -type f -name "*.la" -delete -print +install -v -m 755 -D -t %{buildroot}%{_docdir}/%{name} %{SOURCE2} %{SOURCE3} %post -n %{name}%{sover} -p /sbin/ldconfig %postun -n %{name}%{sover} -p /sbin/ldconfig @@ -101,6 +112,7 @@ find %{buildroot} -type f -name "*.la" -delete -print %files devel %license COPYING.LESSER +%{_docdir}/%{name} %{_libdir}/librtasevent.so %{_libdir}/librtas.so %{_includedir}/librtas.h diff --git a/link-lpthread.patch b/link-lpthread.patch new file mode 100644 index 0000000..cfce39d --- /dev/null +++ b/link-lpthread.patch @@ -0,0 +1,15 @@ +librtas now uses pthread_once + +diff -ur librtas-2.0.5.orig/Makefile.am librtas-2.0.5/Makefile.am +--- librtas-2.0.5.orig/Makefile.am 2023-11-23 20:42:40.488274968 +0100 ++++ librtas-2.0.5/Makefile.am 2023-11-23 20:46:55.600974184 +0100 +@@ -26,7 +26,7 @@ + LIBRTAS_LIBRARY_VERSION = $(LIBRTAS_CURRENT):$(LIBRTAS_REVISION):$(LIBRTAS_AGE) + + lib_LTLIBRARIES += librtas.la +-librtas_la_LDFLAGS = -version-info $(LIBRTAS_LIBRARY_VERSION) ++librtas_la_LDFLAGS = -version-info $(LIBRTAS_LIBRARY_VERSION) -lpthread + librtas_la_SOURCES = \ + librtas_src/vpd.c \ + librtas_src/ofdt.c \ +Only in librtas-2.0.5: Makefile.am~ diff --git a/vpdupdate-regress b/vpdupdate-regress new file mode 100644 index 0000000..8ea022f --- /dev/null +++ b/vpdupdate-regress @@ -0,0 +1,145 @@ +#!/bin/bash + +# Created by argbash-init v2.10.0 +# ARG_OPTIONAL_SINGLE([old],[],[old librtas DSO],[/lib64/librtas.so.2]) +# ARG_OPTIONAL_SINGLE([new],[],[new librtas DSO],[$PWD/.libs/librtas.so.2]) +# ARG_HELP([Test the vpdupdate command against a development build of librtas]) +# ARGBASH_GO() +# needed because of Argbash --> m4_ignore([ +### START OF CODE GENERATED BY Argbash v2.10.0 one line above ### +# Argbash is a bash code generator used to get arguments parsing right. +# Argbash is FREE SOFTWARE, see https://argbash.io for more info + + +die() +{ + local _ret="${2:-1}" + test "${_PRINT_HELP:-no}" = yes && print_help >&2 + echo "$1" >&2 + exit "${_ret}" +} + + +begins_with_short_option() +{ + local first_option all_short_options='h' + first_option="${1:0:1}" + test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 +} + +# THE DEFAULTS INITIALIZATION - OPTIONALS +_arg_old="/lib64/librtas.so.2" +_arg_new="$PWD/.libs/librtas.so.2" + + +print_help() +{ + printf '%s\n' "Test the vpdupdate command against a development build of librtas" + printf 'Usage: %s [--old ] [--new ] [-h|--help]\n' "$0" + printf '\t%s\n' "--old: old librtas DSO (default: '/lib64/librtas.so.2')" + printf '\t%s\n' "--new: new librtas DSO (default: '$PWD/.libs/librtas.so.2')" + printf '\t%s\n' "-h, --help: Prints help" +} + + +parse_commandline() +{ + while test $# -gt 0 + do + _key="$1" + case "$_key" in + --old) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_old="$2" + shift + ;; + --old=*) + _arg_old="${_key##--old=}" + ;; + --new) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_new="$2" + shift + ;; + --new=*) + _arg_new="${_key##--new=}" + ;; + -h|--help) + print_help + exit 0 + ;; + -h*) + print_help + exit 0 + ;; + *) + _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 + ;; + esac + shift + done +} + +parse_commandline "$@" + +# OTHER STUFF GENERATED BY Argbash + +### END OF CODE GENERATED BY Argbash (sortof) ### ]) +# [ <-- needed because of Argbash + +set -eu +set -o pipefail + +workdir="$(mktemp -d)" +chmod 0775 "$workdir" # vpdupdate refuses to create the db without this? + +# vpdupdate unlinks files in the same directory as the target named +# vpd.db*, use separate directories +vpd_db_old="${workdir}/old/vpd.db" +vpd_db_new="${workdir}/new/vpd.db" + +# Interested in detecting leaks from within librtas, but not vpd code. +leak_suppressions="${workdir}/suppressions.txt" +cat > "$leak_suppressions" < "$sizes" +md5sum "$vpd_db_old" "$vpd_db_new" > "$sums" +join -j 2 "$sizes" "$sums" + +echo "Tested $(type -P vpdupdate) with ${_arg_old} and ${_arg_new}, no differences detected." + +test -d "$workdir" && rm -fr "$workdir" + +# ] <-- needed because of Argbash