Merge "Adding breaktrace & disabling timer migration"
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / xcoff_load.c
1 /*
2  *
3  *       <xcoff_load.c>
4  *
5  *       XCOFF file loader
6  *
7  *   Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
8  *
9  *   from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
10  *
11  *   This program is free software; you can redistribute it and/or
12  *   modify it under the terms of the GNU General Public License
13  *   version 2
14  *
15  */
16
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/xcoff_load.h"
20
21 #include "arch/common/xcoff.h"
22
23 #ifdef CONFIG_PPC
24 extern void             flush_icache_range( char *start, char *stop );
25 #endif
26
27 //#define DEBUG_XCOFF
28
29 #ifdef DEBUG_XCOFF
30 #define DPRINTF(fmt, args...) \
31     do { printk("%s: " fmt, __func__ , ##args); } while (0)
32 #else
33 #define DPRINTF(fmt, args...) \
34     do { } while (0)
35 #endif
36
37 int 
38 is_xcoff(COFF_filehdr_t *fhdr)
39 {
40         return (fhdr->f_magic == U802WRMAGIC
41             || fhdr->f_magic == U802ROMAGIC
42             || fhdr->f_magic == U802TOCMAGIC
43             || fhdr->f_magic == U802TOMAGIC);
44 }
45
46 int 
47 xcoff_load(struct sys_info *info, const char *filename)
48 {
49         // Currently not implemented
50         return LOADER_NOT_SUPPORT;
51 }
52
53 void
54 xcoff_init_program(void)
55 {
56         char *base;
57         COFF_filehdr_t *fhdr;
58         COFF_aouthdr_t *ahdr;
59         COFF_scnhdr_t *shdr;
60         uint32_t offset;
61         size_t total_size = 0;
62         int i;
63
64         feval("0 state-valid !");
65
66         feval("load-base");
67         base = (char*)cell2pointer(POP());
68
69         fhdr = (COFF_filehdr_t*)base;
70
71         /* Is it an XCOFF file ? */
72         if (!is_xcoff(fhdr)) {
73                 DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic);
74                 return;
75         }
76
77         /* Is it executable ? */
78         if (fhdr->f_magic != 0x01DF &&
79             (fhdr->f_flags & COFF_F_EXEC) == 0) {
80                 DPRINTF("Not an executable XCOFF file %02x\n", fhdr->f_flags);
81                 return;
82         }
83
84         /* Optional header is a.out ? */
85         if (fhdr->f_opthdr != sizeof(COFF_aouthdr_t)) {
86                 DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
87                 return;
88         }
89
90         ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t));
91
92         /* check a.out magic number */
93         if (ahdr->magic != AOUT_MAGIC) {
94                 DPRINTF("Invalid AOUT optional header\n");
95                 return;
96         }
97
98         offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
99
100         DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns);
101
102         for (i = 0; i < fhdr->f_nscns; i++) {
103
104                 DPRINTF("Read header at offset %0x\n", offset);
105
106                 shdr = (COFF_scnhdr_t*)(base + offset);
107
108                 DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n",
109                         shdr->s_name, offset, shdr->s_scnptr,
110                         shdr->s_vaddr, shdr->s_size);
111
112                 if (strcmp(shdr->s_name, ".text") == 0) {
113
114                         memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
115                                shdr->s_size);
116                         total_size += shdr->s_size;
117 #ifdef CONFIG_PPC
118                         flush_icache_range((char*)(uintptr_t)shdr->s_vaddr,
119                                          (char*)(uintptr_t)(shdr->s_vaddr + shdr->s_size));
120 #endif
121                 } else if (strcmp(shdr->s_name, ".data") == 0) {
122
123                         memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
124                                shdr->s_size);
125                         total_size += shdr->s_size;
126
127                 } else if (strcmp(shdr->s_name, ".bss") == 0) {
128
129                         memset((void *)(uintptr_t)shdr->s_vaddr, 0, shdr->s_size);
130                         total_size += shdr->s_size;
131                 } else {
132                         DPRINTF("    Skip '%s' section\n", shdr->s_name);
133                 }
134                 offset += sizeof(COFF_scnhdr_t);
135         }
136
137         DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry);
138
139         // Initialise saved-program-state
140         PUSH(*(uint32_t*)(uintptr_t)ahdr->entry);
141         feval("saved-program-state >sps.entry !");
142         PUSH(total_size);
143         feval("saved-program-state >sps.file-size !");
144         feval("xcoff saved-program-state >sps.file-type !");
145
146         feval("-1 state-valid !");
147 }