xref: /aosp_15_r20/external/coreboot/util/amdfwtool/handle_file.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <fcntl.h>
4 #include <errno.h>
5 #include <limits.h>
6 #include <stdio.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <stdlib.h>
11 
12 #include "amdfwtool.h"
13 
write_or_fail(int fd,void * ptr,size_t size)14 void write_or_fail(int fd, void *ptr, size_t size)
15 {
16 	ssize_t written;
17 
18 	written = write_from_buf_to_file(fd, ptr, size);
19 	if (written < 0 || (size_t)written != size) {
20 		fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
21 								__func__, size, written);
22 		exit(-1);
23 	}
24 }
25 
read_from_file_to_buf(int fd,void * buf,size_t buf_size)26 ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
27 {
28 	ssize_t bytes;
29 	size_t total_bytes = 0;
30 
31 	do {
32 		bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
33 		if (bytes == 0) {
34 			fprintf(stderr, "Reached EOF probably\n");
35 			break;
36 		}
37 
38 		if (bytes < 0 && errno == EAGAIN)
39 			bytes = 0;
40 
41 		if (bytes < 0) {
42 			fprintf(stderr, "Read failure %s\n", strerror(errno));
43 			return bytes;
44 		}
45 
46 		total_bytes += bytes;
47 	} while (total_bytes < buf_size);
48 
49 	if (total_bytes != buf_size) {
50 		fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
51 								total_bytes, buf_size);
52 		return -1;
53 	}
54 	return buf_size;
55 }
56 
write_from_buf_to_file(int fd,const void * buf,size_t buf_size)57 ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
58 {
59 	ssize_t bytes;
60 	size_t total_bytes = 0;
61 
62 	do {
63 		bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
64 		if (bytes < 0 && errno == EAGAIN)
65 			bytes = 0;
66 
67 		if (bytes < 0) {
68 			fprintf(stderr, "Write failure %s\n", strerror(errno));
69 			lseek(fd, SEEK_CUR, -total_bytes);
70 			return bytes;
71 		}
72 
73 		total_bytes += bytes;
74 	} while (total_bytes < buf_size);
75 
76 	if (total_bytes != buf_size) {
77 		fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
78 								total_bytes, buf_size);
79 		lseek(fd, SEEK_CUR, -total_bytes);
80 		return -1;
81 	}
82 
83 	return buf_size;
84 }
85 
write_body(char * output,void * body_offset,ssize_t body_size)86 ssize_t write_body(char *output, void *body_offset, ssize_t body_size)
87 {
88 	char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
89 	int ret;
90 	int fd;
91 	ssize_t bytes = -1;
92 
93 	/* Create a tmp file and rename it at the end so that make does not get confused
94 	   if amdfwtool is killed for some unexpected reasons. */
95 	ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
96 			output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
97 	if (ret < 0) {
98 		fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
99 							strerror(errno), ret);
100 		return -1;
101 	} else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
102 		fprintf(stderr, "BODY File name %d  > %zu\n", ret, sizeof(body_tmp_name));
103 		return -1;
104 	}
105 
106 	fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
107 	if (fd < 0) {
108 		fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
109 		return -1;
110 	}
111 
112 	bytes = write_from_buf_to_file(fd, body_offset, body_size);
113 	if (bytes != body_size) {
114 		fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
115 		return -1;
116 	}
117 	close(fd);
118 
119 	/* Rename the tmp file */
120 	ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
121 	if (ret < 0) {
122 		fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
123 		return -1;
124 	}
125 
126 	if (rename(body_tmp_name, body_name)) {
127 		fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
128 		return -1;
129 	}
130 
131 	return bytes;
132 }
133 
copy_blob(void * dest,const char * src_file,size_t room)134 ssize_t copy_blob(void *dest, const char *src_file, size_t room)
135 {
136 	int fd;
137 	struct stat fd_stat;
138 	ssize_t bytes;
139 
140 	fd = open(src_file, O_RDONLY);
141 	if (fd < 0) {
142 		fprintf(stderr, "Error opening file: %s: %s\n",
143 		       src_file, strerror(errno));
144 		return -1;
145 	}
146 
147 	if (fstat(fd, &fd_stat)) {
148 		fprintf(stderr, "fstat error: %s\n", strerror(errno));
149 		close(fd);
150 		return -2;
151 	}
152 
153 	if ((size_t)fd_stat.st_size > room) {
154 		fprintf(stderr, "Error: %s will not fit.  Exiting.\n", src_file);
155 		close(fd);
156 		return -3;
157 	}
158 
159 	bytes = read(fd, dest, (size_t)fd_stat.st_size);
160 	close(fd);
161 	if (bytes != (ssize_t)fd_stat.st_size) {
162 		fprintf(stderr, "Error while reading %s\n", src_file);
163 		return -4;
164 	}
165 
166 	return bytes;
167 }
168