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
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.
26 #include <sys/types.h>
34 #include "qemu-common.h"
37 unsigned long signature
;
43 * INFO HOB is the first data data in one HOB list
44 * it contains the control information of the HOB list
47 HOB_GENERIC_HEADER header
;
48 unsigned long length
; // current length of hob
49 unsigned long cur_pos
; // current poisiton of hob
50 unsigned long buf_size
; // size of hob buffer
62 HOB_TYPE_PAL_BUS_GET_FEATURES_DATA
,
63 HOB_TYPE_PAL_CACHE_SUMMARY
,
64 HOB_TYPE_PAL_MEM_ATTRIB
,
65 HOB_TYPE_PAL_CACHE_INFO
,
66 HOB_TYPE_PAL_CACHE_PROT_INFO
,
67 HOB_TYPE_PAL_DEBUG_INFO
,
68 HOB_TYPE_PAL_FIXED_ADDR
,
69 HOB_TYPE_PAL_FREQ_BASE
,
70 HOB_TYPE_PAL_FREQ_RATIOS
,
71 HOB_TYPE_PAL_HALT_INFO
,
72 HOB_TYPE_PAL_PERF_MON_INFO
,
73 HOB_TYPE_PAL_PROC_GET_FEATURES
,
74 HOB_TYPE_PAL_PTCE_INFO
,
75 HOB_TYPE_PAL_REGISTER_INFO
,
76 HOB_TYPE_PAL_RSE_INFO
,
77 HOB_TYPE_PAL_TEST_INFO
,
78 HOB_TYPE_PAL_VM_SUMMARY
,
80 HOB_TYPE_PAL_VM_PAGE_SIZE
,
86 static int hob_init(void *buffer
,unsigned long buf_size
);
87 static int add_pal_hob(void* hob_buf
);
88 static int add_mem_hob(void* hob_buf
, unsigned long dom_mem_size
);
89 static int add_vcpus_hob(void* hob_buf
, unsigned long nr_vcpu
);
90 static int add_nvram_hob(void *hob_buf
, unsigned long nvram_addr
);
91 static int build_hob(void *hob_buf
, unsigned long hob_buf_size
,
92 unsigned long dom_mem_size
, unsigned long vcpus
,
93 unsigned long nvram_addr
);
94 static int load_hob(void *hob_buf
,
95 unsigned long dom_mem_size
, void* hob_start
);
98 kvm_ia64_build_hob(unsigned long memsize
, unsigned long vcpus
,
99 uint8_t *fw_start
, unsigned long nvram_addr
)
103 hob_buf
= malloc(GFW_HOB_SIZE
);
104 if (hob_buf
== NULL
) {
105 Hob_Output("Hob: Could not allocate hob");
109 if (build_hob(hob_buf
, GFW_HOB_SIZE
, memsize
, vcpus
, nvram_addr
) < 0) {
111 Hob_Output("Could not build hob");
114 if (load_hob(hob_buf
, memsize
, fw_start
+ HOB_OFFSET
) < 0) {
116 Hob_Output("Could not load hob");
125 hob_init(void *buffer
, unsigned long buf_size
)
128 HOB_GENERIC_HEADER
*terminal
;
130 if (sizeof(HOB_INFO
) + sizeof(HOB_GENERIC_HEADER
) > buf_size
) {
135 phit
= (HOB_INFO
*)buffer
;
136 phit
->header
.signature
= HOB_SIGNATURE
;
137 phit
->header
.type
= HOB_TYPE_INFO
;
138 phit
->header
.length
= sizeof(HOB_INFO
);
139 phit
->length
= sizeof(HOB_INFO
) + sizeof(HOB_GENERIC_HEADER
);
141 phit
->buf_size
= buf_size
;
143 terminal
= (HOB_GENERIC_HEADER
*)(buffer
+ sizeof(HOB_INFO
));
144 terminal
->signature
= HOB_SIGNATURE
;
145 terminal
->type
= HOB_TYPE_TERMINAL
;
146 terminal
->length
= sizeof(HOB_GENERIC_HEADER
);
152 * Add a new HOB to the HOB List.
154 * hob_start - start address of hob buffer
155 * type - type of the hob to be added
156 * data - data of the hob to be added
157 * data_size - size of the data
160 hob_add(void* hob_start
, int type
, void* data
, int data_size
)
163 HOB_GENERIC_HEADER
*newhob
, *tail
;
165 phit
= (HOB_INFO
*)hob_start
;
167 if (phit
->length
+ data_size
> phit
->buf_size
) {
168 // no space for new hob
173 newhob
= (HOB_GENERIC_HEADER
*)(hob_start
+ phit
->length
-
174 sizeof(HOB_GENERIC_HEADER
));
175 newhob
->signature
= HOB_SIGNATURE
;
177 newhob
->length
= data_size
+ sizeof(HOB_GENERIC_HEADER
);
178 memcpy((void*)newhob
+ sizeof(HOB_GENERIC_HEADER
), data
, data_size
);
180 // append terminal HOB
181 tail
= (HOB_GENERIC_HEADER
*)(hob_start
+ phit
->length
+ data_size
);
182 tail
->signature
= HOB_SIGNATURE
;
183 tail
->type
= HOB_TYPE_TERMINAL
;
184 tail
->length
= sizeof(HOB_GENERIC_HEADER
);
186 // adjust HOB list length
187 phit
->length
+= sizeof(HOB_GENERIC_HEADER
) + data_size
;
193 get_hob_size(void* hob_buf
)
195 HOB_INFO
*phit
= (HOB_INFO
*)hob_buf
;
197 if (phit
->header
.signature
!= HOB_SIGNATURE
) {
198 Hob_Output("xc_get_hob_size:Incorrect signature");
205 add_max_hob_entry(void* hob_buf
)
208 return hob_add(hob_buf
, HOB_TYPE_MAX
, &max_hob
, sizeof(long));
212 build_hob(void* hob_buf
, unsigned long hob_buf_size
,
213 unsigned long dom_mem_size
, unsigned long vcpus
,
214 unsigned long nvram_addr
)
217 if (hob_init(hob_buf
, hob_buf_size
) < 0) {
218 Hob_Output("buffer too small");
222 if (add_mem_hob(hob_buf
,dom_mem_size
) < 0) {
223 Hob_Output("Add memory hob failed, buffer too small");
227 if (add_vcpus_hob(hob_buf
, vcpus
) < 0) {
228 Hob_Output("Add NR_VCPU hob failed, buffer too small");
232 if (add_pal_hob(hob_buf
) < 0) {
233 Hob_Output("Add PAL hob failed, buffer too small");
237 if (add_nvram_hob(hob_buf
, nvram_addr
) < 0) {
238 Hob_Output("Add nvram hob failed, buffer too small");
242 if (add_max_hob_entry(hob_buf
) < 0) {
243 Hob_Output("Add max hob entry failed, buffer too small");
252 load_hob(void *hob_buf
, unsigned long dom_mem_size
, void* hob_start
)
256 hob_size
= get_hob_size(hob_buf
);
258 Hob_Output("Invalid hob data");
262 if (hob_size
> GFW_HOB_SIZE
) {
263 Hob_Output("No enough memory for hob data");
266 memcpy (hob_start
, hob_buf
, hob_size
);
271 add_mem_hob(void* hob_buf
, unsigned long dom_mem_size
)
277 memhob
.size
= MIN(dom_mem_size
, 0xC0000000);
279 if (hob_add(hob_buf
, HOB_TYPE_MEM
, &memhob
, sizeof(memhob
)) < 0)
282 if (dom_mem_size
> 0xC0000000) {
284 memhob
.start
= 0x100000000; //4G
285 memhob
.size
= dom_mem_size
- 0xC0000000;
286 if (hob_add(hob_buf
, HOB_TYPE_MEM
, &memhob
, sizeof(memhob
)) < 0)
293 add_vcpus_hob(void* hob_buf
, unsigned long vcpus
)
295 return hob_add(hob_buf
, HOB_TYPE_NR_VCPU
, &vcpus
, sizeof(vcpus
));
299 add_nvram_hob(void *hob_buf
, unsigned long nvram_addr
)
301 return hob_add(hob_buf
, HOB_TYPE_NR_NVRAM
,
302 &nvram_addr
, sizeof(nvram_addr
));
305 static const unsigned char config_pal_bus_get_features_data
[24] = {
306 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
310 static const unsigned char config_pal_cache_summary
[16] = {
311 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
314 static const unsigned char config_pal_mem_attrib
[8] = {
315 241, 0, 0, 0, 0, 0, 0, 0
318 static const unsigned char config_pal_cache_info
[152] = {
319 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
321 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
322 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
323 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
324 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
325 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
326 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
327 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
328 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
331 static const unsigned char config_pal_cache_prot_info
[200] = {
332 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
337 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
339 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
341 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
343 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 static const unsigned char config_pal_debug_info
[16] = {
348 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
351 static const unsigned char config_pal_fixed_addr
[8] = {
352 0, 0, 0, 0, 0, 0, 0, 0
355 static const unsigned char config_pal_freq_base
[8] = {
356 109, 219, 182, 13, 0, 0, 0, 0
359 static const unsigned char config_pal_freq_ratios
[24] = {
360 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
364 static const unsigned char config_pal_halt_info
[64] = {
365 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
366 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
367 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
368 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
371 static const unsigned char config_pal_perf_mon_info
[136] = {
372 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
377 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
379 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
380 0, 0, 0, 0, 0, 0, 0, 0
383 static const unsigned char config_pal_proc_get_features
[104] = {
384 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
387 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
388 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
389 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
390 0, 0, 0, 0, 0, 0, 0, 0
393 static const unsigned char config_pal_ptce_info
[24] = {
394 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0
398 static const unsigned char config_pal_register_info
[64] = {
399 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
400 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
401 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
402 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
405 static const unsigned char config_pal_rse_info
[16] = {
406 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
409 static const unsigned char config_pal_test_info
[48] = {
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
415 static const unsigned char config_pal_vm_summary
[16] = {
416 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
419 static const unsigned char config_pal_vm_info
[104] = {
420 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
421 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
422 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
423 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
424 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
425 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
428 static const unsigned char config_pal_vm_page_size
[16] = {
429 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
438 static const hob_batch_t hob_batch
[]={
439 { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA
,
440 &config_pal_bus_get_features_data
,
441 sizeof(config_pal_bus_get_features_data
)
443 { HOB_TYPE_PAL_CACHE_SUMMARY
,
444 &config_pal_cache_summary
,
445 sizeof(config_pal_cache_summary
)
447 { HOB_TYPE_PAL_MEM_ATTRIB
,
448 &config_pal_mem_attrib
,
449 sizeof(config_pal_mem_attrib
)
451 { HOB_TYPE_PAL_CACHE_INFO
,
452 &config_pal_cache_info
,
453 sizeof(config_pal_cache_info
)
455 { HOB_TYPE_PAL_CACHE_PROT_INFO
,
456 &config_pal_cache_prot_info
,
457 sizeof(config_pal_cache_prot_info
)
459 { HOB_TYPE_PAL_DEBUG_INFO
,
460 &config_pal_debug_info
,
461 sizeof(config_pal_debug_info
)
463 { HOB_TYPE_PAL_FIXED_ADDR
,
464 &config_pal_fixed_addr
,
465 sizeof(config_pal_fixed_addr
)
467 { HOB_TYPE_PAL_FREQ_BASE
,
468 &config_pal_freq_base
,
469 sizeof(config_pal_freq_base
)
471 { HOB_TYPE_PAL_FREQ_RATIOS
,
472 &config_pal_freq_ratios
,
473 sizeof(config_pal_freq_ratios
)
475 { HOB_TYPE_PAL_HALT_INFO
,
476 &config_pal_halt_info
,
477 sizeof(config_pal_halt_info
)
479 { HOB_TYPE_PAL_PERF_MON_INFO
,
480 &config_pal_perf_mon_info
,
481 sizeof(config_pal_perf_mon_info
)
483 { HOB_TYPE_PAL_PROC_GET_FEATURES
,
484 &config_pal_proc_get_features
,
485 sizeof(config_pal_proc_get_features
)
487 { HOB_TYPE_PAL_PTCE_INFO
,
488 &config_pal_ptce_info
,
489 sizeof(config_pal_ptce_info
)
491 { HOB_TYPE_PAL_REGISTER_INFO
,
492 &config_pal_register_info
,
493 sizeof(config_pal_register_info
)
495 { HOB_TYPE_PAL_RSE_INFO
,
496 &config_pal_rse_info
,
497 sizeof(config_pal_rse_info
)
499 { HOB_TYPE_PAL_TEST_INFO
,
500 &config_pal_test_info
,
501 sizeof(config_pal_test_info
)
503 { HOB_TYPE_PAL_VM_SUMMARY
,
504 &config_pal_vm_summary
,
505 sizeof(config_pal_vm_summary
)
507 { HOB_TYPE_PAL_VM_INFO
,
509 sizeof(config_pal_vm_info
)
511 { HOB_TYPE_PAL_VM_PAGE_SIZE
,
512 &config_pal_vm_page_size
,
513 sizeof(config_pal_vm_page_size
)
518 add_pal_hob(void* hob_buf
)
521 for (i
= 0; i
< sizeof(hob_batch
)/sizeof(hob_batch_t
); i
++) {
522 if (hob_add(hob_buf
, hob_batch
[i
].type
, hob_batch
[i
].data
,
523 hob_batch
[i
].size
) < 0)
529 char *read_image(const char *filename
, unsigned long *size
)
532 gzFile kernel_gfd
= NULL
;
533 char *image
= NULL
, *tmp
;
536 if ((filename
== NULL
) || (size
== NULL
))
539 kernel_fd
= open(filename
, O_RDONLY
);
541 Hob_Output("Could not open kernel image\n");
545 if ((kernel_gfd
= gzdopen(kernel_fd
, "rb")) == NULL
) {
546 Hob_Output("Could not allocate decompression state for state file\n");
552 #define CHUNK 1*1024*1024
555 if ((tmp
= realloc(image
, *size
+ CHUNK
)) == NULL
) {
556 Hob_Output("Could not allocate memory for kernel image");
563 bytes
= gzread(kernel_gfd
, image
+ *size
, CHUNK
);
566 Hob_Output("Error reading kernel image");
581 Hob_Output("Could not read kernel image");
585 /* Shrink allocation to fit image. */
586 tmp
= realloc(image
, *size
);
591 if (kernel_gfd
!= NULL
)
593 else if (kernel_fd
>= 0)
601 int kvm_ia64_nvram_init(unsigned long type
)
603 unsigned long nvram_fd
;
604 char nvram_path
[PATH_MAX
];
608 if (strlen(nvram
) > PATH_MAX
) {
611 if (type
== READ_FROM_NVRAM
) {
612 if (access(nvram
, R_OK
| W_OK
| X_OK
) == -1)
614 nvram_fd
= open(nvram
, O_RDONLY
);
617 else { /* write from gfw to nvram file */
618 i
= access(nvram
, R_OK
| W_OK
| X_OK
);
619 if ((i
== -1) && (errno
!= ENOENT
))
621 nvram_fd
= open(nvram
, O_CREAT
|O_RDWR
, 0777);
626 strcpy(nvram_path
, "nvram.dat");
627 if (type
== READ_FROM_NVRAM
) {
628 if (access(nvram_path
, R_OK
| W_OK
| X_OK
) == -1)
630 nvram_fd
= open(nvram_path
, O_RDONLY
);
633 else { /* write from gfw to nvram file */
634 i
= access(nvram_path
, R_OK
| W_OK
| X_OK
);
635 if ((i
== -1) && (errno
!= ENOENT
))
637 nvram_fd
= open(nvram_path
, O_CREAT
|O_RDWR
, 0777);
646 kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd
,
647 const uint8_t *fw_start
)
649 struct stat file_stat
;
650 if ((fstat(nvram_fd
, &file_stat
) < 0) ||
651 (NVRAM_SIZE
!= file_stat
.st_size
) ||
652 (read(nvram_fd
, (void *)(fw_start
+ NVRAM_OFFSET
),
653 NVRAM_SIZE
) != NVRAM_SIZE
))
659 kvm_ia64_copy_from_GFW_to_nvram()
661 unsigned long nvram_fd
;
662 unsigned long type
= WRITE_TO_NVRAM
;
663 unsigned long *nvram_addr
= (unsigned long *)(g_fw_start
+ NVRAM_OFFSET
);
664 nvram_fd
= kvm_ia64_nvram_init(type
);
667 if (((struct nvram_save_addr
*)nvram_addr
)->signature
!= NVRAM_VALID_SIG
) {
671 lseek(nvram_fd
, 0, SEEK_SET
);
672 if (write(nvram_fd
, ((void *)(((struct nvram_save_addr
*)nvram_addr
)->addr
+
673 (char *)phys_ram_base
)), NVRAM_SIZE
) != NVRAM_SIZE
) {
689 * indent-tabs-mode: nil