kvm: qemu: reindent ia64 code to match qemu code style
[kvm-userspace.git] / qemu / target-ia64 / firmware.c
blobc5e4fa9c562ee1815539f29850a5cf2028f1b82e
1 /*
2 * firmware.c : Firmware build logic for ia64 platform.
4 * Ported from Xen 3.0 Source.
5 * Copyright (c) 2007, Intel Corporation.
6 * Zhang Xiantao <xiantao.zhang@intel.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place - Suite 330, Boston, MA 02111-1307 USA.
22 #include <string.h>
23 #include <stdlib.h>
24 #include <zlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
29 #include "cpu.h"
31 #include "firmware.h"
33 typedef struct {
34 unsigned long signature;
35 unsigned int type;
36 unsigned int length;
37 } HOB_GENERIC_HEADER;
40 * INFO HOB is the first data data in one HOB list
41 * it contains the control information of the HOB list
43 typedef struct {
44 HOB_GENERIC_HEADER header;
45 unsigned long length; // current length of hob
46 unsigned long cur_pos; // current poisiton of hob
47 unsigned long buf_size; // size of hob buffer
48 } HOB_INFO;
50 typedef struct{
51 unsigned long start;
52 unsigned long size;
53 } hob_mem_t;
55 typedef enum {
56 HOB_TYPE_INFO=0,
57 HOB_TYPE_TERMINAL,
58 HOB_TYPE_MEM,
59 HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
60 HOB_TYPE_PAL_CACHE_SUMMARY,
61 HOB_TYPE_PAL_MEM_ATTRIB,
62 HOB_TYPE_PAL_CACHE_INFO,
63 HOB_TYPE_PAL_CACHE_PROT_INFO,
64 HOB_TYPE_PAL_DEBUG_INFO,
65 HOB_TYPE_PAL_FIXED_ADDR,
66 HOB_TYPE_PAL_FREQ_BASE,
67 HOB_TYPE_PAL_FREQ_RATIOS,
68 HOB_TYPE_PAL_HALT_INFO,
69 HOB_TYPE_PAL_PERF_MON_INFO,
70 HOB_TYPE_PAL_PROC_GET_FEATURES,
71 HOB_TYPE_PAL_PTCE_INFO,
72 HOB_TYPE_PAL_REGISTER_INFO,
73 HOB_TYPE_PAL_RSE_INFO,
74 HOB_TYPE_PAL_TEST_INFO,
75 HOB_TYPE_PAL_VM_SUMMARY,
76 HOB_TYPE_PAL_VM_INFO,
77 HOB_TYPE_PAL_VM_PAGE_SIZE,
78 HOB_TYPE_NR_VCPU,
79 HOB_TYPE_NR_NVRAM,
80 HOB_TYPE_MAX
81 } hob_type_t;
83 static int hob_init(void *buffer ,unsigned long buf_size);
84 static int add_pal_hob(void* hob_buf);
85 static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
86 static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
87 static int build_hob(void* hob_buf, unsigned long hob_buf_size,
88 unsigned long dom_mem_size, unsigned long vcpus);
89 static int load_hob(void *hob_buf,
90 unsigned long dom_mem_size, void* hob_start);
92 int
93 kvm_ia64_build_hob(unsigned long memsize,
94 unsigned long vcpus, uint8_t* fw_start)
96 char *hob_buf;
98 hob_buf = malloc(GFW_HOB_SIZE);
99 if (hob_buf == NULL) {
100 Hob_Output("Hob: Could not allocate hob");
101 return -1;
104 if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) < 0) {
105 free(hob_buf);
106 Hob_Output("Could not build hob");
107 return -1;
109 if (load_hob(hob_buf, memsize, fw_start + HOB_OFFSET) < 0) {
110 free(hob_buf);
111 Hob_Output("Could not load hob");
112 return -1;
114 free(hob_buf);
116 return 0;
119 static int
120 hob_init(void *buffer, unsigned long buf_size)
122 HOB_INFO *phit;
123 HOB_GENERIC_HEADER *terminal;
125 if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
126 // buffer too small
127 return -1;
130 phit = (HOB_INFO*)buffer;
131 phit->header.signature = HOB_SIGNATURE;
132 phit->header.type = HOB_TYPE_INFO;
133 phit->header.length = sizeof(HOB_INFO);
134 phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
135 phit->cur_pos = 0;
136 phit->buf_size = buf_size;
138 terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO));
139 terminal->signature = HOB_SIGNATURE;
140 terminal->type = HOB_TYPE_TERMINAL;
141 terminal->length = sizeof(HOB_GENERIC_HEADER);
143 return 0;
147 * Add a new HOB to the HOB List.
149 * hob_start - start address of hob buffer
150 * type - type of the hob to be added
151 * data - data of the hob to be added
152 * data_size - size of the data
154 static int
155 hob_add(void* hob_start, int type, void* data, int data_size)
157 HOB_INFO *phit;
158 HOB_GENERIC_HEADER *newhob, *tail;
160 phit = (HOB_INFO*)hob_start;
162 if (phit->length + data_size > phit->buf_size) {
163 // no space for new hob
164 return -1;
167 //append new HOB
168 newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
169 sizeof(HOB_GENERIC_HEADER));
170 newhob->signature = HOB_SIGNATURE;
171 newhob->type = type;
172 newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
173 memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
175 // append terminal HOB
176 tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size);
177 tail->signature = HOB_SIGNATURE;
178 tail->type = HOB_TYPE_TERMINAL;
179 tail->length = sizeof(HOB_GENERIC_HEADER);
181 // adjust HOB list length
182 phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
184 return 0;
187 static int
188 get_hob_size(void* hob_buf)
190 HOB_INFO *phit = (HOB_INFO*)hob_buf;
192 if (phit->header.signature != HOB_SIGNATURE) {
193 Hob_Output("xc_get_hob_size:Incorrect signature");
194 return -1;
196 return phit->length;
199 static int
200 add_max_hob_entry(void* hob_buf)
202 long max_hob = 0;
203 return hob_add(hob_buf, HOB_TYPE_MAX, &max_hob, sizeof(long));
206 static int
207 build_hob(void* hob_buf, unsigned long hob_buf_size,
208 unsigned long dom_mem_size, unsigned long vcpus)
210 //Init HOB List
211 if (hob_init(hob_buf, hob_buf_size) < 0) {
212 Hob_Output("buffer too small");
213 goto err_out;
216 if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
217 Hob_Output("Add memory hob failed, buffer too small");
218 goto err_out;
221 if (add_vcpus_hob(hob_buf, vcpus) < 0) {
222 Hob_Output("Add NR_VCPU hob failed, buffer too small");
223 goto err_out;
226 if (add_pal_hob(hob_buf) < 0) {
227 Hob_Output("Add PAL hob failed, buffer too small");
228 goto err_out;
231 if (add_max_hob_entry(hob_buf) < 0) {
232 Hob_Output("Add max hob entry failed, buffer too small");
233 goto err_out;
235 return 0;
237 err_out:
238 return -1;
240 static int
241 load_hob(void *hob_buf, unsigned long dom_mem_size, void* hob_start)
243 int hob_size;
245 hob_size = get_hob_size(hob_buf);
246 if (hob_size < 0) {
247 Hob_Output("Invalid hob data");
248 return -1;
251 if (hob_size > GFW_HOB_SIZE) {
252 Hob_Output("No enough memory for hob data");
253 return -1;
255 memcpy (hob_start, hob_buf, hob_size);
256 return 0;
259 static int
260 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
262 hob_mem_t memhob;
264 // less than 3G
265 memhob.start = 0;
266 memhob.size = MIN(dom_mem_size, 0xC0000000);
268 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
269 return -1;
271 if (dom_mem_size > 0xC0000000) {
272 // 4G ~ 4G+remain
273 memhob.start = 0x100000000; //4G
274 memhob.size = dom_mem_size - 0xC0000000;
275 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
276 return -1;
278 return 0;
281 static int
282 add_vcpus_hob(void* hob_buf, unsigned long vcpus)
284 return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
287 static const unsigned char config_pal_bus_get_features_data[24] = {
288 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
292 static const unsigned char config_pal_cache_summary[16] = {
293 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
296 static const unsigned char config_pal_mem_attrib[8] = {
297 241, 0, 0, 0, 0, 0, 0, 0
300 static const unsigned char config_pal_cache_info[152] = {
301 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
302 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
303 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
304 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
305 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
306 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
307 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
308 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
309 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
310 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
313 static const unsigned char config_pal_cache_prot_info[200] = {
314 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
319 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
321 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
322 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
323 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
325 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
326 0, 0, 0
329 static const unsigned char config_pal_debug_info[16] = {
330 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
333 static const unsigned char config_pal_fixed_addr[8] = {
334 0, 0, 0, 0, 0, 0, 0, 0
337 static const unsigned char config_pal_freq_base[8] = {
338 109, 219, 182, 13, 0, 0, 0, 0
341 static const unsigned char config_pal_freq_ratios[24] = {
342 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
343 0, 0, 0, 7, 0, 0, 0
346 static const unsigned char config_pal_halt_info[64] = {
347 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
349 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
353 static const unsigned char config_pal_perf_mon_info[136] = {
354 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
355 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
356 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
357 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
358 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
362 0, 0, 0, 0, 0, 0, 0, 0
365 static const unsigned char config_pal_proc_get_features[104] = {
366 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
367 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
368 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
369 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
371 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
372 0, 0, 0, 0, 0, 0, 0, 0
375 static const unsigned char config_pal_ptce_info[24] = {
376 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
377 0, 0, 0, 0, 0, 0, 0, 0
380 static const unsigned char config_pal_register_info[64] = {
381 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
382 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
383 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
384 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
387 static const unsigned char config_pal_rse_info[16] = {
388 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
391 static const unsigned char config_pal_test_info[48] = {
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
397 static const unsigned char config_pal_vm_summary[16] = {
398 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
401 static const unsigned char config_pal_vm_info[104] = {
402 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
403 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
405 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
406 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
410 static const unsigned char config_pal_vm_page_size[16] = {
411 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
414 typedef struct{
415 hob_type_t type;
416 void* data;
417 unsigned long size;
418 } hob_batch_t;
420 static const hob_batch_t hob_batch[]={
421 { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
422 &config_pal_bus_get_features_data,
423 sizeof(config_pal_bus_get_features_data)
425 { HOB_TYPE_PAL_CACHE_SUMMARY,
426 &config_pal_cache_summary,
427 sizeof(config_pal_cache_summary)
429 { HOB_TYPE_PAL_MEM_ATTRIB,
430 &config_pal_mem_attrib,
431 sizeof(config_pal_mem_attrib)
433 { HOB_TYPE_PAL_CACHE_INFO,
434 &config_pal_cache_info,
435 sizeof(config_pal_cache_info)
437 { HOB_TYPE_PAL_CACHE_PROT_INFO,
438 &config_pal_cache_prot_info,
439 sizeof(config_pal_cache_prot_info)
441 { HOB_TYPE_PAL_DEBUG_INFO,
442 &config_pal_debug_info,
443 sizeof(config_pal_debug_info)
445 { HOB_TYPE_PAL_FIXED_ADDR,
446 &config_pal_fixed_addr,
447 sizeof(config_pal_fixed_addr)
449 { HOB_TYPE_PAL_FREQ_BASE,
450 &config_pal_freq_base,
451 sizeof(config_pal_freq_base)
453 { HOB_TYPE_PAL_FREQ_RATIOS,
454 &config_pal_freq_ratios,
455 sizeof(config_pal_freq_ratios)
457 { HOB_TYPE_PAL_HALT_INFO,
458 &config_pal_halt_info,
459 sizeof(config_pal_halt_info)
461 { HOB_TYPE_PAL_PERF_MON_INFO,
462 &config_pal_perf_mon_info,
463 sizeof(config_pal_perf_mon_info)
465 { HOB_TYPE_PAL_PROC_GET_FEATURES,
466 &config_pal_proc_get_features,
467 sizeof(config_pal_proc_get_features)
469 { HOB_TYPE_PAL_PTCE_INFO,
470 &config_pal_ptce_info,
471 sizeof(config_pal_ptce_info)
473 { HOB_TYPE_PAL_REGISTER_INFO,
474 &config_pal_register_info,
475 sizeof(config_pal_register_info)
477 { HOB_TYPE_PAL_RSE_INFO,
478 &config_pal_rse_info,
479 sizeof(config_pal_rse_info)
481 { HOB_TYPE_PAL_TEST_INFO,
482 &config_pal_test_info,
483 sizeof(config_pal_test_info)
485 { HOB_TYPE_PAL_VM_SUMMARY,
486 &config_pal_vm_summary,
487 sizeof(config_pal_vm_summary)
489 { HOB_TYPE_PAL_VM_INFO,
490 &config_pal_vm_info,
491 sizeof(config_pal_vm_info)
493 { HOB_TYPE_PAL_VM_PAGE_SIZE,
494 &config_pal_vm_page_size,
495 sizeof(config_pal_vm_page_size)
499 static int
500 add_pal_hob(void* hob_buf)
502 int i;
503 for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) {
504 if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data,
505 hob_batch[i].size) < 0)
506 return -1;
508 return 0;
511 char *read_image(const char *filename, unsigned long *size)
513 int kernel_fd = -1;
514 gzFile kernel_gfd = NULL;
515 char *image = NULL, *tmp;
516 unsigned int bytes;
518 if ((filename == NULL) || (size == NULL))
519 return NULL;
521 kernel_fd = open(filename, O_RDONLY);
522 if (kernel_fd < 0) {
523 Hob_Output("Could not open kernel image\n");
524 goto out_1;
527 if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
528 Hob_Output("Could not allocate decompression state for state file\n");
529 goto out_1;
532 *size = 0;
534 #define CHUNK 1*1024*1024
535 while(1)
537 if ((tmp = realloc(image, *size + CHUNK)) == NULL) {
538 Hob_Output("Could not allocate memory for kernel image");
539 free(image);
540 image = NULL;
541 goto out;
543 image = tmp;
545 bytes = gzread(kernel_gfd, image + *size, CHUNK);
546 switch (bytes) {
547 case -1:
548 Hob_Output("Error reading kernel image");
549 free(image);
550 image = NULL;
551 goto out;
552 case 0: /* EOF */
553 goto out;
554 default:
555 *size += bytes;
556 break;
559 #undef CHUNK
561 out:
562 if (*size == 0) {
563 Hob_Output("Could not read kernel image");
564 free(image);
565 image = NULL;
566 } else if (image) {
567 /* Shrink allocation to fit image. */
568 tmp = realloc(image, *size);
569 if (tmp)
570 image = tmp;
573 if (kernel_gfd != NULL)
574 gzclose(kernel_gfd);
575 else if (kernel_fd >= 0)
576 close(kernel_fd);
577 return image;
579 out_1:
580 return NULL;
584 * Local variables:
585 * mode: C
586 * c-set-style: "BSD"
587 * c-basic-offset: 4
588 * tab-width: 4
589 * indent-tabs-mode: nil
590 * End: