Device-assignment: introduce add_assigned_devices()
[qemu-kvm/fedora.git] / target-ia64 / firmware.c
blobbac2721f284cba36c589e6c0c1574930ecff5434
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 <stdio.h>
25 #include <zlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
30 #include "cpu.h"
32 #include "firmware.h"
34 typedef struct {
35 unsigned long signature;
36 unsigned int type;
37 unsigned int length;
38 } HOB_GENERIC_HEADER;
41 * INFO HOB is the first data data in one HOB list
42 * it contains the control information of the HOB list
44 typedef struct {
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
49 } HOB_INFO;
51 typedef struct{
52 unsigned long start;
53 unsigned long size;
54 } hob_mem_t;
56 typedef enum {
57 HOB_TYPE_INFO=0,
58 HOB_TYPE_TERMINAL,
59 HOB_TYPE_MEM,
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,
77 HOB_TYPE_PAL_VM_INFO,
78 HOB_TYPE_PAL_VM_PAGE_SIZE,
79 HOB_TYPE_NR_VCPU,
80 HOB_TYPE_NR_NVRAM,
81 HOB_TYPE_MAX
82 } hob_type_t;
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);
93 int
94 kvm_ia64_build_hob(unsigned long memsize,
95 unsigned long vcpus, uint8_t* fw_start)
97 char *hob_buf;
99 hob_buf = malloc(GFW_HOB_SIZE);
100 if (hob_buf == NULL) {
101 Hob_Output("Hob: Could not allocate hob");
102 return -1;
105 if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) < 0) {
106 free(hob_buf);
107 Hob_Output("Could not build hob");
108 return -1;
110 if (load_hob(hob_buf, memsize, fw_start + HOB_OFFSET) < 0) {
111 free(hob_buf);
112 Hob_Output("Could not load hob");
113 return -1;
115 free(hob_buf);
117 return 0;
120 static int
121 hob_init(void *buffer, unsigned long buf_size)
123 HOB_INFO *phit;
124 HOB_GENERIC_HEADER *terminal;
126 if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
127 // buffer too small
128 return -1;
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);
136 phit->cur_pos = 0;
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);
144 return 0;
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
155 static int
156 hob_add(void* hob_start, int type, void* data, int data_size)
158 HOB_INFO *phit;
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
165 return -1;
168 //append new HOB
169 newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
170 sizeof(HOB_GENERIC_HEADER));
171 newhob->signature = HOB_SIGNATURE;
172 newhob->type = type;
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;
185 return 0;
188 static int
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");
195 return -1;
197 return phit->length;
200 static int
201 add_max_hob_entry(void* hob_buf)
203 long max_hob = 0;
204 return hob_add(hob_buf, HOB_TYPE_MAX, &max_hob, sizeof(long));
207 static int
208 build_hob(void* hob_buf, unsigned long hob_buf_size,
209 unsigned long dom_mem_size, unsigned long vcpus)
211 //Init HOB List
212 if (hob_init(hob_buf, hob_buf_size) < 0) {
213 Hob_Output("buffer too small");
214 goto err_out;
217 if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
218 Hob_Output("Add memory hob failed, buffer too small");
219 goto err_out;
222 if (add_vcpus_hob(hob_buf, vcpus) < 0) {
223 Hob_Output("Add NR_VCPU hob failed, buffer too small");
224 goto err_out;
227 if (add_pal_hob(hob_buf) < 0) {
228 Hob_Output("Add PAL hob failed, buffer too small");
229 goto err_out;
232 if (add_max_hob_entry(hob_buf) < 0) {
233 Hob_Output("Add max hob entry failed, buffer too small");
234 goto err_out;
236 return 0;
238 err_out:
239 return -1;
241 static int
242 load_hob(void *hob_buf, unsigned long dom_mem_size, void* hob_start)
244 int hob_size;
246 hob_size = get_hob_size(hob_buf);
247 if (hob_size < 0) {
248 Hob_Output("Invalid hob data");
249 return -1;
252 if (hob_size > GFW_HOB_SIZE) {
253 Hob_Output("No enough memory for hob data");
254 return -1;
256 memcpy (hob_start, hob_buf, hob_size);
257 return 0;
260 static int
261 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
263 hob_mem_t memhob;
265 // less than 3G
266 memhob.start = 0;
267 memhob.size = MIN(dom_mem_size, 0xC0000000);
269 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
270 return -1;
272 if (dom_mem_size > 0xC0000000) {
273 // 4G ~ 4G+remain
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)
277 return -1;
279 return 0;
282 static int
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,
327 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,
344 0, 0, 0, 7, 0, 0, 0
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
415 typedef struct{
416 hob_type_t type;
417 void* data;
418 unsigned long size;
419 } hob_batch_t;
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,
491 &config_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)
500 static int
501 add_pal_hob(void* hob_buf)
503 int i;
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)
507 return -1;
509 return 0;
512 char *read_image(const char *filename, unsigned long *size)
514 int kernel_fd = -1;
515 gzFile kernel_gfd = NULL;
516 char *image = NULL, *tmp;
517 unsigned int bytes;
519 if ((filename == NULL) || (size == NULL))
520 return NULL;
522 kernel_fd = open(filename, O_RDONLY);
523 if (kernel_fd < 0) {
524 Hob_Output("Could not open kernel image\n");
525 goto out_1;
528 if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
529 Hob_Output("Could not allocate decompression state for state file\n");
530 goto out_1;
533 *size = 0;
535 #define CHUNK 1*1024*1024
536 while(1)
538 if ((tmp = realloc(image, *size + CHUNK)) == NULL) {
539 Hob_Output("Could not allocate memory for kernel image");
540 free(image);
541 image = NULL;
542 goto out;
544 image = tmp;
546 bytes = gzread(kernel_gfd, image + *size, CHUNK);
547 switch (bytes) {
548 case -1:
549 Hob_Output("Error reading kernel image");
550 free(image);
551 image = NULL;
552 goto out;
553 case 0: /* EOF */
554 goto out;
555 default:
556 *size += bytes;
557 break;
560 #undef CHUNK
562 out:
563 if (*size == 0) {
564 Hob_Output("Could not read kernel image");
565 free(image);
566 image = NULL;
567 } else if (image) {
568 /* Shrink allocation to fit image. */
569 tmp = realloc(image, *size);
570 if (tmp)
571 image = tmp;
574 if (kernel_gfd != NULL)
575 gzclose(kernel_gfd);
576 else if (kernel_fd >= 0)
577 close(kernel_fd);
578 return image;
580 out_1:
581 return NULL;
585 * Local variables:
586 * mode: C
587 * c-set-style: "BSD"
588 * c-basic-offset: 4
589 * tab-width: 4
590 * indent-tabs-mode: nil
591 * End: