flashrom.c
1 /* Copyright 2020 The ChromiumOS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 /* For strdup */ 7 #define _POSIX_C_SOURCE 200809L 8 #include <fcntl.h> 9 #include <limits.h> 10 #include <stdbool.h> 11 #include <stdint.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <sys/stat.h> 16 #include <sys/types.h> 17 #include <unistd.h> 18 19 #include "common.h" /* from cbfstool for buffer API. */ 20 #include "subprocess.h" /* from vboot_reference */ 21 #include "flashrom.h" 22 23 #define FLASHROM_EXEC_NAME "flashrom" 24 #define FLASHROM_PROGRAMMER_INTERNAL_AP "internal" 25 26 /** 27 * Helper to create a temporary file. 28 * 29 * @param path_out An output pointer for the filename. Caller should free. 30 * 31 * @return 0 on success, -1 for file open error, or -2 for write error. 32 */ 33 static int create_temp_file(char **path_out) 34 { 35 int fd; 36 int rv; 37 char *path; 38 mode_t umask_save; 39 40 #if defined(__FreeBSD__) 41 #define P_tmpdir "/tmp" 42 #endif 43 *path_out = NULL; 44 path = strdup(P_tmpdir "/flashrom.XXXXXX"); 45 /* Set the umask before mkstemp for security considerations. */ 46 umask_save = umask(077); 47 fd = mkstemp(path); 48 umask(umask_save); 49 if (fd < 0) { 50 rv = -1; 51 goto fail; 52 } 53 54 close(fd); 55 *path_out = path; 56 57 return 0; 58 fail: 59 free(path); 60 return rv; 61 } 62 63 static int run_flashrom(const char *const argv[]) 64 { 65 int status = subprocess_run(argv, &subprocess_null, &subprocess_null, 66 &subprocess_null); 67 if (status) { 68 fprintf(stderr, "Flashrom invocation failed (exit status %d):", 69 status); 70 for (const char *const *argp = argv; *argp; argp++) 71 fprintf(stderr, " %s", *argp); 72 fprintf(stderr, "\n"); 73 return -1; 74 } 75 76 return 0; 77 } 78 79 int flashrom_host_read(struct buffer *buffer, const char *region) 80 { 81 char *tmpfile; 82 char region_param[PATH_MAX]; 83 int rv; 84 85 if (create_temp_file(&tmpfile) != 0) 86 return -1; 87 if (region) 88 snprintf(region_param, sizeof(region_param), "%s:%s", region, 89 tmpfile); 90 const char *const argv[] = { 91 FLASHROM_EXEC_NAME, 92 "-p", 93 FLASHROM_PROGRAMMER_INTERNAL_AP, 94 "-r", 95 region ? "-i" : tmpfile, 96 region ? region_param : NULL, 97 NULL, 98 }; 99 rv = run_flashrom(argv); 100 if (!rv) 101 rv = buffer_from_file(buffer, tmpfile); 102 103 unlink(tmpfile); 104 free(tmpfile); 105 106 return rv; 107 } 108 109 int flashrom_host_write(struct buffer *buffer, const char *region) 110 { 111 char *tmpfile; 112 char region_param[PATH_MAX]; 113 int rv; 114 115 if (create_temp_file(&tmpfile) != 0) 116 return -1; 117 if (buffer_write_file(buffer, tmpfile) != 0) { 118 rv = -2; 119 goto fail; 120 } 121 122 if (region) 123 snprintf(region_param, sizeof(region_param), "%s:%s", region, 124 tmpfile); 125 const char *const argv[] = { 126 FLASHROM_EXEC_NAME, 127 "-p", 128 FLASHROM_PROGRAMMER_INTERNAL_AP, 129 "--noverify-all", 130 "-w", 131 region ? "-i" : tmpfile, 132 region ? region_param : NULL, 133 NULL, 134 }; 135 136 rv = run_flashrom(argv); 137 138 fail: 139 unlink(tmpfile); 140 free(tmpfile); 141 142 return rv; 143 }