Пример #1
0
int
mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,
    uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
{
	struct mfi_ioc_passthru ioc;
	struct mfi_dcmd_frame *dcmd;
	int r;

	if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) ||
	    (mbox == NULL && mboxlen != 0)) {
		errno = EINVAL;
		return (-1);
	}

	bzero(&ioc, sizeof(ioc));
	dcmd = &ioc.ioc_frame;
	if (mbox)
		bcopy(mbox, dcmd->mbox, mboxlen);
	dcmd->header.cmd = MFI_CMD_DCMD;
	dcmd->header.timeout = 0;
	dcmd->header.flags = 0;
	dcmd->header.data_len = bufsize;
	dcmd->opcode = opcode;

	ioc.buf = buf;
	ioc.buf_size = bufsize;
	r = ioctl(fd, MFIIO_PASSTHRU, &ioc);
	if (r < 0)
		return (r);

	if (statusp != NULL)
		*statusp = dcmd->header.cmd_status;
	else if (dcmd->header.cmd_status != MFI_STAT_OK) {
		warnx("Command failed: %s",
		    mfi_status(dcmd->header.cmd_status));
		errno = EIO;
		return (-1);
	}
	return (0);
}
Пример #2
0
static int
flash_adapter(int ac, char **av)
{
	struct mfi_progress dummy;
	off_t offset;
	size_t nread;
	char *buf;
	struct stat sb;
	int error, fd, flash;
	uint8_t mbox[4], status;

	if (ac != 2) {
		warnx("flash: Firmware file required");
		return (EINVAL);
	}

	flash = open(av[1], O_RDONLY);
	if (flash < 0) {
		error = errno;
		warn("flash: Failed to open %s", av[1]);
		return (error);
	}

	buf = NULL;
	fd = -1;

	if (fstat(flash, &sb) < 0) {
		error = errno;
		warn("fstat(%s)", av[1]);
		goto error;
	}
	if (sb.st_size % 1024 != 0 || sb.st_size > 0x7fffffff) {
		warnx("Invalid flash file size");
		error = EINVAL;
		goto error;
	}

	fd = mfi_open(mfi_unit, O_RDWR);
	if (fd < 0) {
		error = errno;
		warn("mfi_open");
		goto error;
	}

	/* First, ask the firmware to allocate space for the flash file. */
	mbox_store_word(mbox, sb.st_size);
	mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_OPEN, NULL, 0, mbox, 4, &status);
	if (status != MFI_STAT_OK) {
		warnx("Failed to alloc flash memory: %s", mfi_status(status));
		error = EIO;
		goto error;
	}

	/* Upload the file 64k at a time. */
	buf = malloc(FLASH_BUF_SIZE);
	if (buf == NULL) {
		warnx("malloc failed");
		error = ENOMEM;
		goto error;
	}
	offset = 0;
	while (sb.st_size > 0) {
		nread = read(flash, buf, FLASH_BUF_SIZE);
		if (nread <= 0 || nread % 1024 != 0) {
			warnx("Bad read from flash file");
			mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0,
			    NULL, 0, NULL);
			error = ENXIO;
			goto error;
		}

		mbox_store_word(mbox, offset);
		mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_DOWNLOAD, buf, nread,
		    mbox, 4, &status);
		if (status != MFI_STAT_OK) {
			warnx("Flash download failed: %s", mfi_status(status));
			mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0,
			    NULL, 0, NULL);
			error = ENXIO;
			goto error;
		}
		sb.st_size -= nread;
		offset += nread;
	}

	/* Kick off the flash. */
	printf("WARNING: Firmware flash in progress, do not reboot machine... ");
	fflush(stdout);
	mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_FLASH, &dummy, sizeof(dummy),
	    NULL, 0, &status);
	if (status != MFI_STAT_OK) {
		printf("failed:\n\t%s\n", mfi_status(status));
		error = ENXIO;
		goto error;
	}
	printf("finished\n");
	error = display_pending_firmware(fd);

error:
	free(buf);
	if (fd >= 0)
		close(fd);
	close(flash);

	return (error);
}