On 24. 2. 1., Dmitry Salychev wrote:

Hi,

Jung-uk Kim <j...@freebsd.org> writes:

On 24. 1. 31., Baptiste Daroussin wrote:
Hello,
Either this one or the previous import is breaking arm64 build
--- acpi_iort.o ---
/home/bapt/worktrees/main/sys/arm64/acpica/acpi_iort.c:103:4: error: field
'data' with variable sized type 'union (unnamed union at
/home/bapt/worktrees/main/sys/arm64/acpica/acpi_iort.c:98:2
)' not at the end of a struct or class is a GNU extension
[-Werror,-Wgnu-variable-sized-type-not-at-end]
    103 |         } data;
          |           ^

Sorry for the breakage.  I will fix it soon.

BTW, this code was added by this:

https://reviews.freebsd.org/D31267

It seems struct iort_named_component was a hack, which duplicated
ACPI_IORT_NAMED_COMPONENT but with a fixed length field
DeviceName[32]. Is it really necessary?

Jung-uk Kim

I'm struggling to understand (a) how the entire anonymous "data" union
was added by https://reviews.freebsd.org/D31267 as was "named_comp"
only and (b) what the problem with the "struct iort_named_component" really
is as ACPI_IORT_ROOT_COMPLEX and ACPI_IORT_SMMU were re-defined as
incomplete types in the new version of ACPICA. Everything is compilable
as it used to be with the attached patch.

FYI, ACPICA 20230331 dropped support for ANSI C (C89) and minimum requirement is C99 now. One of the first feature they used was the variable-length array, which replaced "foo[1]" hack. Previously, "sizeof(struct bar)" was not real size because of the (fake variable-length) array at the end of it. Now they removed the hack and started using real variable-length arrays. I believe the hack in acpi_iort.c was to work around the fake 1-byte array but it does not work any more because all ACPI_IORT_* are now using correct VLA. So, the cleanest way to fix this is using ACPI_IORT_NAMED_COMPONENT instead of "struct iort_named_component" (see attached PoC patch), which also eliminates the need for DeviceName[32].

Jung-uk Kim
diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
index a0e24788b775..298679d05c7d 100644
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -74,14 +74,6 @@ struct iort_its_entry {
 	int			pxm;
 };
 
-struct iort_named_component
-{
-	UINT32                  NodeFlags;
-	UINT64                  MemoryProperties;
-	UINT8                   MemoryAddressLimit;
-	char                    DeviceName[32]; /* Path of namespace object */
-};
-
 /*
  * IORT node. Each node has some device specific data depending on the
  * type of the node. The node can also have a set of mappings, OR in
@@ -103,7 +95,7 @@ struct iort_node {
 		ACPI_IORT_ROOT_COMPLEX		pci_rc;	/* PCI root complex */
 		ACPI_IORT_SMMU			smmu;
 		ACPI_IORT_SMMU_V3		smmu_v3;
-		struct iort_named_component	named_comp;
+		ACPI_IORT_NAMED_COMPONENT	named_comp;
 	} data;
 };
 
@@ -325,6 +317,7 @@ iort_add_nodes(ACPI_IORT_NODE *node_entry, u_int node_offset)
 	ACPI_IORT_SMMU_V3 *smmu_v3;
 	ACPI_IORT_NAMED_COMPONENT *named_comp;
 	struct iort_node *node;
+	size_t name_len;
 
 	node = malloc(sizeof(*node), M_DEVBUF, M_WAITOK | M_ZERO);
 	node->type =  node_entry->Type;
@@ -360,10 +353,14 @@ iort_add_nodes(ACPI_IORT_NODE *node_entry, u_int node_offset)
 		memcpy(&node->data.named_comp, named_comp, sizeof(*named_comp));
 
 		/* Copy name of the node separately. */
+		name_len = node_entry->Length;
+		name_len -= ACPI_OFFSET(ACPI_IORT_NAMED_COMPONENT, DeviceName);
+		name_len = strnlen(node->data.named_comp.DeviceName, name_len);
+		named_comp = realloc(named_comp, sizeof(*node) + name_len + 1,
+		    M_DEVBUF, M_WAITOK | M_ZERO);
 		strncpy(node->data.named_comp.DeviceName,
-		    named_comp->DeviceName,
-		    sizeof(node->data.named_comp.DeviceName));
-		node->data.named_comp.DeviceName[31] = 0;
+		    named_comp->DeviceName, name_len + 1);
+		node->data.named_comp.DeviceName[name_len] = 0;
 
 		iort_copy_data(node, node_entry);
 		TAILQ_INSERT_TAIL(&named_nodes, node, next);

Reply via email to