Rename and move gpiobus_alloc_ivars() and gpiobus_free_ivars() so they can
be used on non FDT systems. This prevents access to uninitialized memory on drivers that try to access pin flags on non FDT systems.
This commit is contained in:
parent
4fc4286fbc
commit
5019630122
@ -195,6 +195,39 @@ gpiobus_init_softc(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
|
||||
{
|
||||
|
||||
/* Allocate pins and flags memory. */
|
||||
devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (devi->pins == NULL)
|
||||
return (ENOMEM);
|
||||
devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (devi->flags == NULL) {
|
||||
free(devi->pins, M_DEVBUF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
gpiobus_free_ivars(struct gpiobus_ivar *devi)
|
||||
{
|
||||
|
||||
if (devi->flags) {
|
||||
free(devi->flags, M_DEVBUF);
|
||||
devi->flags = NULL;
|
||||
}
|
||||
if (devi->pins) {
|
||||
free(devi->pins, M_DEVBUF);
|
||||
devi->pins = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
|
||||
{
|
||||
@ -206,29 +239,23 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
|
||||
if (mask & (1 << i))
|
||||
npins++;
|
||||
}
|
||||
|
||||
if (npins == 0) {
|
||||
device_printf(child, "empty pin mask\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
devi->npins = npins;
|
||||
devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
|
||||
if (!devi->pins)
|
||||
return (ENOMEM);
|
||||
|
||||
if (gpiobus_alloc_ivars(devi) != 0) {
|
||||
device_printf(child, "cannot allocate device ivars\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
npins = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
|
||||
if ((mask & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
if (i >= sc->sc_npins) {
|
||||
device_printf(child,
|
||||
"invalid pin %d, max: %d\n", i, sc->sc_npins - 1);
|
||||
free(devi->pins, M_DEVBUF);
|
||||
gpiobus_free_ivars(devi);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
@ -239,7 +266,7 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
|
||||
if (sc->sc_pins_mapped[i]) {
|
||||
device_printf(child,
|
||||
"warning: pin %d is already mapped\n", i);
|
||||
free(devi->pins, M_DEVBUF);
|
||||
gpiobus_free_ivars(devi);
|
||||
return (EINVAL);
|
||||
}
|
||||
sc->sc_pins_mapped[i] = 1;
|
||||
@ -299,10 +326,7 @@ gpiobus_detach(device_t dev)
|
||||
for (i = 0; i < ndevs; i++) {
|
||||
device_delete_child(dev, devlist[i]);
|
||||
devi = GPIOBUS_IVAR(devlist[i]);
|
||||
if (devi->pins) {
|
||||
free(devi->pins, M_DEVBUF);
|
||||
devi->pins = NULL;
|
||||
}
|
||||
gpiobus_free_ivars(devi);
|
||||
}
|
||||
free(devlist, M_TEMP);
|
||||
|
||||
|
@ -100,6 +100,8 @@ int gpio_check_flags(uint32_t, uint32_t);
|
||||
device_t gpiobus_attach_bus(device_t);
|
||||
int gpiobus_detach_bus(device_t);
|
||||
int gpiobus_init_softc(device_t);
|
||||
int gpiobus_alloc_ivars(struct gpiobus_ivar *);
|
||||
void gpiobus_free_ivars(struct gpiobus_ivar *);
|
||||
|
||||
extern driver_t gpiobus_driver;
|
||||
|
||||
|
@ -69,33 +69,6 @@ ofw_gpiobus_add_fdt_child(device_t bus, phandle_t child)
|
||||
return (childdev);
|
||||
}
|
||||
|
||||
static int
|
||||
ofw_gpiobus_alloc_ivars(struct gpiobus_ivar *dinfo)
|
||||
{
|
||||
|
||||
/* Allocate pins and flags memory. */
|
||||
dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (dinfo->pins == NULL)
|
||||
return (ENOMEM);
|
||||
dinfo->flags = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (dinfo->flags == NULL) {
|
||||
free(dinfo->pins, M_DEVBUF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ofw_gpiobus_free_ivars(struct gpiobus_ivar *dinfo)
|
||||
{
|
||||
|
||||
free(dinfo->flags, M_DEVBUF);
|
||||
free(dinfo->pins, M_DEVBUF);
|
||||
}
|
||||
|
||||
static int
|
||||
ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
phandle_t child)
|
||||
@ -152,7 +125,7 @@ ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
}
|
||||
|
||||
/* Allocate the child resources. */
|
||||
if (ofw_gpiobus_alloc_ivars(dinfo) != 0) {
|
||||
if (gpiobus_alloc_ivars(dinfo) != 0) {
|
||||
free(gpios, M_DEVBUF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
@ -172,7 +145,7 @@ ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
/* Read gpio-cells property for this GPIO controller. */
|
||||
if (OF_getencprop(gpio, "#gpio-cells", &cells,
|
||||
sizeof(cells)) < 0) {
|
||||
ofw_gpiobus_free_ivars(dinfo);
|
||||
gpiobus_free_ivars(dinfo);
|
||||
free(gpios, M_DEVBUF);
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -180,7 +153,7 @@ ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
/* Get the GPIO pin number and flags. */
|
||||
if (gpio_map_gpios(sc->sc_dev, child, gpio, cells,
|
||||
&gpios[i + 1], &dinfo->pins[j], &dinfo->flags[j]) != 0) {
|
||||
ofw_gpiobus_free_ivars(dinfo);
|
||||
gpiobus_free_ivars(dinfo);
|
||||
free(gpios, M_DEVBUF);
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -190,7 +163,7 @@ ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
device_printf(sc->sc_busdev,
|
||||
"invalid pin %d, max: %d\n",
|
||||
dinfo->pins[j], sc->sc_npins - 1);
|
||||
ofw_gpiobus_free_ivars(dinfo);
|
||||
gpiobus_free_ivars(dinfo);
|
||||
free(gpios, M_DEVBUF);
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -202,7 +175,7 @@ ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
|
||||
device_printf(sc->sc_busdev,
|
||||
"warning: pin %d is already mapped\n",
|
||||
dinfo->pins[j]);
|
||||
ofw_gpiobus_free_ivars(dinfo);
|
||||
gpiobus_free_ivars(dinfo);
|
||||
free(gpios, M_DEVBUF);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user