/ util / cbfstool / flashrom.c
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  }