1196200Sscottl/*- 2196200Sscottl * Copyright (c) 2008, 2009 Yahoo!, Inc. 3196200Sscottl * All rights reserved. 4196200Sscottl * 5196200Sscottl * Redistribution and use in source and binary forms, with or without 6196200Sscottl * modification, are permitted provided that the following conditions 7196200Sscottl * are met: 8196200Sscottl * 1. Redistributions of source code must retain the above copyright 9196200Sscottl * notice, this list of conditions and the following disclaimer. 10196200Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11196200Sscottl * notice, this list of conditions and the following disclaimer in the 12196200Sscottl * documentation and/or other materials provided with the distribution. 13196200Sscottl * 3. The names of the authors may not be used to endorse or promote 14196200Sscottl * products derived from this software without specific prior written 15196200Sscottl * permission. 16196200Sscottl * 17196200Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18196200Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19196200Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20196200Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21196200Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22196200Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23196200Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24196200Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25196200Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26196200Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27196200Sscottl * SUCH DAMAGE. 28196200Sscottl * 29196200Sscottl * $FreeBSD: releng/11.0/usr.sbin/mfiutil/mfi_flash.c 241776 2012-10-20 10:20:06Z ed $ 30196200Sscottl */ 31196200Sscottl 32196200Sscottl#include <sys/param.h> 33196200Sscottl#include <sys/errno.h> 34196200Sscottl#include <sys/stat.h> 35196200Sscottl#include <err.h> 36196200Sscottl#include <fcntl.h> 37196200Sscottl#include <stdio.h> 38196200Sscottl#include <stdlib.h> 39196200Sscottl#include <string.h> 40196200Sscottl#include <unistd.h> 41196200Sscottl#include "mfiutil.h" 42196200Sscottl 43196200Sscottl#define FLASH_BUF_SIZE (64 * 1024) 44196200Sscottl 45214396Sjhbstatic int 46196200Sscottldisplay_pending_firmware(int fd) 47196200Sscottl{ 48196200Sscottl struct mfi_ctrl_info info; 49196200Sscottl struct mfi_info_component header; 50214396Sjhb int error; 51196200Sscottl u_int i; 52196200Sscottl 53196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 54214396Sjhb error = errno; 55196200Sscottl warn("Failed to get controller info"); 56214396Sjhb return (error); 57196200Sscottl } 58196200Sscottl 59196200Sscottl printf("mfi%d Pending Firmware Images:\n", mfi_unit); 60196200Sscottl strcpy(header.name, "Name"); 61196200Sscottl strcpy(header.version, "Version"); 62196200Sscottl strcpy(header.build_date, "Date"); 63196200Sscottl strcpy(header.build_time, "Time"); 64196200Sscottl scan_firmware(&header); 65196200Sscottl if (info.pending_image_component_count > 8) 66196200Sscottl info.pending_image_component_count = 8; 67196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 68196200Sscottl scan_firmware(&info.pending_image_component[i]); 69241776Sed display_firmware(&header, ""); 70196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 71241776Sed display_firmware(&info.pending_image_component[i], ""); 72214396Sjhb 73214396Sjhb return (0); 74196200Sscottl} 75196200Sscottl 76196200Sscottlstatic void 77196200Sscottlmbox_store_word(uint8_t *mbox, uint32_t val) 78196200Sscottl{ 79196200Sscottl 80196200Sscottl mbox[0] = val & 0xff; 81196200Sscottl mbox[1] = val >> 8 & 0xff; 82196200Sscottl mbox[2] = val >> 16 & 0xff; 83196200Sscottl mbox[3] = val >> 24; 84196200Sscottl} 85196200Sscottl 86196200Sscottlstatic int 87196200Sscottlflash_adapter(int ac, char **av) 88196200Sscottl{ 89196200Sscottl struct mfi_progress dummy; 90196200Sscottl off_t offset; 91196200Sscottl size_t nread; 92196200Sscottl char *buf; 93196200Sscottl struct stat sb; 94214396Sjhb int error, fd, flash; 95196200Sscottl uint8_t mbox[4], status; 96196200Sscottl 97196200Sscottl if (ac != 2) { 98196200Sscottl warnx("flash: Firmware file required"); 99196200Sscottl return (EINVAL); 100196200Sscottl } 101196200Sscottl 102196200Sscottl flash = open(av[1], O_RDONLY); 103196200Sscottl if (flash < 0) { 104214396Sjhb error = errno; 105196200Sscottl warn("flash: Failed to open %s", av[1]); 106214396Sjhb return (error); 107196200Sscottl } 108196200Sscottl 109222899Sbz buf = NULL; 110222899Sbz fd = -1; 111222899Sbz 112196200Sscottl if (fstat(flash, &sb) < 0) { 113214396Sjhb error = errno; 114196200Sscottl warn("fstat(%s)", av[1]); 115222899Sbz goto error; 116196200Sscottl } 117196200Sscottl if (sb.st_size % 1024 != 0 || sb.st_size > 0x7fffffff) { 118196200Sscottl warnx("Invalid flash file size"); 119222899Sbz error = EINVAL; 120222899Sbz goto error; 121196200Sscottl } 122196200Sscottl 123237259Seadler fd = mfi_open(mfi_unit, O_RDWR); 124196200Sscottl if (fd < 0) { 125214396Sjhb error = errno; 126196200Sscottl warn("mfi_open"); 127222899Sbz goto error; 128196200Sscottl } 129196200Sscottl 130196200Sscottl /* First, ask the firmware to allocate space for the flash file. */ 131196200Sscottl mbox_store_word(mbox, sb.st_size); 132196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_OPEN, NULL, 0, mbox, 4, &status); 133196200Sscottl if (status != MFI_STAT_OK) { 134196200Sscottl warnx("Failed to alloc flash memory: %s", mfi_status(status)); 135222899Sbz error = EIO; 136222899Sbz goto error; 137196200Sscottl } 138196200Sscottl 139196200Sscottl /* Upload the file 64k at a time. */ 140196200Sscottl buf = malloc(FLASH_BUF_SIZE); 141215526Sjhb if (buf == NULL) { 142215526Sjhb warnx("malloc failed"); 143222899Sbz error = ENOMEM; 144222899Sbz goto error; 145215526Sjhb } 146196200Sscottl offset = 0; 147196200Sscottl while (sb.st_size > 0) { 148196200Sscottl nread = read(flash, buf, FLASH_BUF_SIZE); 149196200Sscottl if (nread <= 0 || nread % 1024 != 0) { 150196200Sscottl warnx("Bad read from flash file"); 151196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 152196200Sscottl NULL, 0, NULL); 153222899Sbz error = ENXIO; 154222899Sbz goto error; 155196200Sscottl } 156196200Sscottl 157196200Sscottl mbox_store_word(mbox, offset); 158196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_DOWNLOAD, buf, nread, 159196200Sscottl mbox, 4, &status); 160196200Sscottl if (status != MFI_STAT_OK) { 161196200Sscottl warnx("Flash download failed: %s", mfi_status(status)); 162196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 163196200Sscottl NULL, 0, NULL); 164222899Sbz error = ENXIO; 165222899Sbz goto error; 166196200Sscottl } 167196200Sscottl sb.st_size -= nread; 168196200Sscottl offset += nread; 169196200Sscottl } 170196200Sscottl 171196200Sscottl /* Kick off the flash. */ 172196200Sscottl printf("WARNING: Firmware flash in progress, do not reboot machine... "); 173196200Sscottl fflush(stdout); 174196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_FLASH, &dummy, sizeof(dummy), 175196200Sscottl NULL, 0, &status); 176196200Sscottl if (status != MFI_STAT_OK) { 177196200Sscottl printf("failed:\n\t%s\n", mfi_status(status)); 178222899Sbz error = ENXIO; 179222899Sbz goto error; 180196200Sscottl } 181196200Sscottl printf("finished\n"); 182214396Sjhb error = display_pending_firmware(fd); 183196200Sscottl 184222899Sbzerror: 185222899Sbz free(buf); 186222899Sbz if (fd >= 0) 187222899Sbz close(fd); 188222899Sbz close(flash); 189196200Sscottl 190214396Sjhb return (error); 191196200Sscottl} 192196200SscottlMFI_COMMAND(top, flash, flash_adapter); 193