blob: 79f846421764fa56661e4f98f6a63a60f4eefdf8 [file] [log] [blame]
/*
* firmware.c : Firmware build logic for ia64 platform.
*
* Ported from Xen 3.0 Source.
* Copyright (c) 2007, Intel Corporation.
* Zhang Xiantao <xiantao.zhang@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cpu.h"
#include "firmware.h"
#include "qemu-common.h"
typedef struct {
unsigned long signature;
unsigned int type;
unsigned int length;
} HOB_GENERIC_HEADER;
/*
* INFO HOB is the first data data in one HOB list
* it contains the control information of the HOB list
*/
typedef struct {
HOB_GENERIC_HEADER header;
unsigned long length; // current length of hob
unsigned long cur_pos; // current poisiton of hob
unsigned long buf_size; // size of hob buffer
} HOB_INFO;
typedef struct{
unsigned long start;
unsigned long size;
} hob_mem_t;
typedef enum {
HOB_TYPE_INFO=0,
HOB_TYPE_TERMINAL,
HOB_TYPE_MEM,
HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
HOB_TYPE_PAL_CACHE_SUMMARY,
HOB_TYPE_PAL_MEM_ATTRIB,
HOB_TYPE_PAL_CACHE_INFO,
HOB_TYPE_PAL_CACHE_PROT_INFO,
HOB_TYPE_PAL_DEBUG_INFO,
HOB_TYPE_PAL_FIXED_ADDR,
HOB_TYPE_PAL_FREQ_BASE,
HOB_TYPE_PAL_FREQ_RATIOS,
HOB_TYPE_PAL_HALT_INFO,
HOB_TYPE_PAL_PERF_MON_INFO,
HOB_TYPE_PAL_PROC_GET_FEATURES,
HOB_TYPE_PAL_PTCE_INFO,
HOB_TYPE_PAL_REGISTER_INFO,
HOB_TYPE_PAL_RSE_INFO,
HOB_TYPE_PAL_TEST_INFO,
HOB_TYPE_PAL_VM_SUMMARY,
HOB_TYPE_PAL_VM_INFO,
HOB_TYPE_PAL_VM_PAGE_SIZE,
HOB_TYPE_NR_VCPU,
HOB_TYPE_NR_NVRAM,
HOB_TYPE_MAX
} hob_type_t;
static int hob_init(void *buffer ,unsigned long buf_size);
static int add_pal_hob(void* hob_buf);
static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
static int add_nvram_hob(void *hob_buf, unsigned long nvram_addr);
static int build_hob(void *hob_buf, unsigned long hob_buf_size,
unsigned long dom_mem_size, unsigned long vcpus,
unsigned long nvram_addr);
static int load_hob(void *hob_buf, unsigned long dom_mem_size);
int
kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus,
unsigned long nvram_addr)
{
char *hob_buf;
hob_buf = malloc(GFW_HOB_SIZE);
if (hob_buf == NULL) {
Hob_Output("Hob: Could not allocate hob");
return -1;
}
if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) {
free(hob_buf);
Hob_Output("Could not build hob");
return -1;
}
if (load_hob(hob_buf, memsize) < 0) {
free(hob_buf);
Hob_Output("Could not load hob");
return -1;
}
free(hob_buf);
return 0;
}
static int
hob_init(void *buffer, unsigned long buf_size)
{
HOB_INFO *phit;
HOB_GENERIC_HEADER *terminal;
if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
// buffer too small
return -1;
}
phit = (HOB_INFO*)buffer;
phit->header.signature = HOB_SIGNATURE;
phit->header.type = HOB_TYPE_INFO;
phit->header.length = sizeof(HOB_INFO);
phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
phit->cur_pos = 0;
phit->buf_size = buf_size;
terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO));
terminal->signature = HOB_SIGNATURE;
terminal->type = HOB_TYPE_TERMINAL;
terminal->length = sizeof(HOB_GENERIC_HEADER);
return 0;
}
/*
* Add a new HOB to the HOB List.
*
* hob_start - start address of hob buffer
* type - type of the hob to be added
* data - data of the hob to be added
* data_size - size of the data
*/
static int
hob_add(void* hob_start, int type, void* data, int data_size)
{
HOB_INFO *phit;
HOB_GENERIC_HEADER *newhob, *tail;
phit = (HOB_INFO*)hob_start;
if (phit->length + data_size > phit->buf_size) {
// no space for new hob
return -1;
}
//append new HOB
newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
sizeof(HOB_GENERIC_HEADER));
newhob->signature = HOB_SIGNATURE;
newhob->type = type;
newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
// append terminal HOB
tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size);
tail->signature = HOB_SIGNATURE;
tail->type = HOB_TYPE_TERMINAL;
tail->length = sizeof(HOB_GENERIC_HEADER);
// adjust HOB list length
phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
return 0;
}
static int
get_hob_size(void* hob_buf)
{
HOB_INFO *phit = (HOB_INFO*)hob_buf;
if (phit->header.signature != HOB_SIGNATURE) {
Hob_Output("xc_get_hob_size:Incorrect signature");
return -1;
}
return phit->length;
}
static int
add_max_hob_entry(void* hob_buf)
{
long max_hob = 0;
return hob_add(hob_buf, HOB_TYPE_MAX, &max_hob, sizeof(long));
}
static int
build_hob(void* hob_buf, unsigned long hob_buf_size,
unsigned long dom_mem_size, unsigned long vcpus,
unsigned long nvram_addr)
{
//Init HOB List
if (hob_init(hob_buf, hob_buf_size) < 0) {
Hob_Output("buffer too small");
goto err_out;
}
if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
Hob_Output("Add memory hob failed, buffer too small");
goto err_out;
}
if (add_vcpus_hob(hob_buf, vcpus) < 0) {
Hob_Output("Add NR_VCPU hob failed, buffer too small");
goto err_out;
}
if (add_pal_hob(hob_buf) < 0) {
Hob_Output("Add PAL hob failed, buffer too small");
goto err_out;
}
if (add_nvram_hob(hob_buf, nvram_addr) < 0) {
Hob_Output("Add nvram hob failed, buffer too small");
goto err_out;
}
if (add_max_hob_entry(hob_buf) < 0) {
Hob_Output("Add max hob entry failed, buffer too small");
goto err_out;
}
return 0;
err_out:
return -1;
}
static int
load_hob(void *hob_buf, unsigned long dom_mem_size)
{
int hob_size;
hob_size = get_hob_size(hob_buf);
if (hob_size < 0) {
Hob_Output("Invalid hob data");
return -1;
}
if (hob_size > GFW_HOB_SIZE) {
Hob_Output("No enough memory for hob data");
return -1;
}
cpu_physical_memory_write(GFW_HOB_START, hob_buf, hob_size);
return 0;
}
static int
add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
{
hob_mem_t memhob;
// less than 3G
memhob.start = 0;
memhob.size = MIN(dom_mem_size, 0xC0000000);
if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
return -1;
if (dom_mem_size > 0xC0000000) {
// 4G ~ 4G+remain
memhob.start = 0x100000000; //4G
memhob.size = dom_mem_size - 0xC0000000;
if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
return -1;
}
return 0;
}
static int
add_vcpus_hob(void* hob_buf, unsigned long vcpus)
{
return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
}
static int
add_nvram_hob(void *hob_buf, unsigned long nvram_addr)
{
return hob_add(hob_buf, HOB_TYPE_NR_NVRAM,
&nvram_addr, sizeof(nvram_addr));
}
static const unsigned char config_pal_bus_get_features_data[24] = {
0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_cache_summary[16] = {
3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_mem_attrib[8] = {
241, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_cache_info[152] = {
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
};
static const unsigned char config_pal_cache_prot_info[200] = {
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0
};
static const unsigned char config_pal_debug_info[16] = {
2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_fixed_addr[8] = {
0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_freq_base[8] = {
109, 219, 182, 13, 0, 0, 0, 0
};
static const unsigned char config_pal_freq_ratios[24] = {
11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
0, 0, 0, 7, 0, 0, 0
};
static const unsigned char config_pal_halt_info[64] = {
0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_perf_mon_info[136] = {
12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_proc_get_features[104] = {
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_ptce_info[24] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_register_info[64] = {
255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
};
static const unsigned char config_pal_rse_info[16] = {
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_test_info[48] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_vm_summary[16] = {
101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_vm_info[104] = {
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
};
static const unsigned char config_pal_vm_page_size[16] = {
0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
};
typedef struct{
hob_type_t type;
void* data;
unsigned long size;
} hob_batch_t;
static const hob_batch_t hob_batch[]={
{ HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
&config_pal_bus_get_features_data,
sizeof(config_pal_bus_get_features_data)
},
{ HOB_TYPE_PAL_CACHE_SUMMARY,
&config_pal_cache_summary,
sizeof(config_pal_cache_summary)
},
{ HOB_TYPE_PAL_MEM_ATTRIB,
&config_pal_mem_attrib,
sizeof(config_pal_mem_attrib)
},
{ HOB_TYPE_PAL_CACHE_INFO,
&config_pal_cache_info,
sizeof(config_pal_cache_info)
},
{ HOB_TYPE_PAL_CACHE_PROT_INFO,
&config_pal_cache_prot_info,
sizeof(config_pal_cache_prot_info)
},
{ HOB_TYPE_PAL_DEBUG_INFO,
&config_pal_debug_info,
sizeof(config_pal_debug_info)
},
{ HOB_TYPE_PAL_FIXED_ADDR,
&config_pal_fixed_addr,
sizeof(config_pal_fixed_addr)
},
{ HOB_TYPE_PAL_FREQ_BASE,
&config_pal_freq_base,
sizeof(config_pal_freq_base)
},
{ HOB_TYPE_PAL_FREQ_RATIOS,
&config_pal_freq_ratios,
sizeof(config_pal_freq_ratios)
},
{ HOB_TYPE_PAL_HALT_INFO,
&config_pal_halt_info,
sizeof(config_pal_halt_info)
},
{ HOB_TYPE_PAL_PERF_MON_INFO,
&config_pal_perf_mon_info,
sizeof(config_pal_perf_mon_info)
},
{ HOB_TYPE_PAL_PROC_GET_FEATURES,
&config_pal_proc_get_features,
sizeof(config_pal_proc_get_features)
},
{ HOB_TYPE_PAL_PTCE_INFO,
&config_pal_ptce_info,
sizeof(config_pal_ptce_info)
},
{ HOB_TYPE_PAL_REGISTER_INFO,
&config_pal_register_info,
sizeof(config_pal_register_info)
},
{ HOB_TYPE_PAL_RSE_INFO,
&config_pal_rse_info,
sizeof(config_pal_rse_info)
},
{ HOB_TYPE_PAL_TEST_INFO,
&config_pal_test_info,
sizeof(config_pal_test_info)
},
{ HOB_TYPE_PAL_VM_SUMMARY,
&config_pal_vm_summary,
sizeof(config_pal_vm_summary)
},
{ HOB_TYPE_PAL_VM_INFO,
&config_pal_vm_info,
sizeof(config_pal_vm_info)
},
{ HOB_TYPE_PAL_VM_PAGE_SIZE,
&config_pal_vm_page_size,
sizeof(config_pal_vm_page_size)
},
};
static int
add_pal_hob(void* hob_buf)
{
int i;
for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) {
if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data,
hob_batch[i].size) < 0)
return -1;
}
return 0;
}
uint8_t *read_image(const char *filename, unsigned long *size)
{
int kernel_fd = -1;
gzFile kernel_gfd = NULL;
uint8_t *image = NULL, *tmp;
unsigned int bytes;
if ((filename == NULL) || (size == NULL))
return NULL;
kernel_fd = open(filename, O_RDONLY);
if (kernel_fd < 0) {
Hob_Output("Could not open kernel image\n");
goto out_1;
}
if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
Hob_Output("Could not allocate decompression state for state file\n");
goto out_1;
}
*size = 0;
#define CHUNK 1*1024*1024
while(1)
{
if ((tmp = realloc(image, *size + CHUNK)) == NULL) {
Hob_Output("Could not allocate memory for kernel image");
free(image);
image = NULL;
goto out;
}
image = tmp;
bytes = gzread(kernel_gfd, image + *size, CHUNK);
switch (bytes) {
case -1:
Hob_Output("Error reading kernel image");
free(image);
image = NULL;
goto out;
case 0: /* EOF */
goto out;
default:
*size += bytes;
break;
}
}
#undef CHUNK
out:
if (*size == 0) {
Hob_Output("Could not read kernel image");
free(image);
image = NULL;
} else if (image) {
/* Shrink allocation to fit image. */
tmp = realloc(image, *size);
if (tmp)
image = tmp;
}
if (kernel_gfd != NULL)
gzclose(kernel_gfd);
else if (kernel_fd >= 0)
close(kernel_fd);
return image;
out_1:
return NULL;
}
int kvm_ia64_nvram_init(unsigned long type)
{
unsigned long nvram_fd;
char nvram_path[PATH_MAX];
unsigned long i;
if (nvram) {
if (strlen(nvram) > PATH_MAX) {
goto out;
}
if (type == READ_FROM_NVRAM) {
if (access(nvram, R_OK | W_OK | X_OK) == -1)
goto out;
nvram_fd = open(nvram, O_RDONLY);
return nvram_fd;
}
else { /* write from gfw to nvram file */
i = access(nvram, R_OK | W_OK | X_OK);
if ((i == -1) && (errno != ENOENT))
goto out;
nvram_fd = open(nvram, O_CREAT|O_RDWR, 0777);
return nvram_fd;
}
}
else {
strcpy(nvram_path, "nvram.dat");
if (type == READ_FROM_NVRAM) {
if (access(nvram_path, R_OK | W_OK | X_OK) == -1)
goto out;
nvram_fd = open(nvram_path, O_RDONLY);
return nvram_fd;
}
else { /* write from gfw to nvram file */
i = access(nvram_path, R_OK | W_OK | X_OK);
if ((i == -1) && (errno != ENOENT))
goto out;
nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0777);
return nvram_fd;
}
}
out:
return -1;
}
int
kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd)
{
struct stat file_stat;
uint8_t *nvram_buf;
int r = 0;
nvram_buf = malloc(NVRAM_SIZE);
if ((fstat(nvram_fd, &file_stat) < 0) ||
(NVRAM_SIZE != file_stat.st_size) ||
(read(nvram_fd, nvram_buf, NVRAM_SIZE) != NVRAM_SIZE)) {
r = -1;
goto out;
}
cpu_physical_memory_write(NVRAM_START, nvram_buf, NVRAM_SIZE);
out:
free(nvram_buf);
return r;
}
int
kvm_ia64_copy_from_GFW_to_nvram()
{
struct nvram_save_addr nvram_addr_buf;
uint8_t *nvram_buf;
unsigned long nvram_fd;
unsigned long type = WRITE_TO_NVRAM;
int ret = -1;
nvram_buf = malloc(NVRAM_SIZE);
if (!nvram_buf)
goto out_free;
cpu_physical_memory_read(NVRAM_START, (uint8_t *)&nvram_addr_buf,
sizeof(struct nvram_save_addr));
if (nvram_addr_buf.signature != NVRAM_VALID_SIG) {
goto out_free;
}
cpu_physical_memory_read(nvram_addr_buf.addr, nvram_buf, NVRAM_SIZE);
nvram_fd = kvm_ia64_nvram_init(type);
if (nvram_fd == -1)
goto out;
lseek(nvram_fd, 0, SEEK_SET);
if (write(nvram_fd, nvram_buf, NVRAM_SIZE) != NVRAM_SIZE)
goto out;
ret = 0;
out:
close(nvram_fd);
out_free:
free(nvram_buf);
return ret;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/