1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2008, 2009 Yahoo!, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The names of the authors may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/errno.h> 36 #include <sys/stat.h> 37 #include <err.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include "mfiutil.h" 44 45 #define FLASH_BUF_SIZE (64 * 1024) 46 47 static int 48 display_pending_firmware(int fd) 49 { 50 struct mfi_ctrl_info info; 51 struct mfi_info_component header; 52 int error; 53 u_int i; 54 55 if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 56 error = errno; 57 warn("Failed to get controller info"); 58 return (error); 59 } 60 61 printf("mfi%d Pending Firmware Images:\n", mfi_unit); 62 strcpy(header.name, "Name"); 63 strcpy(header.version, "Version"); 64 strcpy(header.build_date, "Date"); 65 strcpy(header.build_time, "Time"); 66 scan_firmware(&header); 67 if (info.pending_image_component_count > 8) 68 info.pending_image_component_count = 8; 69 for (i = 0; i < info.pending_image_component_count; i++) 70 scan_firmware(&info.pending_image_component[i]); 71 display_firmware(&header, ""); 72 for (i = 0; i < info.pending_image_component_count; i++) 73 display_firmware(&info.pending_image_component[i], ""); 74 75 return (0); 76 } 77 78 static void 79 mbox_store_word(uint8_t *mbox, uint32_t val) 80 { 81 82 mbox[0] = val & 0xff; 83 mbox[1] = val >> 8 & 0xff; 84 mbox[2] = val >> 16 & 0xff; 85 mbox[3] = val >> 24; 86 } 87 88 static int 89 flash_adapter(int ac, char **av) 90 { 91 struct mfi_progress dummy; 92 off_t offset; 93 size_t nread; 94 char *buf; 95 struct stat sb; 96 int error, fd, flash; 97 uint8_t mbox[4], status; 98 99 if (ac != 2) { 100 warnx("flash: Firmware file required"); 101 return (EINVAL); 102 } 103 104 flash = open(av[1], O_RDONLY); 105 if (flash < 0) { 106 error = errno; 107 warn("flash: Failed to open %s", av[1]); 108 return (error); 109 } 110 111 buf = NULL; 112 fd = -1; 113 114 if (fstat(flash, &sb) < 0) { 115 error = errno; 116 warn("fstat(%s)", av[1]); 117 goto error; 118 } 119 if (sb.st_size % 1024 != 0 || sb.st_size > 0x7fffffff) { 120 warnx("Invalid flash file size"); 121 error = EINVAL; 122 goto error; 123 } 124 125 fd = mfi_open(mfi_unit, O_RDWR); 126 if (fd < 0) { 127 error = errno; 128 warn("mfi_open"); 129 goto error; 130 } 131 132 /* First, ask the firmware to allocate space for the flash file. */ 133 mbox_store_word(mbox, sb.st_size); 134 mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_OPEN, NULL, 0, mbox, 4, &status); 135 if (status != MFI_STAT_OK) { 136 warnx("Failed to alloc flash memory: %s", mfi_status(status)); 137 error = EIO; 138 goto error; 139 } 140 141 /* Upload the file 64k at a time. */ 142 buf = malloc(FLASH_BUF_SIZE); 143 if (buf == NULL) { 144 warnx("malloc failed"); 145 error = ENOMEM; 146 goto error; 147 } 148 offset = 0; 149 while (sb.st_size > 0) { 150 nread = read(flash, buf, FLASH_BUF_SIZE); 151 if (nread <= 0 || nread % 1024 != 0) { 152 warnx("Bad read from flash file"); 153 mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 154 NULL, 0, NULL); 155 error = ENXIO; 156 goto error; 157 } 158 159 mbox_store_word(mbox, offset); 160 mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_DOWNLOAD, buf, nread, 161 mbox, 4, &status); 162 if (status != MFI_STAT_OK) { 163 warnx("Flash download failed: %s", mfi_status(status)); 164 mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0, 165 NULL, 0, NULL); 166 error = ENXIO; 167 goto error; 168 } 169 sb.st_size -= nread; 170 offset += nread; 171 } 172 173 /* Kick off the flash. */ 174 printf("WARNING: Firmware flash in progress, do not reboot machine... "); 175 fflush(stdout); 176 mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_FLASH, &dummy, sizeof(dummy), 177 NULL, 0, &status); 178 if (status != MFI_STAT_OK) { 179 printf("failed:\n\t%s\n", mfi_status(status)); 180 error = ENXIO; 181 goto error; 182 } 183 printf("finished\n"); 184 error = display_pending_firmware(fd); 185 186 error: 187 free(buf); 188 if (fd >= 0) 189 close(fd); 190 close(flash); 191 192 return (error); 193 } 194 MFI_COMMAND(top, flash, flash_adapter); 195