xref: /aosp_15_r20/external/coreboot/util/cbfstool/flashrom.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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  */
create_temp_file(char ** path_out)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 
run_flashrom(const char * const argv[])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 
flashrom_host_read(struct buffer * buffer,const char * region)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 
flashrom_host_write(struct buffer * buffer,const char * region)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 }
144