X86 platform drivers
 help / color / mirror / Atom feed
From: Muhammad Bilal <meatuni001@gmail.com>
To: Jorge Lopez <jorge.lopez2@hp.com>
Cc: "Hans de Goede" <hansg@kernel.org>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	"Muhammad Bilal" <meatuni001@gmail.com>
Subject: [PATCH] platform/x86: hp-bioscfg: consolidate common package-element parsing
Date: Sun,  6 Sep 2026 02:48:01 +0500	[thread overview]
Message-ID: <20260905214801.76265-1-meatuni001@gmail.com> (raw)

hp_populate_string_elements_from_package(),
hp_populate_integer_elements_from_package(),
hp_populate_enumeration_elements_from_package(),
hp_populate_ordered_list_elements_from_package(), and
hp_populate_password_elements_from_package() each parse the same
PATH..SECURITY_LEVEL range into their own struct common_data
sub-object, copy-pasted five times. Factor it into
hp_get_common_data_from_package(), called from all five, mirroring
hp_get_common_data_from_buffer()'s existing split for the buffer
side.

The five PREREQUISITES loops weren't identical: on a bad
prerequisite string, string/integer/ordered_list continue,
enumeration returns -EINVAL, password breaks. The shared helper
continues, matching the majority and
hp_get_common_data_from_buffer()'s own handling of the equivalent
failure. This changes enumeration (no longer aborts the package)
and password (no longer leaves later prerequisites unfilled).

The expected_*_types[eloc] != obj[elem].type check above this
switch has the same split -- enumeration warns and continues, the
rest pr_err() and return -EIO -- left alone here; consolidating it
needs each type's expected_*_types[] table passed into a shared
checker, not just struct common_data.

Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Muhammad Bilal <meatuni001@gmail.com>
---
 drivers/platform/x86/hp/hp-bioscfg/bioscfg.c  | 97 +++++++++++++++++++
 drivers/platform/x86/hp/hp-bioscfg/bioscfg.h  |  3 +
 .../x86/hp/hp-bioscfg/enum-attributes.c       | 57 +----------
 .../x86/hp/hp-bioscfg/int-attributes.c        | 57 +----------
 .../x86/hp/hp-bioscfg/order-list-attributes.c | 58 +----------
 .../x86/hp/hp-bioscfg/passwdobj-attributes.c  | 57 +----------
 .../x86/hp/hp-bioscfg/string-attributes.c     | 58 +----------
 7 files changed, 125 insertions(+), 262 deletions(-)

diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
index 309634c1cc20..22c198680903 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
@@ -484,6 +484,103 @@ int hp_convert_hexstr_to_str(const char *input, u32 input_len, char **str, int *
 	return ret;
 }
 
