blob: fe3fb7b3d881293975ff16839fb209a56fd3fa47 [file] [log] [blame]
Jon Murphyc4e90452022-06-28 10:36:23 -06001/* Copyright 2020 The ChromiumOS Authors. All rights reserved.
Edward O'Callaghan774dcff2022-06-06 20:01:04 +10002 * 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"
Hsuan Ting Chena6d68182023-09-14 11:46:20 +080024#define FLASHROM_PROGRAMMER_INTERNAL_AP "internal"
Edward O'Callaghan774dcff2022-06-06 20:01:04 +100025
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 */
33static 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;
58fail:
59 free(path);
60 return rv;
61}
62
63static 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
79int 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
109int 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
138fail:
139 unlink(tmpfile);
140 free(tmpfile);
141
142 return rv;
143}