Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: make_prom.c | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /* | |
24 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
25 | * Use is subject to license terms. | |
26 | */ | |
27 | ||
28 | #include <sys/types.h> | |
29 | #include <stdio.h> | |
30 | #include <stdlib.h> | |
31 | #include <strings.h> | |
32 | #include <errno.h> | |
33 | #include <inttypes.h> | |
34 | ||
35 | #include <unistd.h> | |
36 | #include <fcntl.h> | |
37 | #include <sys/stat.h> | |
38 | #include <sys/mman.h> | |
39 | ||
40 | ||
41 | #include "xilinx_t1_system_config.h" | |
42 | ||
43 | ||
44 | /* | |
45 | * This program is used to create prom.bin from the components. | |
46 | */ | |
47 | ||
48 | ||
49 | static char *prom_filename = ""; | |
50 | ||
51 | ||
52 | struct file_info { | |
53 | char *name; | |
54 | size_t prom_file_offset; | |
55 | size_t max_file_size; | |
56 | }; | |
57 | ||
58 | ||
59 | #define F_RESET 0 | |
60 | #define F_Q 1 | |
61 | #define F_OPENBOOT 2 | |
62 | #define F_GUEST_MD 3 | |
63 | #define F_HV_MD 4 | |
64 | #define F_NVRAM 5 | |
65 | #define F_MAX 6 | |
66 | ||
67 | ||
68 | ||
69 | struct file_info files[F_MAX] = { | |
70 | { "reset.bin", T1_FPGA_PROM_RESET_OFFSET, T1_FPGA_PROM_MAX_RESET_SIZE }, | |
71 | { "q.bin", T1_FPGA_PROM_HV_OFFSET, T1_FPGA_PROM_MAX_HV_SIZE }, | |
72 | { "openboot.bin", T1_FPGA_PROM_OPENBOOT_OFFSET, T1_FPGA_PROM_MAX_OPENBOOT_SIZE }, | |
73 | { "guest.md", T1_FPGA_PROM_GUEST_MD_OFFSET, T1_FPGA_PROM_MAX_GUEST_MD_SIZE }, | |
74 | { "hv.md", T1_FPGA_PROM_HV_MD_OFFSET, T1_FPGA_PROM_MAX_HV_MD_SIZE }, | |
75 | { "nvram.bin", T1_FPGA_PROM_NVRAM_OFFSET, T1_FPGA_PROM_MAX_NVRAM_SIZE } | |
76 | }; | |
77 | ||
78 | ||
79 | static void | |
80 | cleanup_and_exit(int status) | |
81 | { | |
82 | unlink(prom_filename); | |
83 | exit(status); | |
84 | } | |
85 | ||
86 | ||
87 | /* | |
88 | * Always reads "nbyte" bytes unless end of file encountered. | |
89 | */ | |
90 | ||
91 | static ssize_t | |
92 | read_all(int ifd, char *buf, size_t nbyte, const char *filename) | |
93 | { | |
94 | size_t rem_bytes, bytes_read; | |
95 | ssize_t read_result; | |
96 | ||
97 | bytes_read = 0; | |
98 | rem_bytes = nbyte; | |
99 | ||
100 | while (rem_bytes) { | |
101 | read_result = read(ifd, &buf[bytes_read], rem_bytes); | |
102 | if (read_result < 0) { | |
103 | perror("ERROR: read "); | |
104 | fprintf(stderr, "ERROR: Couldn't read file \"%s\" \n", filename); | |
105 | cleanup_and_exit(EXIT_FAILURE); | |
106 | } | |
107 | if (read_result == 0) { | |
108 | return bytes_read; | |
109 | } | |
110 | ||
111 | rem_bytes -= read_result; | |
112 | bytes_read += read_result; | |
113 | } | |
114 | ||
115 | return bytes_read; | |
116 | } | |
117 | ||
118 | static size_t | |
119 | get_file_size(const char *filename) | |
120 | { | |
121 | struct stat stat_buf; | |
122 | ||
123 | if (stat(filename, &stat_buf) < 0) { | |
124 | perror("ERROR: stat"); | |
125 | fprintf(stderr, "ERROR: Couldn't stat file \"%s\" \n", filename); | |
126 | cleanup_and_exit(EXIT_FAILURE); | |
127 | } | |
128 | ||
129 | return stat_buf.st_size; | |
130 | } | |
131 | ||
132 | static void | |
133 | read_file(char *filename, char *buf, size_t buf_size) | |
134 | { | |
135 | int fd; | |
136 | size_t file_size; | |
137 | ||
138 | struct stat stat_buf; | |
139 | ||
140 | fd = open(filename, O_RDONLY); | |
141 | if (fd < 0) { | |
142 | perror("ERROR: open"); | |
143 | printf("ERROR: error opening file \"%s\" for reading. \n", filename); | |
144 | cleanup_and_exit(EXIT_FAILURE); | |
145 | } | |
146 | ||
147 | file_size = get_file_size(filename); | |
148 | ||
149 | if (file_size > buf_size) { | |
150 | fprintf(stderr, "ERROR: filename %s: file_size 0x%" PRIx64 " is larger than allocated space 0x%" PRIx64 " \n", | |
151 | filename, (uint64_t) file_size, (uint64_t) buf_size); | |
152 | cleanup_and_exit(EXIT_FAILURE); | |
153 | } | |
154 | ||
155 | read_all(fd, buf, file_size, filename); | |
156 | close(fd); | |
157 | ||
158 | return; | |
159 | } | |
160 | ||
161 | void | |
162 | print_help_and_exit(const char *progname) | |
163 | { | |
164 | printf("%s \n", progname); | |
165 | printf(" -g <filename> # guest machine description file \n"); | |
166 | printf(" -h # print this help \n"); | |
167 | printf(" -H <filename> # hypervisor machine description file \n"); | |
168 | printf(" -n <filename> # nvram file \n"); | |
169 | printf(" -o <filename> # openboot file \n"); | |
170 | printf(" -p <filename> # prom file \n"); | |
171 | printf(" -r <filename> # reset file \n"); | |
172 | exit(1); | |
173 | } | |
174 | ||
175 | int | |
176 | process_options(int argc, char *argv[]) | |
177 | { | |
178 | int lib_result; | |
179 | ||
180 | while ((lib_result = getopt(argc, argv, "g:H:o:p:r:h")) != -1) { | |
181 | switch (lib_result) { | |
182 | case 'g': | |
183 | files[F_GUEST_MD].name = strdup(optarg); | |
184 | break; | |
185 | case 'H': | |
186 | files[F_HV_MD].name = strdup(optarg); | |
187 | break; | |
188 | case 'o': | |
189 | files[F_OPENBOOT].name = strdup(optarg); | |
190 | break; | |
191 | case 'p': | |
192 | prom_filename = strdup(optarg); | |
193 | break; | |
194 | case 'n': | |
195 | files[F_NVRAM].name = strdup(optarg); | |
196 | break; | |
197 | case 'r': | |
198 | files[F_RESET].name = strdup(optarg); | |
199 | break; | |
200 | case 'h': | |
201 | print_help_and_exit(argv[0]); | |
202 | /* NOT REACHED */ | |
203 | break; | |
204 | default: | |
205 | print_help_and_exit(argv[0]); | |
206 | /* NOT REACHED */ | |
207 | break; | |
208 | } | |
209 | } | |
210 | ||
211 | return 0; | |
212 | } | |
213 | ||
214 | int | |
215 | main(int argc, char *argv[]) | |
216 | { | |
217 | int fd; | |
218 | off_t prom_file_offset; | |
219 | ||
220 | size_t bytes_written; | |
221 | off_t lseek_result; | |
222 | ||
223 | char buf[1]; | |
224 | ||
225 | ||
226 | process_options(argc, argv); | |
227 | ||
228 | if (prom_filename[0] == 0) { | |
229 | fprintf(stderr, "ERROR: prom filename not specified \n"); | |
230 | cleanup_and_exit(EXIT_FAILURE); | |
231 | } | |
232 | ||
233 | fd = open(prom_filename, O_RDWR|O_CREAT|O_TRUNC, 0666); | |
234 | if (fd < 0) { | |
235 | perror("ERROR: open"); | |
236 | fprintf(stderr, "ERROR: Couldn't open/creat prom file \"%s\" for reading/writing \n", prom_filename); | |
237 | cleanup_and_exit(EXIT_FAILURE); | |
238 | } | |
239 | ||
240 | prom_file_offset = T1_FPGA_PROM_BIN_FILE_SIZE - 1; | |
241 | lseek_result = lseek(fd, prom_file_offset, SEEK_SET); | |
242 | if (lseek_result == (off_t) -1) { | |
243 | perror("ERROR: lseek"); | |
244 | fprintf(stderr, "ERROR: lseek failed trying to set file pointer to 0x%" PRIx64 " \n", (uint64_t)prom_file_offset); | |
245 | cleanup_and_exit(EXIT_FAILURE); | |
246 | } | |
247 | ||
248 | buf[0] = 0; | |
249 | bytes_written = write(fd, buf, 1); | |
250 | if (bytes_written < 0) { | |
251 | perror("ERROR: write "); | |
252 | fprintf(stderr, "ERROR: Couldn't write to prom file \"%s\" \n", prom_filename); | |
253 | cleanup_and_exit(EXIT_FAILURE); | |
254 | } | |
255 | ||
256 | caddr_t addr = mmap(0, T1_FPGA_PROM_BIN_FILE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | |
257 | if (addr == MAP_FAILED) { | |
258 | perror("ERROR: mmap"); | |
259 | cleanup_and_exit(EXIT_FAILURE); | |
260 | } | |
261 | memset(addr, 0, T1_FPGA_PROM_BIN_FILE_SIZE); | |
262 | ||
263 | for (int i=0; i<F_MAX; i++) { | |
264 | read_file(files[i].name, (addr + files[i].prom_file_offset), files[i].max_file_size); | |
265 | } | |
266 | ||
267 | munmap(addr, T1_FPGA_PROM_BIN_FILE_SIZE); | |
268 | ||
269 | close(fd); | |
270 | ||
271 | return 0; | |
272 | } | |
273 | ||
274 |