+/**
+ * hp_get_common_data_from_package() - Parse the package elements shared
+ * by every attribute type (PATH..SECURITY_LEVEL)
+ * @obj: ACPI object package for this attribute instance
+ * @obj_count: Number of elements in @obj
+ * @elem: Current position in @obj; advanced in place when PREREQUISITES
+ *	  consumes additional array elements
+ * @eloc: Current common-element locator; advanced in place when
+ *	  PREREQUISITES_SIZE is zero, since PREREQUISITES is then omitted
+ *	  by BIOS
+ * @int_value: Integer value already decoded by the caller for *@eloc,
+ *	       when applicable
+ * @str_value: String value already decoded by the caller for *@eloc, when
+ *	       applicable; reused and reset to NULL while walking
+ *	       PREREQUISITES, same as the caller does with its own copy
+ * @common: Destination common_data struct for this attribute instance
+ *
+ * Called by each type's own hp_populate_*_elements_from_package()
+ * instead of duplicating this parsing per type, since every BIOS
+ * attribute package uses the same layout for these elements (see
+ * struct common_data).
+ *
+ * Return: 0 on success, or -EINVAL if @obj is too small for the
+ * declared PREREQUISITES_SIZE.
+ */
+int hp_get_common_data_from_package(union acpi_object *obj, int obj_count,
+				    int *elem, int *eloc, u32 int_value,
+				    char **str_value, struct common_data *common)
+{
+	int value_len;
+	int reqs;
+	int size;
+
+	switch (*eloc) {
+	case PATH:
+		strscpy(common->path, *str_value);
+		break;
+	case IS_READONLY:
+		common->is_readonly = int_value;
+		break;
+	case DISPLAY_IN_UI:
+		common->display_in_ui = int_value;
+		break;
+	case REQUIRES_PHYSICAL_PRESENCE:
+		common->requires_physical_presence = int_value;
+		break;
+	case SEQUENCE:
+		common->sequence = int_value;
+		break;
+	case PREREQUISITES_SIZE:
+		if (int_value > MAX_PREREQUISITES_SIZE) {
+			pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
+			int_value = MAX_PREREQUISITES_SIZE;
+		}
+		common->prerequisites_size = int_value;
+
+		/*
+		 * This step is needed to keep the expected
+		 * element list pointing to the right obj[elem].type
+		 * when the size is zero. PREREQUISITES
+		 * object is omitted by BIOS when the size is
+		 * zero.
+		 */
+		if (common->prerequisites_size == 0)
+			(*eloc)++;
+		break;
+	case PREREQUISITES:
+		size = min_t(u32, common->prerequisites_size, MAX_PREREQUISITES_SIZE);
+
+		for (reqs = 0; reqs < size; reqs++) {
+			if (*elem + reqs >= obj_count) {
+				pr_err("Error elem-objects package is too small\n");
+				return -EINVAL;
+			}
+
+			if (hp_convert_hexstr_to_str(obj[*elem + reqs].string.pointer,
+						     obj[*elem + reqs].string.length,
+						     str_value, &value_len))
+				continue;
+
+			strscpy(common->prerequisites[reqs], *str_value);
+			kfree(*str_value);
+			*str_value = NULL;
+		}
+		if (size)
+			*elem += size - 1;
+		break;
+	case SECURITY_LEVEL:
+		common->security_level = int_value;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 /* map output size to the corresponding WMI method id */
 int hp_encode_outsize_for_pvsz(int outsize)
 {
diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.h b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.h
index ac57d6eab4c3..94619c034187 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.h
+++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.h
@@ -493,5 +493,8 @@ void hp_friendly_user_name_update(char *path, const char *attr_name,
 				  char *attr_display, int attr_size);
 int hp_wmi_error_and_message(int error_code);
 int hp_get_common_data_from_buffer(u8 **buffer_ptr, u32 *buffer_size, struct common_data *common);
+int hp_get_common_data_from_package(union acpi_object *obj, int obj_count,
+				    int *elem, int *eloc, u32 int_value,
+				    char **str_value, struct common_data *common);
 
 #endif
diff --git a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
index 446dd18d2cee..8f1ecbf127bc 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
@@ -132,7 +132,6 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
 	u32 size = 0;
 	u32 int_value = 0;
 	int elem = 0;
-	int reqs;
 	int pos_values;
 	int ret;
 	int eloc;
@@ -176,64 +175,18 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
 		case VALUE:
 			break;
 		case PATH:
-			strscpy(enum_data->common.path, str_value);
-			break;
 		case IS_READONLY:
-			enum_data->common.is_readonly = int_value;
-			break;
 		case DISPLAY_IN_UI:
-			enum_data->common.display_in_ui = int_value;
-			break;
 		case REQUIRES_PHYSICAL_PRESENCE:
-			enum_data->common.requires_physical_presence = int_value;
-			break;
 		case SEQUENCE:
-			enum_data->common.sequence = int_value;
-			break;
 		case PREREQUISITES_SIZE:
-			if (int_value > MAX_PREREQUISITES_SIZE) {
-				pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
-				int_value = MAX_PREREQUISITES_SIZE;
-			}
-			enum_data->common.prerequisites_size = int_value;
-
-			/*
-			 * This step is needed to keep the expected
-			 * element list pointing to the right obj[elem].type
-			 * when the size is zero. PREREQUISITES
-			 * object is omitted by BIOS when the size is
-			 * zero.
-			 */
-			if (int_value == 0)
-				eloc++;
-			break;
-
 		case PREREQUISITES:
-			size = min_t(u32, enum_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
-			for (reqs = 0; reqs < size; reqs++) {
-				if (elem + reqs >= enum_obj_count) {
-					pr_err("Error enum-objects package is too small\n");
-					return -EINVAL;
-				}
-
-				ret = hp_convert_hexstr_to_str(enum_obj[elem + reqs].string.pointer,
-							       enum_obj[elem + reqs].string.length,
-							       &str_value, &value_len);
-
-				if (ret)
-					return -EINVAL;
-
-				strscpy(enum_data->common.prerequisites[reqs], str_value);
-
-				kfree(str_value);
-				str_value = NULL;
-			}
-			if (size)
-				elem += size - 1;
-			break;
-
 		case SECURITY_LEVEL:
-			enum_data->common.security_level = int_value;
+			ret = hp_get_common_data_from_package(enum_obj, enum_obj_count,
+							      &elem, &eloc, int_value, &str_value,
+							      &enum_data->common);
+			if (ret)
+				return ret;
 			break;
 
 		case ENUM_CURRENT_VALUE:
diff --git a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
index a27907066448..f2774eff613b 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
@@ -145,9 +145,7 @@ static int hp_populate_integer_elements_from_package(union acpi_object *integer_
 	int ret;
 	u32 int_value = 0;
 	int elem;
-	int reqs;
 	int eloc;
-	int size;
 	struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id];
 
 	if (!integer_obj)
@@ -192,63 +190,18 @@ static int hp_populate_integer_elements_from_package(union acpi_object *integer_
 			integer_data->current_value = int_value;
 			break;
 		case PATH:
-			strscpy(integer_data->common.path, str_value);
-			break;
 		case IS_READONLY:
-			integer_data->common.is_readonly = int_value;
-			break;
 		case DISPLAY_IN_UI:
-			integer_data->common.display_in_ui = int_value;
-			break;
 		case REQUIRES_PHYSICAL_PRESENCE:
-			integer_data->common.requires_physical_presence = int_value;
-			break;
 		case SEQUENCE:
-			integer_data->common.sequence = int_value;
-			break;
 		case PREREQUISITES_SIZE:
-			if (int_value > MAX_PREREQUISITES_SIZE) {
-				pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
-				int_value = MAX_PREREQUISITES_SIZE;
-			}
-			integer_data->common.prerequisites_size = int_value;
-
-			/*
-			 * This step is needed to keep the expected
-			 * element list pointing to the right obj[elem].type
-			 * when the size is zero. PREREQUISITES
-			 * object is omitted by BIOS when the size is
-			 * zero.
-			 */
-			if (integer_data->common.prerequisites_size == 0)
-				eloc++;
-			break;
 		case PREREQUISITES:
-			size = min_t(u32, integer_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
-
-			for (reqs = 0; reqs < size; reqs++) {
-				if (elem + reqs >= integer_obj_count) {
-					pr_err("Error elem-objects package is too small\n");
-					return -EINVAL;
-				}
-
-				ret = hp_convert_hexstr_to_str(integer_obj[elem + reqs].string.pointer,
-							       integer_obj[elem + reqs].string.length,
-							       &str_value, &value_len);
-
-				if (ret)
-					continue;
-
-				strscpy(integer_data->common.prerequisites[reqs], str_value);
-				kfree(str_value);
-				str_value = NULL;
-			}
-			if (size)
-				elem += size - 1;
-			break;
-
 		case SECURITY_LEVEL:
-			integer_data->common.security_level = int_value;
+			ret = hp_get_common_data_from_package(integer_obj, integer_obj_count,
+							      &elem, &eloc, int_value, &str_value,
+							      &integer_data->common);
+			if (ret)
+				return ret;
 			break;
 		case INT_LOWER_BOUND:
 			integer_data->lower_bound = int_value;
diff --git a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
index 5bf8d40bdf81..95fca0919f1f 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
@@ -130,11 +130,9 @@ static int hp_populate_ordered_list_elements_from_package(union acpi_object *ord
 	char *str_value = NULL;
 	int value_len = 0;
 	int ret;
-	u32 size;
 	u32 int_value = 0;
 	int elem;
 	int olist_elem;
-	int reqs;
 	int eloc;
 	char *tmpstr = NULL;
 	char *part_tmp = NULL;
@@ -180,64 +178,18 @@ static int hp_populate_ordered_list_elements_from_package(union acpi_object *ord
 			replace_char_str(ordered_list_data->current_value, COMMA_SEP, SEMICOLON_SEP);
 			break;
 		case PATH:
-			strscpy(ordered_list_data->common.path, str_value);
-			break;
 		case IS_READONLY:
-			ordered_list_data->common.is_readonly = int_value;
-			break;
 		case DISPLAY_IN_UI:
-			ordered_list_data->common.display_in_ui = int_value;
-			break;
 		case REQUIRES_PHYSICAL_PRESENCE:
-			ordered_list_data->common.requires_physical_presence = int_value;
-			break;
 		case SEQUENCE:
-			ordered_list_data->common.sequence = int_value;
-			break;
 		case PREREQUISITES_SIZE:
-			if (int_value > MAX_PREREQUISITES_SIZE) {
-				pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
-				int_value = MAX_PREREQUISITES_SIZE;
-			}
-			ordered_list_data->common.prerequisites_size = int_value;
-
-			/*
-			 * This step is needed to keep the expected
-			 * element list pointing to the right obj[elem].type
-			 * when the size is zero. PREREQUISITES
-			 * object is omitted by BIOS when the size is
-			 * zero.
-			 */
-			if (int_value == 0)
-				eloc++;
-			break;
 		case PREREQUISITES:
-			size = min_t(u32, ordered_list_data->common.prerequisites_size,
-				     MAX_PREREQUISITES_SIZE);
-			for (reqs = 0; reqs < size; reqs++) {
-				if (elem + reqs >= order_obj_count) {
-					pr_err("Error elem-objects package is too small\n");
-					return -EINVAL;
-				}
-
-				ret = hp_convert_hexstr_to_str(order_obj[elem + reqs].string.pointer,
-							       order_obj[elem + reqs].string.length,
-							       &str_value, &value_len);
-
-				if (ret)
-					continue;
-
-				strscpy(ordered_list_data->common.prerequisites[reqs], str_value);
-
-				kfree(str_value);
-				str_value = NULL;
-			}
-			if (size)
-				elem += size - 1;
-			break;
-
 		case SECURITY_LEVEL:
-			ordered_list_data->common.security_level = int_value;
+			ret = hp_get_common_data_from_package(order_obj, order_obj_count,
+							      &elem, &eloc, int_value, &str_value,
+							      &ordered_list_data->common);
+			if (ret)
+				return ret;
 			break;
 
 		case ORD_LIST_SIZE:
diff --git a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
index a9e178637416..95fa0aeba920 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
@@ -224,7 +224,6 @@ static int hp_populate_password_elements_from_package(union acpi_object *passwor
 	u32 size;
 	u32 int_value = 0;
 	int elem;
-	int reqs;
 	int eloc;
 	int pos_values;
 	struct password_data *password_data = &bioscfg_drv.password_data[instance_id];
@@ -268,64 +267,18 @@ static int hp_populate_password_elements_from_package(union acpi_object *passwor
 		case VALUE:
 			break;
 		case PATH:
-			strscpy(password_data->common.path, str_value);
-			break;
 		case IS_READONLY:
-			password_data->common.is_readonly = int_value;
-			break;
 		case DISPLAY_IN_UI:
-			password_data->common.display_in_ui = int_value;
-			break;
 		case REQUIRES_PHYSICAL_PRESENCE:
-			password_data->common.requires_physical_presence = int_value;
-			break;
 		case SEQUENCE:
-			password_data->common.sequence = int_value;
-			break;
 		case PREREQUISITES_SIZE:
-			if (int_value > MAX_PREREQUISITES_SIZE) {
-				pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
-				int_value = MAX_PREREQUISITES_SIZE;
-			}
-			password_data->common.prerequisites_size = int_value;
-
-			/* This step is needed to keep the expected
-			 * element list pointing to the right obj[elem].type
-			 * when the size is zero. PREREQUISITES
-			 * object is omitted by BIOS when the size is
-			 * zero.
-			 */
-			if (int_value == 0)
-				eloc++;
-			break;
 		case PREREQUISITES:
-			size = min_t(u32, password_data->common.prerequisites_size,
-				     MAX_PREREQUISITES_SIZE);
-
-			for (reqs = 0; reqs < size; reqs++) {
-				if (elem + reqs >= password_obj_count) {
-					pr_err("Error elem-objects package is too small\n");
-					return -EINVAL;
-				}
-
-				ret = hp_convert_hexstr_to_str(password_obj[elem + reqs].string.pointer,
-							       password_obj[elem + reqs].string.length,
-							       &str_value, &value_len);
-
-				if (ret)
-					break;
-
-				strscpy(password_data->common.prerequisites[reqs], str_value);
-
-				kfree(str_value);
-				str_value = NULL;
-
-			}
-			if (size)
-				elem += size - 1;
-			break;
 		case SECURITY_LEVEL:
-			password_data->common.security_level = int_value;
+			ret = hp_get_common_data_from_package(password_obj, password_obj_count,
+							      &elem, &eloc, int_value, &str_value,
+							      &password_data->common);
+			if (ret)
+				return ret;
 			break;
 		case PSWD_MIN_LENGTH:
 			password_data->min_password_length = int_value;
diff --git a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
index f3dfba270f7e..e9bfbef8a3a4 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
@@ -135,9 +135,7 @@ static int hp_populate_string_elements_from_package(union acpi_object *string_ob
 	int ret = 0;
 	u32 int_value = 0;
 	int elem;
-	int reqs;
 	int eloc;
-	int size;
 	struct string_data *string_data = &bioscfg_drv.string_data[instance_id];
 
 	if (!string_obj)
@@ -181,64 +179,18 @@ static int hp_populate_string_elements_from_package(union acpi_object *string_ob
 			strscpy(string_data->current_value, str_value);
 			break;
 		case PATH:
-			strscpy(string_data->common.path, str_value);
-			break;
 		case IS_READONLY:
-			string_data->common.is_readonly = int_value;
-			break;
 		case DISPLAY_IN_UI:
-			string_data->common.display_in_ui = int_value;
-			break;
 		case REQUIRES_PHYSICAL_PRESENCE:
-			string_data->common.requires_physical_presence = int_value;
-			break;
 		case SEQUENCE:
-			string_data->common.sequence = int_value;
-			break;
 		case PREREQUISITES_SIZE:
-			if (int_value > MAX_PREREQUISITES_SIZE) {
-				pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
-				int_value = MAX_PREREQUISITES_SIZE;
-			}
-			string_data->common.prerequisites_size = int_value;
-
-			/*
-			 * This step is needed to keep the expected
-			 * element list pointing to the right obj[elem].type
-			 * when the size is zero. PREREQUISITES
-			 * object is omitted by BIOS when the size is
-			 * zero.
-			 */
-			if (string_data->common.prerequisites_size == 0)
-				eloc++;
-			break;
 		case PREREQUISITES:
-			size = min_t(u32, string_data->common.prerequisites_size,
-				     MAX_PREREQUISITES_SIZE);
-
-			for (reqs = 0; reqs < size; reqs++) {
-				if (elem + reqs >= string_obj_count) {
-					pr_err("Error elem-objects package is too small\n");
-					return -EINVAL;
-				}
-
-				ret = hp_convert_hexstr_to_str(string_obj[elem + reqs].string.pointer,
-							       string_obj[elem + reqs].string.length,
-							       &str_value, &value_len);
-
-				if (ret)
-					continue;
-
-				strscpy(string_data->common.prerequisites[reqs], str_value);
-				kfree(str_value);
-				str_value = NULL;
-			}
-			if (size)
-				elem += size - 1;
-			break;
-
 		case SECURITY_LEVEL:
-			string_data->common.security_level = int_value;
+			ret = hp_get_common_data_from_package(string_obj, string_obj_count,
+							      &elem, &eloc, int_value, &str_value,
+							      &string_data->common);
+			if (ret)
+				return ret;
 			break;
 		case STR_MIN_LENGTH:
 			string_data->min_length = int_value;
-- 
2.55.0


                 reply	other threads:[~2026-09-05 21:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260905214801.76265-1-meatuni001@gmail.com \
    --to=meatuni001@gmail.com \
    --cc=hansg@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=jorge.lopez2@hp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox