kvm: qemu: fix pci_enable_capabilities to set the CAP feature in pci::status
[kvm-userspace.git] / qemu / target-ia64 / firmware.c
blob87a817881794974b412d1536af0dc65ed17e78dd
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 #include "qemu-common.h"
36 typedef struct {
37 unsigned long signature;
38 unsigned int type;
39 unsigned int length;
40 } HOB_GENERIC_HEADER;
43 * INFO HOB is the first data data in one HOB list
44 * it contains the control information of the HOB list
46 typedef struct {
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
51 } HOB_INFO;
53 typedef struct{
54 unsigned long start;
55 unsigned long size;
56 } hob_mem_t;
58 typedef enum {
59 HOB_TYPE_INFO=0,
60 HOB_TYPE_TERMINAL,
61 HOB_TYPE_MEM,
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,
79 HOB_TYPE_PAL_VM_INFO,
80 HOB_TYPE_PAL_VM_PAGE_SIZE,
81 HOB_TYPE_NR_VCPU,
82 HOB_TYPE_NR_NVRAM,
83 HOB_TYPE_MAX
84 } hob_type_t;
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);
97 int
98 kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus,
99 uint8_t *fw_start, unsigned long nvram_addr)
101 char *hob_buf;
103 hob_buf = malloc(GFW_HOB_SIZE);
104 if (hob_buf == NULL) {
105 Hob_Output("Hob: Could not allocate hob");
106 return -1;
109 if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) {
110 free(hob_buf);
111 Hob_Output("Could not build hob");
112 return -1;
114 if (load_hob(hob_buf, memsize, fw_start + HOB_OFFSET) < 0) {
115 free(hob_buf);
116 Hob_Output("Could not load hob");
117 return -1;
119 free(hob_buf);
121 return 0;
124 static int
125 hob_init(void *buffer, unsigned long buf_size)
127 HOB_INFO *phit;
128 HOB_GENERIC_HEADER *terminal;
130 if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
131 // buffer too small
132 return -1;
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);
140 phit->cur_pos = 0;
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);
148 return 0;
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
159 static int
160 hob_add(void* hob_start, int type, void* data, int data_size)
162 HOB_INFO *phit;
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
169 return -1;
172 //append new HOB
173 newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
174 sizeof(HOB_GENERIC_HEADER));
175 newhob->signature = HOB_SIGNATURE;
176 newhob->type = type;
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;
189 return 0;
192 static int
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");
199 return -1;
201 return phit->length;
204 static int
205 add_max_hob_entry(void* hob_buf)
207 long max_hob = 0;
208 return hob_add(hob_buf, HOB_TYPE_MAX, &max_hob, sizeof(long));
211 static int
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)
216 //Init HOB List
217 if (hob_init(hob_buf, hob_buf_size) < 0) {
218 Hob_Output("buffer too small");
219 goto err_out;
222 if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
223 Hob_Output("Add memory hob failed, buffer too small");
224 goto err_out;
227 if (add_vcpus_hob(hob_buf, vcpus) < 0) {
228 Hob_Output("Add NR_VCPU hob failed, buffer too small");
229 goto err_out;
232 if (add_pal_hob(hob_buf) < 0) {
233 Hob_Output("Add PAL hob failed, buffer too small");
234 goto err_out;
237 if (add_nvram_hob(hob_buf, nvram_addr) < 0) {
238 Hob_Output("Add nvram hob failed, buffer too small");
239 goto err_out;
242 if (add_max_hob_entry(hob_buf) < 0) {
243 Hob_Output("Add max hob entry failed, buffer too small");
244 goto err_out;
246 return 0;
248 err_out:
249 return -1;
251 static int
252 load_hob(void *hob_buf, unsigned long dom_mem_size, void* hob_start)
254 int hob_size;
256 hob_size = get_hob_size(hob_buf);
257 if (hob_size < 0) {
258 Hob_Output("Invalid hob data");
259 return -1;
262 if (hob_size > GFW_HOB_SIZE) {
263 Hob_Output("No enough memory for hob data");
264 return -1;
266 memcpy (hob_start, hob_buf, hob_size);
267 return 0;
270 static int
271 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
273 hob_mem_t memhob;
275 // less than 3G
276 memhob.start = 0;
277 memhob.size = MIN(dom_mem_size, 0xC0000000);
279 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
280 return -1;
282 if (dom_mem_size > 0xC0000000) {
283 // 4G ~ 4G+remain
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)
287 return -1;
289 return 0;
292 static int
293 add_vcpus_hob(void* hob_buf, unsigned long vcpus)
295 return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
298 static int
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,
344 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,
361 0, 0, 0, 7, 0, 0, 0
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
432 typedef struct{
433 hob_type_t type;
434 void* data;
435 unsigned long size;
436 } hob_batch_t;
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,
508 &config_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)
517 static int
518 add_pal_hob(void* hob_buf)
520 int i;
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)
524 return -1;
526 return 0;
529 char *read_image(const char *filename, unsigned long *size)
531 int kernel_fd = -1;
532 gzFile kernel_gfd = NULL;
533 char *image = NULL, *tmp;
534 unsigned int bytes;
536 if ((filename == NULL) || (size == NULL))
537 return NULL;
539 kernel_fd = open(filename, O_RDONLY);
540 if (kernel_fd < 0) {
541 Hob_Output("Could not open kernel image\n");
542 goto out_1;
545 if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
546 Hob_Output("Could not allocate decompression state for state file\n");
547 goto out_1;
550 *size = 0;
552 #define CHUNK 1*1024*1024
553 while(1)
555 if ((tmp = realloc(image, *size + CHUNK)) == NULL) {
556 Hob_Output("Could not allocate memory for kernel image");
557 free(image);
558 image = NULL;
559 goto out;
561 image = tmp;
563 bytes = gzread(kernel_gfd, image + *size, CHUNK);
564 switch (bytes) {
565 case -1:
566 Hob_Output("Error reading kernel image");
567 free(image);
568 image = NULL;
569 goto out;
570 case 0: /* EOF */
571 goto out;
572 default:
573 *size += bytes;
574 break;
577 #undef CHUNK
579 out:
580 if (*size == 0) {
581 Hob_Output("Could not read kernel image");
582 free(image);
583 image = NULL;
584 } else if (image) {
585 /* Shrink allocation to fit image. */
586 tmp = realloc(image, *size);
587 if (tmp)
588 image = tmp;
591 if (kernel_gfd != NULL)
592 gzclose(kernel_gfd);
593 else if (kernel_fd >= 0)
594 close(kernel_fd);
595 return image;
597 out_1:
598 return NULL;
601 int kvm_ia64_nvram_init(unsigned long type)
603 unsigned long nvram_fd;
604 char nvram_path[PATH_MAX];
605 unsigned long i;
607 if (nvram) {
608 if (strlen(nvram) > PATH_MAX) {
609 goto out;
611 if (type == READ_FROM_NVRAM) {
612 if (access(nvram, R_OK | W_OK | X_OK) == -1)
613 goto out;
614 nvram_fd = open(nvram, O_RDONLY);
615 return nvram_fd;
617 else { /* write from gfw to nvram file */
618 i = access(nvram, R_OK | W_OK | X_OK);
619 if ((i == -1) && (errno != ENOENT))
620 goto out;
621 nvram_fd = open(nvram, O_CREAT|O_RDWR, 0777);
622 return nvram_fd;
625 else {
626 strcpy(nvram_path, "nvram.dat");
627 if (type == READ_FROM_NVRAM) {
628 if (access(nvram_path, R_OK | W_OK | X_OK) == -1)
629 goto out;
630 nvram_fd = open(nvram_path, O_RDONLY);
631 return nvram_fd;
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))
636 goto out;
637 nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0777);
638 return nvram_fd;
641 out:
642 return -1;
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))
654 return -1;
655 return 0;
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);
665 if (nvram_fd == -1)
666 goto out;
667 if (((struct nvram_save_addr *)nvram_addr)->signature != NVRAM_VALID_SIG) {
668 close(nvram_fd);
669 goto out;
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) {
674 close(nvram_fd);
675 goto out;
677 close(nvram_fd);
678 return 0;
679 out:
680 return -1;
684 * Local variables:
685 * mode: C
686 * c-set-style: "BSD"
687 * c-basic-offset: 4
688 * tab-width: 4
689 * indent-tabs-mode: nil
690 * End: