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
This commit is contained in:
Michal Suchanek 2024-01-04 16:53:48 +00:00 committed by Git OBS Bridge
parent 1d05bfa7fe
commit 6320ffa20b
12 changed files with 1435 additions and 3 deletions

View File

@ -0,0 +1,79 @@
From 0d48bdca32cbf7a83bcaa5a27e3454d24055e0cb Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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

View File

@ -0,0 +1,197 @@
From 12a2764fd7efe7c52b53579a67edb641d662f54f Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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 <endian.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+#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

View File

@ -0,0 +1,230 @@
From 80dfb541257cb88519855543324478cbb0f1f1b3 Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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 <stdint.h>
+#include <string.h>
+#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

View File

@ -0,0 +1,48 @@
From ba86b513cbed32f5cdf8840b727457688a0737fb Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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

View File

@ -0,0 +1,279 @@
From 3fffa2c147a69fac72b0159be967ecbe9c751dfb Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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 <asm/ioctl.h>
+#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 <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
#include <linux/types.h>
#include <linux/unistd.h>
-#include <stdint.h>
+#include <pthread.h>
+#include <search.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <sys/syscall.h>
+#include <unistd.h>
#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

View File

@ -0,0 +1,286 @@
From c98bf4d902821cfeb83cd6037a36a0bf208f842c Mon Sep 17 00:00:00 2001
From: Nathan Lynch <nathanl@linux.ibm.com>
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 <nathanl@linux.ibm.com>
---
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 <linux/types.h>
+#include <asm/ioctl.h>
+#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 <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
#include <stdint.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
#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

118
activate-firmware-regress Normal file
View File

@ -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 <arg>] [--new <arg>] [-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

View File

@ -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

View File

@ -1,3 +1,16 @@
-------------------------------------------------------------------
Mon Nov 20 16:14:19 UTC 2023 - Michal Suchanek <msuchanek@suse.com>
- 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 <msuchanek@suse.com>

View File

@ -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

15
link-lpthread.patch Normal file
View File

@ -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~

145
vpdupdate-regress Normal file
View File

@ -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 <arg>] [--new <arg>] [-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" <<EOF
leak:^lsvpd::SysFSTreeCollector::
EOF
# ASAN_OPTIONS=alloc_dealloc_mismatch=0 is for new[]/delete
# mismatches in vpdupdate code.
export LSAN_OPTIONS="suppressions=$leak_suppressions"
export ASAN_OPTIONS=alloc_dealloc_mismatch=0
preload_sanitizers=/lib64/libasan.so.8:/lib64/libubsan.so.1
export LD_PRELOAD="${preload_sanitizers}":"$_arg_old"
vpdupdate -p "$vpd_db_old"
test -s "$vpd_db_old" || {
echo "error: VPD database ${vpd_db_old} is empty!?"
exit 1
}
export LD_PRELOAD="${preload_sanitizers}":"$_arg_new"
vpdupdate -p "$vpd_db_new"
test -s "$vpd_db_new" || {
echo "error: VPD database ${vpd_db_new} is empty!?"
exit 1
}
export -n LSAN_OPTIONS ASAN_OPTIONS LD_PRELOAD
cmp "$vpd_db_old" "$vpd_db_new" || {
echo "error: VPD database ${vpd_db_old} differs from ${vpd_db_new}"
exit 1
}
sizes="${workdir}/sizes"
sums="${workdir}/sums"
du -h "$vpd_db_old" "$vpd_db_new" > "$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