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$ 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 45196200Sscottlint fw_name_width, fw_version_width, fw_date_width, fw_time_width; 46196200Sscottl 47196200Sscottlstatic void 48196200Sscottlscan_firmware(struct mfi_info_component *comp) 49196200Sscottl{ 50196200Sscottl int len; 51196200Sscottl 52196200Sscottl len = strlen(comp->name); 53196200Sscottl if (fw_name_width < len) 54196200Sscottl fw_name_width = len; 55196200Sscottl len = strlen(comp->version); 56196200Sscottl if (fw_version_width < len) 57196200Sscottl fw_version_width = len; 58196200Sscottl len = strlen(comp->build_date); 59196200Sscottl if (fw_date_width < len) 60196200Sscottl fw_date_width = len; 61196200Sscottl len = strlen(comp->build_time); 62196200Sscottl if (fw_time_width < len) 63196200Sscottl fw_time_width = len; 64196200Sscottl} 65196200Sscottl 66196200Sscottlstatic void 67196200Sscottldisplay_firmware(struct mfi_info_component *comp) 68196200Sscottl{ 69196200Sscottl 70196200Sscottl printf("%-*s %-*s %-*s %-*s\n", fw_name_width, comp->name, 71196200Sscottl fw_version_width, comp->version, fw_date_width, comp->build_date, 72196200Sscottl fw_time_width, comp->build_time); 73196200Sscottl} 74196200Sscottl 75214396Sjhbstatic int 76196200Sscottldisplay_pending_firmware(int fd) 77196200Sscottl{ 78196200Sscottl struct mfi_ctrl_info info; 79196200Sscottl struct mfi_info_component header; 80214396Sjhb int error; 81196200Sscottl u_int i; 82196200Sscottl 83196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 84214396Sjhb error = errno; 85196200Sscottl warn("Failed to get controller info"); 86214396Sjhb return (error); 87196200Sscottl } 88196200Sscottl 89196200Sscottl printf("mfi%d Pending Firmware Images:\n", mfi_unit); 90196200Sscottl strcpy(header.name, "Name"); 91196200Sscottl strcpy(header.version, "Version"); 92196200Sscottl strcpy(header.build_date, "Date"); 93196200Sscottl strcpy(header.build_time, "Time"); 94196200Sscottl scan_firmware(&header); 95196200Sscottl if (info.pending_image_component_count > 8) 96196200Sscottl info.pending_image_component_count = 8; 97196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 98196200Sscottl scan_firmware(&info.pending_image_component[i]); 99196200Sscottl display_firmware(&header); 100196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 101196200Sscottl display_firmware(&info.pending_image_component[i]); 102214396Sjhb 103214396Sjhb return (0); 104196200Sscottl} 105196200Sscottl 106196200Sscottlstatic void 107196200Sscottlmbox_store_word(uint8_t *mbox, uint32_t val) 108196200Sscottl{ 109196200Sscottl 110196200Sscottl mbox[0] = val & 0xff; 111196200Sscottl mbox[1] = val >> 8 & 0xff; 112196200Sscottl mbox[2] = val >> 16 & 0xff; 113196200Sscottl mbox[3] = val >> 24; 114196200Sscottl} 115196200Sscottl 116196200Sscottlstatic int 117196200Sscottlflash_adapter(int ac, char **av) 118196200Sscottl{ 119196200Sscottl struct mfi_progress dummy; 120196200Sscottl off_t offset; 121196200Sscottl size_t nread; 122196200Sscottl char *buf; 123196200Sscottl struct stat sb; 124214396Sjhb int error, fd, flash; 125196200Sscottl uint8_t mbox[4], status; 126196200Sscottl 127196200Sscottl if (ac != 2) { 128196200Sscottl warnx("flash: Firmware file required"); 129196200Sscottl return (EINVAL); 130196200Sscottl } 131196200Sscottl 132196200Sscottl flash = open(av[1], O_RDONLY); 133196200Sscottl if (flash < 0) { 134214396Sjhb error = errno; 135196200Sscottl warn("flash: Failed to open %s", av[1]); 136214396Sjhb return (error); 137196200Sscottl } 138196200Sscottl 139222899Sbz buf = NULL; 140222899Sbz fd = -1; 141222899Sbz 142196200Sscottl if (fstat(flash, &sb) < 0) { 143214396Sjhb error = errno; 144196200Sscottl warn("fstat(%s)", av[1]); 145222899Sbz goto error; 146196200Sscottl } 147196200Sscottl if (sb.st_size % 1024 != 0 || sb.st_size > 0x7fffffff) { 148196200Sscottl warnx("Invalid flash file size"); 149222899Sbz error = EINVAL; 150222899Sbz goto error; 151196200Sscottl } 152196200Sscottl 153237589Seadler fd = mfi_open(mfi_unit, O_RDWR); 154196200Sscottl if (fd < 0) { 155214396Sjhb error = errno; 156196200Sscottl warn("mfi_open"); 157222899Sbz goto error; 158196200Sscottl } 159196200Sscottl 160196200Sscottl /* First, ask the firmware to allocate space for the flash file. */ 161196200Sscottl mbox_store_word(mbox, sb.st_size); 162196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_OPEN, NULL, 0, mbox, 4, &status); 163196200Sscottl if (status != MFI_STAT_OK) { 164196200Sscottl warnx("Failed to alloc flash memory: %s", mfi_status(status)); 165222899Sbz error = EIO; 166222899Sbz goto error; 167196200Sscottl } 168196200Sscottl 169196200Sscottl /* Upload the file 64k at a time. */ 170196200Sscottl buf = malloc(FLASH_BUF_SIZE); 171215526Sjhb if (buf == NULL) { 172215526Sjhb warnx("malloc failed"); 173222899Sbz error = ENOMEM; 174222899Sbz goto error; 175215526Sjhb } 176196200Sscottl offset = 0; 177196200Sscottl while (sb.st_size > 0) { 178196200Sscottl nread = read(flash, buf, FLASH_BUF_SIZE); 179196200Sscottl if (nread <= 0 || nread % 1024 != 0) { 180196200Sscottl warnx("Bad read from flash file"); 181196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 182196200Sscottl NULL, 0, NULL); 183222899Sbz error = ENXIO; 184222899Sbz goto error; 185196200Sscottl } 186196200Sscottl 187196200Sscottl mbox_store_word(mbox, offset); 188196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_DOWNLOAD, buf, nread, 189196200Sscottl mbox, 4, &status); 190196200Sscottl if (status != MFI_STAT_OK) { 191196200Sscottl warnx("Flash download failed: %s", mfi_status(status)); 192196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 193196200Sscottl NULL, 0, NULL); 194222899Sbz error = ENXIO; 195222899Sbz goto error; 196196200Sscottl } 197196200Sscottl sb.st_size -= nread; 198196200Sscottl offset += nread; 199196200Sscottl } 200196200Sscottl 201196200Sscottl /* Kick off the flash. */ 202196200Sscottl printf("WARNING: Firmware flash in progress, do not reboot machine... "); 203196200Sscottl fflush(stdout); 204196200Sscottl mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_FLASH, &dummy, sizeof(dummy), 205196200Sscottl NULL, 0, &status); 206196200Sscottl if (status != MFI_STAT_OK) { 207196200Sscottl printf("failed:\n\t%s\n", mfi_status(status)); 208222899Sbz error = ENXIO; 209222899Sbz goto error; 210196200Sscottl } 211196200Sscottl printf("finished\n"); 212214396Sjhb error = display_pending_firmware(fd); 213196200Sscottl 214222899Sbzerror: 215222899Sbz free(buf); 216222899Sbz if (fd >= 0) 217222899Sbz close(fd); 218222899Sbz close(flash); 219196200Sscottl 220214396Sjhb return (error); 221196200Sscottl} 222196200SscottlMFI_COMMAND(top, flash, flash_adapter); 223