xref: /illumos-kvm-cmd/target-ia64/firmware.c (revision 68396ea9)
1 /*
2  * firmware.c : Firmware build logic for ia64 platform.
3  *
4  * Ported from Xen 3.0 Source.
5  * Copyright (c) 2007, Intel Corporation.
6  * Zhang Xiantao <xiantao.zhang@intel.com>
7  *
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.
11  *
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.
16  *
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.
20  */
21 
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>
29 
30 #include "cpu.h"
31 
32 #include "firmware.h"
33 
34 #include "qemu-common.h"
35 
36 typedef struct {
37     unsigned long signature;
38     unsigned int  type;
39     unsigned int  length;
40 } HOB_GENERIC_HEADER;
41 
42 /*
43  * INFO HOB is the first data data in one HOB list
44  * it contains the control information of the HOB list
45  */
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;
52 
53 typedef struct{
54     unsigned long start;
55     unsigned long size;
56 } hob_mem_t;
57 
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;
85 
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, unsigned long dom_mem_size);
95 
96 int
kvm_ia64_build_hob(unsigned long memsize,unsigned long vcpus,unsigned long nvram_addr)97 kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus,
98                    unsigned long nvram_addr)
99 {
100     char   *hob_buf;
101 
102     hob_buf = malloc(GFW_HOB_SIZE);
103     if (hob_buf == NULL) {
104         Hob_Output("Hob: Could not allocate hob");
105         return -1;
106     }
107 
108     if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) {
109         free(hob_buf);
110         Hob_Output("Could not build hob");
111         return -1;
112     }
113 
114     if (load_hob(hob_buf, memsize) < 0) {
115         free(hob_buf);
116         Hob_Output("Could not load hob");
117         return -1;
118     }
119     free(hob_buf);
120 
121     return 0;
122 }
123 
124 static int
hob_init(void * buffer,unsigned long buf_size)125 hob_init(void *buffer, unsigned long buf_size)
126 {
127     HOB_INFO *phit;
128     HOB_GENERIC_HEADER *terminal;
129 
130     if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
131         // buffer too small
132         return -1;
133     }
134 
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;
142 
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);
147 
148     return 0;
149 }
150 
151 /*
152  *  Add a new HOB to the HOB List.
153  *
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
158  */
159 static int
hob_add(void * hob_start,int type,void * data,int data_size)160 hob_add(void* hob_start, int type, void* data, int data_size)
161 {
162     HOB_INFO *phit;
163     HOB_GENERIC_HEADER *newhob, *tail;
164 
165     phit = (HOB_INFO*)hob_start;
166 
167     if (phit->length + data_size > phit->buf_size) {
168         // no space for new hob
169         return -1;
170     }
171 
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);
179 
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);
185 
186     // adjust HOB list length
187     phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
188 
189     return 0;
190 }
191 
192 static int
get_hob_size(void * hob_buf)193 get_hob_size(void* hob_buf)
194 {
195     HOB_INFO *phit = (HOB_INFO*)hob_buf;
196 
197     if (phit->header.signature != HOB_SIGNATURE) {
198         Hob_Output("xc_get_hob_size:Incorrect signature");
199         return -1;
200     }
201     return phit->length;
202 }
203 
204 static  int
add_max_hob_entry(void * hob_buf)205 add_max_hob_entry(void* hob_buf)
206 {
207     long max_hob = 0;
208     return hob_add(hob_buf, HOB_TYPE_MAX, &max_hob, sizeof(long));
209 }
210 
211 static int
build_hob(void * hob_buf,unsigned long hob_buf_size,unsigned long dom_mem_size,unsigned long vcpus,unsigned long nvram_addr)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)
215 {
216     //Init HOB List
217     if (hob_init(hob_buf, hob_buf_size) < 0) {
218         Hob_Output("buffer too small");
219         goto err_out;
220     }
221 
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;
225     }
226 
227     if (add_vcpus_hob(hob_buf, vcpus) < 0) {
228         Hob_Output("Add NR_VCPU hob failed, buffer too small");
229         goto err_out;
230     }
231 
232     if (add_pal_hob(hob_buf) < 0) {
233         Hob_Output("Add PAL hob failed, buffer too small");
234         goto err_out;
235     }
236 
237     if (add_nvram_hob(hob_buf, nvram_addr) < 0) {
238 	    Hob_Output("Add nvram hob failed, buffer too small");
239 	    goto err_out;
240 	}
241 
242     if (add_max_hob_entry(hob_buf) < 0) {
243         Hob_Output("Add max hob entry failed, buffer too small");
244         goto err_out;
245     }
246     return 0;
247 
248 err_out:
249     return -1;
250 }
251 static int
load_hob(void * hob_buf,unsigned long dom_mem_size)252 load_hob(void *hob_buf, unsigned long dom_mem_size)
253 {
254     int hob_size;
255 
256     hob_size = get_hob_size(hob_buf);
257     if (hob_size < 0) {
258         Hob_Output("Invalid hob data");
259         return -1;
260     }
261 
262     if (hob_size > GFW_HOB_SIZE) {
263         Hob_Output("No enough memory for hob data");
264         return -1;
265     }
266 
267     cpu_physical_memory_write(GFW_HOB_START, hob_buf, hob_size);
268 
269     return 0;
270 }
271 
272 static int
add_mem_hob(void * hob_buf,unsigned long dom_mem_size)273 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
274 {
275     hob_mem_t memhob;
276 
277     // less than 3G
278     memhob.start = 0;
279     memhob.size = MIN(dom_mem_size, 0xC0000000);
280 
281     if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
282         return -1;
283 
284     if (dom_mem_size > 0xC0000000) {
285         // 4G ~ 4G+remain
286         memhob.start = 0x100000000; //4G
287         memhob.size = dom_mem_size - 0xC0000000;
288         if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
289             return -1;
290     }
291     return 0;
292 }
293 
294 static int
add_vcpus_hob(void * hob_buf,unsigned long vcpus)295 add_vcpus_hob(void* hob_buf, unsigned long vcpus)
296 {
297     return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
298 }
299 
300 static int
add_nvram_hob(void * hob_buf,unsigned long nvram_addr)301 add_nvram_hob(void *hob_buf, unsigned long nvram_addr)
302 {
303     return hob_add(hob_buf, HOB_TYPE_NR_NVRAM,
304                    &nvram_addr, sizeof(nvram_addr));
305 }
306 
307 static const unsigned char config_pal_bus_get_features_data[24] = {
308     0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
309     0, 0, 0, 0, 0, 0, 0, 0, 0, 0
310 };
311 
312 static const unsigned char config_pal_cache_summary[16] = {
313     3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
314 };
315 
316 static const unsigned char config_pal_mem_attrib[8] = {
317     241, 0, 0, 0, 0, 0, 0, 0
318 };
319 
320 static const unsigned char config_pal_cache_info[152] = {
321     3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
322     6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
323     49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
324     0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
325     0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
326     12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
327     7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
328     255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
329     11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
330     0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
331 };
332 
333 static const unsigned char config_pal_cache_prot_info[200] = {
334     3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335     45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
336     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
337     8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
338     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
339     0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
341     112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342     0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
343     32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
344     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
345     12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346     0, 0, 0
347 };
348 
349 static const unsigned char config_pal_debug_info[16] = {
350     2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
351 };
352 
353 static const unsigned char config_pal_fixed_addr[8] = {
354     0, 0, 0, 0, 0, 0, 0, 0
355 };
356 
357 static const unsigned char config_pal_freq_base[8] = {
358     109, 219, 182, 13, 0, 0, 0, 0
359 };
360 
361 static const unsigned char config_pal_freq_ratios[24] = {
362     11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
363     0, 0, 0, 7, 0, 0, 0
364 };
365 
366 static const unsigned char config_pal_halt_info[64] = {
367     0, 0, 0, 0, 0, 0, 0, 48, 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,
369     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
371 };
372 
373 static const unsigned char config_pal_perf_mon_info[136] = {
374     12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
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, 241, 255, 0, 0, 223, 0, 255, 255,
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, 240, 255, 0, 0, 0, 0, 0, 0,
381     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
382     0, 0, 0, 0, 0, 0, 0, 0
383 };
384 
385 static const unsigned char config_pal_proc_get_features[104] = {
386     3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
387     0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
388     0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
389     231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
390     0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
391     63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
392     0, 0, 0, 0, 0, 0, 0, 0
393 };
394 
395 static const unsigned char config_pal_ptce_info[24] = {
396     0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
397     0, 0, 0, 0, 0, 0, 0, 0
398 };
399 
400 static const unsigned char config_pal_register_info[64] = {
401     255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
402     255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
403     251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
404     252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
405 };
406 
407 static const unsigned char config_pal_rse_info[16] = {
408     96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
409 };
410 
411 static const unsigned char config_pal_test_info[48] = {
412     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
413     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
414     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
415 };
416 
417 static const unsigned char config_pal_vm_summary[16] = {
418     101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
419 };
420 
421 static const unsigned char config_pal_vm_info[104] = {
422     2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
423     32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
424     0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
425     21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
426     4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
427     0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
428 };
429 
430 static const unsigned char config_pal_vm_page_size[16] = {
431     0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
432 };
433 
434 typedef struct{
435     hob_type_t type;
436     void* data;
437     unsigned long size;
438 } hob_batch_t;
439 
440 static const hob_batch_t hob_batch[]={
441     {   HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
442         &config_pal_bus_get_features_data,
443         sizeof(config_pal_bus_get_features_data)
444     },
445     {   HOB_TYPE_PAL_CACHE_SUMMARY,
446         &config_pal_cache_summary,
447         sizeof(config_pal_cache_summary)
448     },
449     {   HOB_TYPE_PAL_MEM_ATTRIB,
450         &config_pal_mem_attrib,
451         sizeof(config_pal_mem_attrib)
452     },
453     {   HOB_TYPE_PAL_CACHE_INFO,
454         &config_pal_cache_info,
455         sizeof(config_pal_cache_info)
456     },
457     {   HOB_TYPE_PAL_CACHE_PROT_INFO,
458         &config_pal_cache_prot_info,
459         sizeof(config_pal_cache_prot_info)
460     },
461     {   HOB_TYPE_PAL_DEBUG_INFO,
462         &config_pal_debug_info,
463         sizeof(config_pal_debug_info)
464     },
465     {   HOB_TYPE_PAL_FIXED_ADDR,
466         &config_pal_fixed_addr,
467         sizeof(config_pal_fixed_addr)
468     },
469     {   HOB_TYPE_PAL_FREQ_BASE,
470         &config_pal_freq_base,
471         sizeof(config_pal_freq_base)
472     },
473     {   HOB_TYPE_PAL_FREQ_RATIOS,
474         &config_pal_freq_ratios,
475         sizeof(config_pal_freq_ratios)
476     },
477     {   HOB_TYPE_PAL_HALT_INFO,
478         &config_pal_halt_info,
479         sizeof(config_pal_halt_info)
480     },
481     {   HOB_TYPE_PAL_PERF_MON_INFO,
482         &config_pal_perf_mon_info,
483         sizeof(config_pal_perf_mon_info)
484     },
485     {   HOB_TYPE_PAL_PROC_GET_FEATURES,
486         &config_pal_proc_get_features,
487         sizeof(config_pal_proc_get_features)
488     },
489     {   HOB_TYPE_PAL_PTCE_INFO,
490         &config_pal_ptce_info,
491         sizeof(config_pal_ptce_info)
492     },
493     {   HOB_TYPE_PAL_REGISTER_INFO,
494         &config_pal_register_info,
495         sizeof(config_pal_register_info)
496     },
497     {   HOB_TYPE_PAL_RSE_INFO,
498         &config_pal_rse_info,
499         sizeof(config_pal_rse_info)
500     },
501     {   HOB_TYPE_PAL_TEST_INFO,
502         &config_pal_test_info,
503         sizeof(config_pal_test_info)
504     },
505     {   HOB_TYPE_PAL_VM_SUMMARY,
506         &config_pal_vm_summary,
507         sizeof(config_pal_vm_summary)
508     },
509     {   HOB_TYPE_PAL_VM_INFO,
510         &config_pal_vm_info,
511         sizeof(config_pal_vm_info)
512     },
513     {   HOB_TYPE_PAL_VM_PAGE_SIZE,
514         &config_pal_vm_page_size,
515         sizeof(config_pal_vm_page_size)
516     },
517 };
518 
519 static int
add_pal_hob(void * hob_buf)520 add_pal_hob(void* hob_buf)
521 {
522     int i;
523     for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) {
524         if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data,
525                     hob_batch[i].size) < 0)
526             return -1;
527     }
528     return 0;
529 }
530 
read_image(const char * filename,unsigned long * size)531 uint8_t *read_image(const char *filename, unsigned long *size)
532 {
533     int kernel_fd = -1;
534     gzFile kernel_gfd = NULL;
535     uint8_t *image = NULL, *tmp;
536     unsigned int bytes;
537 
538     if ((filename == NULL) || (size == NULL))
539         return NULL;
540 
541     kernel_fd = open(filename, O_RDONLY);
542     if (kernel_fd < 0) {
543         Hob_Output("Could not open kernel image\n");
544         goto out_1;
545     }
546 
547     if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
548         Hob_Output("Could not allocate decompression state for state file\n");
549         goto out_1;
550     }
551 
552     *size = 0;
553 
554 #define CHUNK 1*1024*1024
555     while(1)
556     {
557         if ((tmp = realloc(image, *size + CHUNK)) == NULL) {
558             Hob_Output("Could not allocate memory for kernel image");
559             free(image);
560             image = NULL;
561             goto out;
562         }
563         image = tmp;
564 
565         bytes = gzread(kernel_gfd, image + *size, CHUNK);
566         switch (bytes) {
567         case -1:
568             Hob_Output("Error reading kernel image");
569             free(image);
570             image = NULL;
571             goto out;
572         case 0: /* EOF */
573             goto out;
574         default:
575             *size += bytes;
576             break;
577         }
578     }
579 #undef CHUNK
580 
581 out:
582     if (*size == 0) {
583         Hob_Output("Could not read kernel image");
584         free(image);
585         image = NULL;
586     } else if (image) {
587         /* Shrink allocation to fit image. */
588         tmp = realloc(image, *size);
589         if (tmp)
590             image = tmp;
591     }
592 
593     if (kernel_gfd != NULL)
594         gzclose(kernel_gfd);
595     else if (kernel_fd >= 0)
596         close(kernel_fd);
597     return image;
598 
599 out_1:
600     return NULL;
601 }
602 
kvm_ia64_nvram_init(unsigned long type)603 int kvm_ia64_nvram_init(unsigned long type)
604 {
605     unsigned long nvram_fd;
606     char nvram_path[PATH_MAX];
607     unsigned long i;
608 
609     if (nvram) {
610         if (strlen(nvram) > PATH_MAX) {
611             goto out;
612         }
613         if (type == READ_FROM_NVRAM) {
614             if (access(nvram, R_OK | W_OK | X_OK) == -1)
615                 goto out;
616             nvram_fd = open(nvram, O_RDONLY);
617             return nvram_fd;
618         }
619         else { /* write from gfw to nvram file */
620             i = access(nvram, R_OK | W_OK | X_OK);
621             if ((i == -1) && (errno != ENOENT))
622                goto out;
623             nvram_fd = open(nvram, O_CREAT|O_RDWR, 0777);
624             return nvram_fd;
625         }
626     }
627     else {
628         strcpy(nvram_path, "nvram.dat");
629         if (type == READ_FROM_NVRAM) {
630             if (access(nvram_path, R_OK | W_OK | X_OK) == -1)
631                 goto out;
632             nvram_fd = open(nvram_path, O_RDONLY);
633             return nvram_fd;
634         }
635         else { /* write from gfw to nvram file */
636             i = access(nvram_path, R_OK | W_OK | X_OK);
637             if ((i == -1) && (errno != ENOENT))
638                goto out;
639             nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0777);
640             return nvram_fd;
641         }
642     }
643 out:
644     return -1;
645 }
646 
647 int
kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd)648 kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd)
649 {
650     struct stat file_stat;
651     uint8_t *nvram_buf;
652     int r = 0;
653 
654     nvram_buf = malloc(NVRAM_SIZE);
655 
656     if ((fstat(nvram_fd, &file_stat) < 0) ||
657         (NVRAM_SIZE  != file_stat.st_size) ||
658         (read(nvram_fd, nvram_buf, NVRAM_SIZE) != NVRAM_SIZE)) {
659         r = -1;
660         goto out;
661     }
662 
663     cpu_physical_memory_write(NVRAM_START, nvram_buf, NVRAM_SIZE);
664 
665  out:
666     free(nvram_buf);
667     return r;
668 }
669 
670 int
kvm_ia64_copy_from_GFW_to_nvram()671 kvm_ia64_copy_from_GFW_to_nvram()
672 {
673     struct nvram_save_addr nvram_addr_buf;
674     uint8_t *nvram_buf;
675     unsigned long nvram_fd;
676     unsigned long type = WRITE_TO_NVRAM;
677     int ret = -1;
678 
679     nvram_buf = malloc(NVRAM_SIZE);
680     if (!nvram_buf)
681         goto out_free;
682 
683     cpu_physical_memory_read(NVRAM_START, (uint8_t *)&nvram_addr_buf,
684                              sizeof(struct nvram_save_addr));
685     if (nvram_addr_buf.signature != NVRAM_VALID_SIG) {
686         goto out_free;
687     }
688 
689     cpu_physical_memory_read(nvram_addr_buf.addr, nvram_buf, NVRAM_SIZE);
690 
691     nvram_fd = kvm_ia64_nvram_init(type);
692     if (nvram_fd  == -1)
693         goto out;
694 
695     lseek(nvram_fd, 0, SEEK_SET);
696     if (write(nvram_fd, nvram_buf, NVRAM_SIZE) != NVRAM_SIZE)
697         goto out;
698 
699     ret = 0;
700  out:
701     close(nvram_fd);
702  out_free:
703     free(nvram_buf);
704     return ret;
705 }
706 
707 /*
708  * Local variables:
709  * mode: C
710  * c-set-style: "BSD"
711  * c-basic-offset: 4
712  * tab-width: 4
713  * indent-tabs-mode: nil
714  * End:
715  */
716