Module Name:    src
Committed By:   jmcneill
Date:           Fri May 26 18:56:27 UTC 2017

Modified Files:
        src/sys/dev/fdt: fdt_subr.c fdtvar.h

Log Message:
Handle reg values beyond 4GB for platforms with 32-bit bus_addr_t.

fdtbus_get_reg will do a range check and return ERANGE if addr+size
exceeds 4GB.

Add fdtbus_get_reg64 to allow for fetching raw values w/o range check.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/fdt/fdt_subr.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/fdt/fdtvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/fdt/fdt_subr.c
diff -u src/sys/dev/fdt/fdt_subr.c:1.10 src/sys/dev/fdt/fdt_subr.c:1.11
--- src/sys/dev/fdt/fdt_subr.c:1.10	Sat Apr 29 12:38:26 2017
+++ src/sys/dev/fdt/fdt_subr.c	Fri May 26 18:56:27 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_subr.c,v 1.10 2017/04/29 12:38:26 jmcneill Exp $ */
+/* $NetBSD: fdt_subr.c,v 1.11 2017/05/26 18:56:27 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.10 2017/04/29 12:38:26 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.11 2017/05/26 18:56:27 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -159,27 +159,47 @@ fdtbus_get_path(int phandle, char *buf, 
 int
 fdtbus_get_reg(int phandle, u_int index, bus_addr_t *paddr, bus_size_t *psize)
 {
-	bus_addr_t addr;
-	bus_size_t size;
+	uint64_t addr, size;
+	int error;
+
+	error = fdtbus_get_reg64(phandle, index, &addr, &size);
+	if (error)
+		return error;
+
+	if (sizeof(bus_addr_t) == 4 && (addr + size) > 0x100000000)
+		return ERANGE;
+
+	if (paddr)
+		*paddr = (bus_addr_t)addr;
+	if (psize)
+		*psize = (bus_size_t)size;
+
+	return 0;
+}
+
+int
+fdtbus_get_reg64(int phandle, u_int index, uint64_t *paddr, uint64_t *psize)
+{
+	uint64_t addr, size;
 	const uint8_t *buf;
 	int len;
 
 	const int addr_cells = fdtbus_get_addr_cells(phandle);
 	const int size_cells = fdtbus_get_size_cells(phandle);
 	if (addr_cells == -1 || size_cells == -1)
-		return -1;
+		return EINVAL;
 
 	buf = fdt_getprop(fdtbus_get_data(),
 	    fdtbus_phandle2offset(phandle), "reg", &len);
 	if (buf == NULL || len <= 0)
-		return -1;
+		return EINVAL;
 
 	const u_int reglen = size_cells * 4 + addr_cells * 4;
 	if (reglen == 0)
-		return -1;
+		return EINVAL;
 
 	if (index >= len / reglen)
-		return -1;
+		return ENXIO;
 
 	switch (addr_cells) {
 	case 0:

Index: src/sys/dev/fdt/fdtvar.h
diff -u src/sys/dev/fdt/fdtvar.h:1.16 src/sys/dev/fdt/fdtvar.h:1.17
--- src/sys/dev/fdt/fdtvar.h:1.16	Sat Apr 29 12:49:05 2017
+++ src/sys/dev/fdt/fdtvar.h	Fri May 26 18:56:27 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: fdtvar.h,v 1.16 2017/04/29 12:49:05 jmcneill Exp $ */
+/* $NetBSD: fdtvar.h,v 1.17 2017/05/26 18:56:27 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -182,6 +182,7 @@ int		fdtbus_register_dma_controller(devi
 		    const struct fdtbus_dma_controller_func *);
 
 int		fdtbus_get_reg(int, u_int, bus_addr_t *, bus_size_t *);
+int		fdtbus_get_reg64(int, u_int, uint64_t *, uint64_t *);
 int		fdtbus_get_phandle(int, const char *);
 int		fdtbus_get_phandle_from_native(int);
 i2c_tag_t	fdtbus_get_i2c_tag(int);

Reply via email to