Exemplo n.º 1
0
/**
 * Find, open, identify, and initialize an I/O context mapping the CFE NVRAM
 * device.
 * 
 * @param[out]	iocfe		On success, an I/O context mapping the CFE NVRAM
 *				device.
 * @param[out]	cls		On success, the identified NVRAM data format
 *				class.
 *
 * @retval 0		success. the caller inherits ownership of @p iocfe.
 * @retval non-zero	if no usable CFE NVRAM device can be found, a standard
 *			unix error will be returned.
 */
int
bcm_nvram_find_cfedev(struct bcm_nvram_iocfe *iocfe,
    bhnd_nvram_data_class **cls)
{
	char	*dname;
	int	 devinfo;
	int	 error, result;

	for (u_int i = 0; i < nitems(nvram_cfe_fmts); i++) {
		*cls = nvram_cfe_fmts[i];

		for (u_int j = 0; j < nitems(nvram_cfe_devs); j++) {
			dname = nvram_cfe_devs[j];

			/* Does the device exist? */
			if ((devinfo = cfe_getdevinfo(dname)) < 0) {
				if (devinfo != CFE_ERR_DEVNOTFOUND) {
					BCM_ERR("cfe_getdevinfo(%s) failed: "
					    "%d\n", dname, devinfo);
				}

				continue;
			}

			/* Open for reading */
			if ((error = bcm_nvram_iocfe_init(iocfe, dname)))
				continue;

			/* Probe */
			result = bhnd_nvram_data_probe(*cls, &iocfe->io);
			if (result <= 0) {
				/* Found a supporting NVRAM data class */
				return (0);
			}

			/* Keep searching */
			bhnd_nvram_io_free(&iocfe->io);
		}
	}

	return (ENODEV);
}
Exemplo n.º 2
0
/**
 * Initialize a new CFE device-backed I/O context.
 *
 * The caller is responsible for releasing all resources held by the returned
 * I/O context via bhnd_nvram_io_free().
 * 
 * @param[out]	io	On success, will be initialized as an I/O context for
 *			CFE device @p dname.
 * @param	dname	The name of the CFE device to be opened for reading.
 *
 * @retval 0		success.
 * @retval non-zero	if opening @p dname otherwise fails, a standard unix
 *			error will be returned.
 */
static int
bcm_nvram_iocfe_init(struct bcm_nvram_iocfe *iocfe, char *dname)
{
	nvram_info_t		 nvram_info;
	int			 cerr, devinfo, dtype, rlen;
	int64_t			 nv_offset;
	u_int			 nv_size;
	bool			 req_blk_erase;
	int			 error;

	iocfe->io.iops = &bhnd_nvram_iocfe_ops;
	iocfe->dname = dname;

	/* Try to open the device */
	iocfe->fd = cfe_open(dname);
	if (iocfe->fd <= 0) {
		IOCFE_LOG(iocfe, "cfe_open() failed: %d\n", iocfe->fd);

		return (ENXIO);
	}

	/* Try to fetch device info */
	if ((devinfo = cfe_getdevinfo(iocfe->dname)) < 0) {
		IOCFE_LOG(iocfe, "cfe_getdevinfo() failed: %d\n", devinfo);
		error = ENXIO;
		goto failed;
	}

	/* Verify device type */
	dtype = devinfo & CFE_DEV_MASK;
	switch (dtype) {
	case CFE_DEV_FLASH:
	case CFE_DEV_NVRAM:
		/* Valid device type */
		break;
	default:
		IOCFE_LOG(iocfe, "unknown device type: %d\n", dtype);
		error = ENXIO;
		goto failed;
	}

	/* Try to fetch nvram info from CFE */
	cerr = cfe_ioctl(iocfe->fd, IOCTL_NVRAM_GETINFO,
	    (unsigned char *)&nvram_info, sizeof(nvram_info), &rlen, 0);
	if (cerr == CFE_OK) {
		/* Sanity check the result; must not be a negative integer */
		if (nvram_info.nvram_size < 0 ||
		    nvram_info.nvram_offset < 0)
		{
			IOCFE_LOG(iocfe, "invalid NVRAM layout (%d/%d)\n",
			    nvram_info.nvram_size, nvram_info.nvram_offset);
			error = ENXIO;
			goto failed;
		}

		nv_offset	= nvram_info.nvram_offset;
		nv_size		= nvram_info.nvram_size;
		req_blk_erase	= (nvram_info.nvram_eraseflg != 0);
	} else if (cerr != CFE_OK && cerr != CFE_ERR_INV_COMMAND) {
		IOCFE_LOG(iocfe, "IOCTL_NVRAM_GETINFO failed: %d\n", cerr);
		error = ENXIO;
		goto failed;
	}

	/* Fall back on flash info.
	 * 
	 * This is known to be required on the Asus RT-N53 (CFE 5.70.55.33, 
	 * BBP 1.0.37, BCM5358UB0), where IOCTL_NVRAM_GETINFO returns
	 * CFE_ERR_INV_COMMAND.
	 */
	if (cerr == CFE_ERR_INV_COMMAND) {
		flash_info_t fi;

		cerr = cfe_ioctl(iocfe->fd, IOCTL_FLASH_GETINFO,
		    (unsigned char *)&fi, sizeof(fi), &rlen, 0);

		if (cerr != CFE_OK) {
			IOCFE_LOG(iocfe, "IOCTL_FLASH_GETINFO failed %d\n",
			    cerr);
			error = ENXIO;
			goto failed;
		}

		nv_offset	= 0x0;
		nv_size		= fi.flash_size;
		req_blk_erase	= !(fi.flash_flags & FLASH_FLAG_NOERASE);
	}

	
	/* Verify that the full NVRAM layout can be represented via size_t */
	if (nv_size > SIZE_MAX || SIZE_MAX - nv_size < nv_offset) {
		IOCFE_LOG(iocfe, "invalid NVRAM layout (%#x/%#jx)\n",
		    nv_size, (intmax_t)nv_offset);
		error = ENXIO;
		goto failed;
	}

	iocfe->offset = nv_offset;
	iocfe->size = nv_size;
	iocfe->req_blk_erase = req_blk_erase;

	return (CFE_OK);

failed:
	if (iocfe->fd >= 0)
		cfe_close(iocfe->fd);

	return (error);
}
Exemplo n.º 3
0
/*  *********************************************************************
    *  ui_cmd_flashop(cmd,argc,argv)
    *  
    *  The 'flashop' command lives here.  This command does a variety
    *  of flash operations over a range of bytes:
    *
    *  erase, protect, unprotect
    *  
    *  Input parameters: 
    *  	   cmd - command table entry
    *  	   argc,argv - parameters
    *  	   
    *  Return value:
    *  	   0 if ok
    *  	   else error
    ********************************************************************* */
