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>
35 unsigned long signature
;
41 * INFO HOB is the first data data in one HOB list
42 * it contains the control information of the HOB list
45 HOB_GENERIC_HEADER header
;
46 unsigned long length
; // current length of hob
47 unsigned long cur_pos
; // current poisiton of hob
48 unsigned long buf_size
; // size of hob buffer
60 HOB_TYPE_PAL_BUS_GET_FEATURES_DATA
,
61 HOB_TYPE_PAL_CACHE_SUMMARY
,
62 HOB_TYPE_PAL_MEM_ATTRIB
,
63 HOB_TYPE_PAL_CACHE_INFO
,
64 HOB_TYPE_PAL_CACHE_PROT_INFO
,
65 HOB_TYPE_PAL_DEBUG_INFO
,
66 HOB_TYPE_PAL_FIXED_ADDR
,
67 HOB_TYPE_PAL_FREQ_BASE
,
68 HOB_TYPE_PAL_FREQ_RATIOS
,
69 HOB_TYPE_PAL_HALT_INFO
,
70 HOB_TYPE_PAL_PERF_MON_INFO
,
71 HOB_TYPE_PAL_PROC_GET_FEATURES
,
72 HOB_TYPE_PAL_PTCE_INFO
,
73 HOB_TYPE_PAL_REGISTER_INFO
,
74 HOB_TYPE_PAL_RSE_INFO
,
75 HOB_TYPE_PAL_TEST_INFO
,
76 HOB_TYPE_PAL_VM_SUMMARY
,
78 HOB_TYPE_PAL_VM_PAGE_SIZE
,
84 static int hob_init(void *buffer
,unsigned long buf_size
);
85 static int add_pal_hob(void* hob_buf
);
86 static int add_mem_hob(void* hob_buf
, unsigned long dom_mem_size
);
87 static int add_vcpus_hob(void* hob_buf
, unsigned long nr_vcpu
);
88 static int build_hob(void* hob_buf
, unsigned long hob_buf_size
,
89 unsigned long dom_mem_size
, unsigned long vcpus
);
90 static int load_hob(void *hob_buf
,
91 unsigned long dom_mem_size
, void* hob_start
);
94 kvm_ia64_build_hob(unsigned long memsize
,
95 unsigned long vcpus
, uint8_t* fw_start
)
99 hob_buf
= malloc(GFW_HOB_SIZE
);
100 if (hob_buf
== NULL
) {
101 Hob_Output("Hob: Could not allocate hob");
105 if (build_hob(hob_buf
, GFW_HOB_SIZE
, memsize
, vcpus
) < 0) {
107 Hob_Output("Could not build hob");
110 if (load_hob(hob_buf
, memsize
, fw_start
+ HOB_OFFSET
) < 0) {
112 Hob_Output("Could not load hob");
121 hob_init(void *buffer
, unsigned long buf_size
)
124 HOB_GENERIC_HEADER
*terminal
;
126 if (sizeof(HOB_INFO
) + sizeof(HOB_GENERIC_HEADER
) > buf_size
) {
131 phit
= (HOB_INFO
*)buffer
;
132 phit
->header
.signature
= HOB_SIGNATURE
;
133 phit
->header
.type
= HOB_TYPE_INFO
;
134 phit
->header
.length
= sizeof(HOB_INFO
);
135 phit
->length
= sizeof(HOB_INFO
) + sizeof(HOB_GENERIC_HEADER
);
137 phit
->buf_size
= buf_size
;
139 terminal
= (HOB_GENERIC_HEADER
*)(buffer
+ sizeof(HOB_INFO
));
140 terminal
->signature
= HOB_SIGNATURE
;
141 terminal
->type
= HOB_TYPE_TERMINAL
;
142 terminal
->length
= sizeof(HOB_GENERIC_HEADER
);
148 * Add a new HOB to the HOB List.
150 * hob_start - start address of hob buffer
151 * type - type of the hob to be added
152 * data - data of the hob to be added
153 * data_size - size of the data
156 hob_add(void* hob_start
, int type
, void* data
, int data_size
)
159 HOB_GENERIC_HEADER
*newhob
, *tail
;
161 phit
= (HOB_INFO
*)hob_start
;
163 if (phit
->length
+ data_size
> phit
->buf_size
) {
164 // no space for new hob
169 newhob
= (HOB_GENERIC_HEADER
*)(hob_start
+ phit
->length
-
170 sizeof(HOB_GENERIC_HEADER
));
171 newhob
->signature
= HOB_SIGNATURE
;
173 newhob
->length
= data_size
+ sizeof(HOB_GENERIC_HEADER
);
174 memcpy((void*)newhob
+ sizeof(HOB_GENERIC_HEADER
), data
, data_size
);
176 // append terminal HOB
177 tail
= (HOB_GENERIC_HEADER
*)(hob_start
+ phit
->length
+ data_size
);
178 tail
->signature
= HOB_SIGNATURE
;
179 tail
->type
= HOB_TYPE_TERMINAL
;
180 tail
->length
= sizeof(HOB_GENERIC_HEADER
);
182 // adjust HOB list length
183 phit
->length
+= sizeof(HOB_GENERIC_HEADER
) + data_size
;
189 get_hob_size(void* hob_buf
)
191 HOB_INFO
*phit
= (HOB_INFO
*)hob_buf
;
193 if (phit
->header
.signature
!= HOB_SIGNATURE
) {
194 Hob_Output("xc_get_hob_size:Incorrect signature");
201 add_max_hob_entry(void* hob_buf
)
204 return hob_add(hob_buf
, HOB_TYPE_MAX
, &max_hob
, sizeof(long));
208 build_hob(void* hob_buf
, unsigned long hob_buf_size
,
209 unsigned long dom_mem_size
, unsigned long vcpus
)
212 if (hob_init(hob_buf
, hob_buf_size
) < 0) {
213 Hob_Output("buffer too small");
217 if (add_mem_hob(hob_buf
,dom_mem_size
) < 0) {
218 Hob_Output("Add memory hob failed, buffer too small");
222 if (add_vcpus_hob(hob_buf
, vcpus
) < 0) {
223 Hob_Output("Add NR_VCPU hob failed, buffer too small");
227 if (add_pal_hob(hob_buf
) < 0) {
228 Hob_Output("Add PAL hob failed, buffer too small");
232 if (add_max_hob_entry(hob_buf
) < 0) {
233 Hob_Output("Add max hob entry failed, buffer too small");
242 load_hob(void *hob_buf
, unsigned long dom_mem_size
, void* hob_start
)
246 hob_size
= get_hob_size(hob_buf
);
248 Hob_Output("Invalid hob data");
252 if (hob_size
> GFW_HOB_SIZE
) {
253 Hob_Output("No enough memory for hob data");
256 memcpy (hob_start
, hob_buf
, hob_size
);
261 add_mem_hob(void* hob_buf
, unsigned long dom_mem_size
)
267 memhob
.size
= MIN(dom_mem_size
, 0xC0000000);
269 if (hob_add(hob_buf
, HOB_TYPE_MEM
, &memhob
, sizeof(memhob
)) < 0)
272 if (dom_mem_size
> 0xC0000000) {
274 memhob
.start
= 0x100000000; //4G
275 memhob
.size
= dom_mem_size
- 0xC0000000;
276 if (hob_add(hob_buf
, HOB_TYPE_MEM
, &memhob
, sizeof(memhob
)) < 0)
283 add_vcpus_hob(void* hob_buf
, unsigned long vcpus
)
285 return hob_add(hob_buf
, HOB_TYPE_NR_VCPU
, &vcpus
, sizeof(vcpus
));
288 static const unsigned char config_pal_bus_get_features_data
[24] = {
289 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
293 static const unsigned char config_pal_cache_summary
[16] = {
294 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
297 static const unsigned char config_pal_mem_attrib
[8] = {
298 241, 0, 0, 0, 0, 0, 0, 0
301 static const unsigned char config_pal_cache_info
[152] = {
302 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
303 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
304 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
305 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
306 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
307 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
308 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
309 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
310 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
311 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
314 static const unsigned char config_pal_cache_prot_info
[200] = {
315 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
316 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
318 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
320 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
322 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
323 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
324 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
326 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 static const unsigned char config_pal_debug_info
[16] = {
331 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
334 static const unsigned char config_pal_fixed_addr
[8] = {
335 0, 0, 0, 0, 0, 0, 0, 0
338 static const unsigned char config_pal_freq_base
[8] = {
339 109, 219, 182, 13, 0, 0, 0, 0
342 static const unsigned char config_pal_freq_ratios
[24] = {
343 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
347 static const unsigned char config_pal_halt_info
[64] = {
348 0, 0, 0, 0, 0, 0, 0, 48, 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,
351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
354 static const unsigned char config_pal_perf_mon_info
[136] = {
355 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
356 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
357 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
358 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
363 0, 0, 0, 0, 0, 0, 0, 0
366 static const unsigned char config_pal_proc_get_features
[104] = {
367 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
368 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
369 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
370 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
372 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0
376 static const unsigned char config_pal_ptce_info
[24] = {
377 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0
381 static const unsigned char config_pal_register_info
[64] = {
382 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
383 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
384 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
385 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
388 static const unsigned char config_pal_rse_info
[16] = {
389 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
392 static const unsigned char config_pal_test_info
[48] = {
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, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
398 static const unsigned char config_pal_vm_summary
[16] = {
399 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
402 static const unsigned char config_pal_vm_info
[104] = {
403 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
404 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
406 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
407 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
411 static const unsigned char config_pal_vm_page_size
[16] = {
412 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
421 static const hob_batch_t hob_batch
[]={
422 { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA
,
423 &config_pal_bus_get_features_data
,
424 sizeof(config_pal_bus_get_features_data
)
426 { HOB_TYPE_PAL_CACHE_SUMMARY
,
427 &config_pal_cache_summary
,
428 sizeof(config_pal_cache_summary
)
430 { HOB_TYPE_PAL_MEM_ATTRIB
,
431 &config_pal_mem_attrib
,
432 sizeof(config_pal_mem_attrib
)
434 { HOB_TYPE_PAL_CACHE_INFO
,
435 &config_pal_cache_info
,
436 sizeof(config_pal_cache_info
)
438 { HOB_TYPE_PAL_CACHE_PROT_INFO
,
439 &config_pal_cache_prot_info
,
440 sizeof(config_pal_cache_prot_info
)
442 { HOB_TYPE_PAL_DEBUG_INFO
,
443 &config_pal_debug_info
,
444 sizeof(config_pal_debug_info
)
446 { HOB_TYPE_PAL_FIXED_ADDR
,
447 &config_pal_fixed_addr
,
448 sizeof(config_pal_fixed_addr
)
450 { HOB_TYPE_PAL_FREQ_BASE
,
451 &config_pal_freq_base
,
452 sizeof(config_pal_freq_base
)
454 { HOB_TYPE_PAL_FREQ_RATIOS
,
455 &config_pal_freq_ratios
,
456 sizeof(config_pal_freq_ratios
)
458 { HOB_TYPE_PAL_HALT_INFO
,
459 &config_pal_halt_info
,
460 sizeof(config_pal_halt_info
)
462 { HOB_TYPE_PAL_PERF_MON_INFO
,
463 &config_pal_perf_mon_info
,
464 sizeof(config_pal_perf_mon_info
)
466 { HOB_TYPE_PAL_PROC_GET_FEATURES
,
467 &config_pal_proc_get_features
,
468 sizeof(config_pal_proc_get_features
)
470 { HOB_TYPE_PAL_PTCE_INFO
,
471 &config_pal_ptce_info
,
472 sizeof(config_pal_ptce_info
)
474 { HOB_TYPE_PAL_REGISTER_INFO
,
475 &config_pal_register_info
,
476 sizeof(config_pal_register_info
)
478 { HOB_TYPE_PAL_RSE_INFO
,
479 &config_pal_rse_info
,
480 sizeof(config_pal_rse_info
)
482 { HOB_TYPE_PAL_TEST_INFO
,
483 &config_pal_test_info
,
484 sizeof(config_pal_test_info
)
486 { HOB_TYPE_PAL_VM_SUMMARY
,
487 &config_pal_vm_summary
,
488 sizeof(config_pal_vm_summary
)
490 { HOB_TYPE_PAL_VM_INFO
,
492 sizeof(config_pal_vm_info
)
494 { HOB_TYPE_PAL_VM_PAGE_SIZE
,
495 &config_pal_vm_page_size
,
496 sizeof(config_pal_vm_page_size
)
501 add_pal_hob(void* hob_buf
)
504 for (i
= 0; i
< sizeof(hob_batch
)/sizeof(hob_batch_t
); i
++) {
505 if (hob_add(hob_buf
, hob_batch
[i
].type
, hob_batch
[i
].data
,
506 hob_batch
[i
].size
) < 0)
512 char *read_image(const char *filename
, unsigned long *size
)
515 gzFile kernel_gfd
= NULL
;
516 char *image
= NULL
, *tmp
;
519 if ((filename
== NULL
) || (size
== NULL
))
522 kernel_fd
= open(filename
, O_RDONLY
);
524 Hob_Output("Could not open kernel image\n");
528 if ((kernel_gfd
= gzdopen(kernel_fd
, "rb")) == NULL
) {
529 Hob_Output("Could not allocate decompression state for state file\n");
535 #define CHUNK 1*1024*1024
538 if ((tmp
= realloc(image
, *size
+ CHUNK
)) == NULL
) {
539 Hob_Output("Could not allocate memory for kernel image");
546 bytes
= gzread(kernel_gfd
, image
+ *size
, CHUNK
);
549 Hob_Output("Error reading kernel image");
564 Hob_Output("Could not read kernel image");
568 /* Shrink allocation to fit image. */
569 tmp
= realloc(image
, *size
);
574 if (kernel_gfd
!= NULL
)
576 else if (kernel_fd
>= 0)
590 * indent-tabs-mode: nil