2 * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __RCSID("$FreeBSD: head/usr.sbin/mpsutil/mps_flash.c 298374 2016-04-20 21:11:49Z bapt $");
30 #include <sys/param.h>
44 MPS_TABLE(top
, flash
);
47 flash_save(int argc
, char **argv
)
49 const char *firmware_file
;
50 unsigned char *firmware_buffer
= NULL
;
53 ssize_t written
= 0, ret
= 0;
56 warnx("missing argument: expecting 'firmware' or bios'");
60 if (strcmp(argv
[1], "bios") == 0) {
62 } else if (strcmp(argv
[1], "firmware") != 0) {
63 warnx("Invalid argument '%s', expecting 'firmware' or 'bios'",
68 warnx("save %s: extra arguments", argv
[1]);
72 firmware_file
= argv
[1];
74 firmware_file
= argv
[2];
77 fd
= mps_open(mps_unit
);
84 if ((size
= mps_firmware_get(fd
, &firmware_buffer
, bios
)) < 0) {
85 warnx("Fail to save %s", argv
[1]);
92 fd
= open(firmware_file
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644);
96 free(firmware_buffer
);
99 while (written
!= size
) {
100 if ((ret
= write(fd
, firmware_buffer
+ written
, size
- written
)) <0) {
103 free(firmware_buffer
);
111 free(firmware_buffer
);
112 printf("%s successfully saved as %s\n", argv
[1], firmware_file
);
116 MPS_COMMAND(flash
, save
, flash_save
, "[firmware|bios] [file]",
117 "Save firmware/bios into a file");
120 flash_update(int argc
, char **argv
)
123 unsigned char *mem
= NULL
;
126 MPI2_FW_IMAGE_HEADER
*fwheader
;
127 MPI2_IOC_FACTS_REPLY
*facts
;
130 warnx("missing argument: expecting 'firmware' or bios'");
134 if (strcmp(argv
[1], "bios") == 0) {
136 } else if (strcmp(argv
[1], "firmware") != 0) {
137 warnx("Invalid argument '%s', expecting 'firmware' or 'bios'",
142 warnx("update firmware: extra arguments");
147 warnx("no firmware specified");
151 if (stat(argv
[2], &st
) == -1) {
157 fd
= open(argv
[2], O_RDONLY
);
164 mem
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
165 if (mem
== MAP_FAILED
) {
173 fd
= mps_open(mps_unit
);
177 munmap(mem
, st
.st_size
);
181 if ((facts
= mps_get_iocfacts(fd
)) == NULL
) {
182 warnx("could not get controller IOCFacts\n");
183 munmap(mem
, st
.st_size
);
189 /* Check boot record magic number */
190 if (((mem
[0x01]<<8) + mem
[0x00]) != 0xaa55) {
191 warnx("Invalid bios: no boot record magic number");
192 munmap(mem
, st
.st_size
);
197 if ((st
.st_size
% 512) != 0) {
198 warnx("Invalid bios: size not a multiple of 512");
199 munmap(mem
, st
.st_size
);
205 fwheader
= (MPI2_FW_IMAGE_HEADER
*)mem
;
206 if (fwheader
->VendorID
!= MPI2_MFGPAGE_VENDORID_LSI
) {
207 warnx("Invalid firmware:");
208 warnx(" Expected Vendor ID: %04x",
209 MPI2_MFGPAGE_VENDORID_LSI
);
210 warnx(" Image Vendor ID: %04x", fwheader
->VendorID
);
211 munmap(mem
, st
.st_size
);
217 if (fwheader
->ProductID
!= facts
->ProductID
) {
218 warnx("Invalid image:");
219 warnx(" Expected Product ID: %04x", facts
->ProductID
);
220 warnx(" Image Product ID: %04x", fwheader
->ProductID
);
221 munmap(mem
, st
.st_size
);
228 printf("Updating %s...\n", argv
[1]);
229 if (mps_firmware_send(fd
, mem
, st
.st_size
, bios
) < 0) {
230 warnx("Fail to update %s", argv
[1]);
231 munmap(mem
, st
.st_size
);
237 munmap(mem
, st
.st_size
);
240 printf("%s successfully updated\n", argv
[1]);
244 MPS_COMMAND(flash
, update
, flash_update
, "[firmware|bios] file",
245 "Update firmware/bios");