static int ui_cmd_flashop(ui_cmdline_t *cmd,int argc,char *argv[])
{
    int fd;
    int res;
    char *flashdev;
    int devtype;
    flash_info_t flashinfo;
    int erase;
    int protect;
    int unprotect;
    int retlen;
    unsigned int startaddr = 0;
    unsigned int endaddr = 0;
    char *x;
    int all;
    flash_range_t range;

    flashdev = cmd_getarg(cmd,0);

    if (!flashdev) flashdev = "flash0";

    /*
     * Make sure it's a flash device.
     */

    res = cfe_getdevinfo(flashdev);
    if (res < 0) {
        return ui_showerror(CFE_ERR_DEVNOTFOUND,flashdev);
        }

    devtype = res & CFE_DEV_MASK;

    if (res != CFE_DEV_FLASH) {
        xprintf("Device '%s' is not a flash device.\n",flashdev);
        return CFE_ERR_INV_PARAM;
    }

    protect = cmd_sw_isset(cmd,"-protect");
    unprotect = cmd_sw_isset(cmd,"-unprotect");
    erase = cmd_sw_isset(cmd,"-erase");

    if (protect == 1) {
        if (erase || unprotect)
            {
            xprintf("Conflicting options\n");
            return CFE_ERR_INV_PARAM;
            }
    }

    if (unprotect == 1) {
        if (erase || protect)
            {
            xprintf("Conflicting options\n");
            return CFE_ERR_INV_PARAM;
            }
    }

    if (erase == 1) {
        if (unprotect || protect)
            {
            xprintf("Conflicting options\n");
            return CFE_ERR_INV_PARAM;
            }
    }

    if (erase == 0 && protect == 0 && unprotect == 0) {
        xprintf("Need one of following options: -erase -protect -unprotect\n");
        return CFE_ERR_INV_PARAM;
    }


    fd = cfe_open(flashdev);
    if (fd < 0) {
	xprintf("Could not open device '%s'\n",flashdev);
	return CFE_ERR_DEVNOTFOUND;
	}

    res = cfe_ioctl(fd,IOCTL_FLASH_GETINFO,(uint8_t *) &flashinfo,sizeof(flash_info_t),&retlen,0);
    if (res != 0) {
        cfe_close (fd);
        return CFE_ERR_IOERR;
    }

    all = cmd_sw_isset(cmd,"-all");
    if (all == 0) {
        if (cmd_sw_value(cmd,"-startaddr",&x)) {
            startaddr = XTOI(x);
            }
        else {
            xprintf("Need option: -startaddr\n");
            cfe_close (fd);
            return CFE_ERR_INV_PARAM;
            }

        if (cmd_sw_value(cmd,"-endaddr",&x)) {
            endaddr = XTOI(x);
            }
        else {
            xprintf("Need option: -endaddr\n");
            cfe_close (fd);
            return CFE_ERR_INV_PARAM;
            }

        if (startaddr > endaddr) {
            xprintf("Final offset (endaddr) must not be less than startaddr \n");
            cfe_close (fd);
            return CFE_ERR_INV_PARAM;
            }
       
        /* Make sure endaddr is within flash */

        if (endaddr >= flashinfo.flash_size) {
            xprintf("Final offset (endaddr) must less than 0x%x\n", flashinfo.flash_size);
            cfe_close (fd);
            return CFE_ERR_INV_PARAM;
        }

        /* We got here, so params are OK  */
        range.range_base = startaddr;
        range.range_length = endaddr-startaddr;
    }
    else {
        range.range_base = 0;
        range.range_length = flashinfo.flash_size;
    }

    if (erase)
        {
        res = cfe_ioctl(fd, IOCTL_FLASH_ERASE_RANGE,
            (void *) &range, NULL, NULL, NULL);
        }

    else if (protect)
        {
        res = cfe_ioctl(fd, IOCTL_FLASH_PROTECT_RANGE,
            (void *) &range, NULL, NULL, NULL);
        }

    else if (unprotect)
        {
        res = cfe_ioctl(fd, IOCTL_FLASH_UNPROTECT_RANGE,
            (void *) &range, NULL, NULL, NULL);
        }

    if (res != 0) {
        printf("ioctl error\n");
        }

    cfe_close (fd);
    return 0;
}