Statistics
| Branch: | Revision:

root / hw / ppc.c @ 50d3eeae

History | View | Annotate | Download (11.1 kB)

1 a541f297 bellard
/*
2 a541f297 bellard
 * QEMU generic PPC hardware System Emulator
3 a541f297 bellard
 * 
4 76a66253 j_mayer
 * Copyright (c) 2003-2007 Jocelyn Mayer
5 a541f297 bellard
 * 
6 a541f297 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 a541f297 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 a541f297 bellard
 * in the Software without restriction, including without limitation the rights
9 a541f297 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 a541f297 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 a541f297 bellard
 * furnished to do so, subject to the following conditions:
12 a541f297 bellard
 *
13 a541f297 bellard
 * The above copyright notice and this permission notice shall be included in
14 a541f297 bellard
 * all copies or substantial portions of the Software.
15 a541f297 bellard
 *
16 a541f297 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 a541f297 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 a541f297 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 a541f297 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 a541f297 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 a541f297 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 a541f297 bellard
 * THE SOFTWARE.
23 a541f297 bellard
 */
24 a541f297 bellard
#include "vl.h"
25 fd0bbb12 bellard
#include "m48t59.h"
26 a541f297 bellard
27 9fddaa0c bellard
/*****************************************************************************/
28 9fddaa0c bellard
/* PPC time base and decrementer emulation */
29 9fddaa0c bellard
//#define DEBUG_TB
30 9fddaa0c bellard
31 9fddaa0c bellard
struct ppc_tb_t {
32 9fddaa0c bellard
    /* Time base management */
33 9fddaa0c bellard
    int64_t  tb_offset;    /* Compensation               */
34 9fddaa0c bellard
    uint32_t tb_freq;      /* TB frequency               */
35 9fddaa0c bellard
    /* Decrementer management */
36 9fddaa0c bellard
    uint64_t decr_next;    /* Tick for next decr interrupt  */
37 9fddaa0c bellard
    struct QEMUTimer *decr_timer;
38 9fddaa0c bellard
};
39 9fddaa0c bellard
40 9fddaa0c bellard
static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
41 9fddaa0c bellard
{
42 9fddaa0c bellard
    /* TB time in tb periods */
43 9fddaa0c bellard
    return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
44 76a66253 j_mayer
                    tb_env->tb_freq, ticks_per_sec);
45 9fddaa0c bellard
}
46 9fddaa0c bellard
47 9fddaa0c bellard
uint32_t cpu_ppc_load_tbl (CPUState *env)
48 9fddaa0c bellard
{
49 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
50 9fddaa0c bellard
    uint64_t tb;
51 9fddaa0c bellard
52 9fddaa0c bellard
    tb = cpu_ppc_get_tb(tb_env);
53 9fddaa0c bellard
#ifdef DEBUG_TB
54 9fddaa0c bellard
    {
55 76a66253 j_mayer
        static int last_time;
56 76a66253 j_mayer
        int now;
57 76a66253 j_mayer
        now = time(NULL);
58 76a66253 j_mayer
        if (last_time != now) {
59 76a66253 j_mayer
            last_time = now;
60 76a66253 j_mayer
            printf("%s: tb=0x%016lx %d %08lx\n",
61 76a66253 j_mayer
                   __func__, tb, now, tb_env->tb_offset);
62 76a66253 j_mayer
        }
63 9fddaa0c bellard
    }
64 9fddaa0c bellard
#endif
65 9fddaa0c bellard
66 9fddaa0c bellard
    return tb & 0xFFFFFFFF;
67 9fddaa0c bellard
}
68 9fddaa0c bellard
69 9fddaa0c bellard
uint32_t cpu_ppc_load_tbu (CPUState *env)
70 9fddaa0c bellard
{
71 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
72 9fddaa0c bellard
    uint64_t tb;
73 9fddaa0c bellard
74 9fddaa0c bellard
    tb = cpu_ppc_get_tb(tb_env);
75 9fddaa0c bellard
#ifdef DEBUG_TB
76 9fddaa0c bellard
    printf("%s: tb=0x%016lx\n", __func__, tb);
77 9fddaa0c bellard
#endif
78 76a66253 j_mayer
79 9fddaa0c bellard
    return tb >> 32;
80 9fddaa0c bellard
}
81 9fddaa0c bellard
82 9fddaa0c bellard
static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
83 9fddaa0c bellard
{
84 9fddaa0c bellard
    tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
85 9fddaa0c bellard
        - qemu_get_clock(vm_clock);
86 9fddaa0c bellard
#ifdef DEBUG_TB
87 9fddaa0c bellard
    printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
88 9fddaa0c bellard
#endif
89 9fddaa0c bellard
}
90 9fddaa0c bellard
91 9fddaa0c bellard
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
92 9fddaa0c bellard
{
93 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
94 9fddaa0c bellard
95 9fddaa0c bellard
    cpu_ppc_store_tb(tb_env,
96 9fddaa0c bellard
                     ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
97 9fddaa0c bellard
}
98 9fddaa0c bellard
99 9fddaa0c bellard
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
100 9fddaa0c bellard
{
101 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
102 9fddaa0c bellard
103 9fddaa0c bellard
    cpu_ppc_store_tb(tb_env,
104 9fddaa0c bellard
                     ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
105 9fddaa0c bellard
}
106 9fddaa0c bellard
107 9fddaa0c bellard
uint32_t cpu_ppc_load_decr (CPUState *env)
108 9fddaa0c bellard
{
109 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
110 9fddaa0c bellard
    uint32_t decr;
111 4e588a4d bellard
    int64_t diff;
112 9fddaa0c bellard
113 4e588a4d bellard
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
114 4e588a4d bellard
    if (diff >= 0)
115 4e588a4d bellard
        decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
116 4e588a4d bellard
    else
117 4e588a4d bellard
        decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
118 fd0bbb12 bellard
#if defined(DEBUG_TB)
119 9fddaa0c bellard
    printf("%s: 0x%08x\n", __func__, decr);
120 9fddaa0c bellard
#endif
121 76a66253 j_mayer
122 9fddaa0c bellard
    return decr;
123 9fddaa0c bellard
}
124 9fddaa0c bellard
125 9fddaa0c bellard
/* When decrementer expires,
126 9fddaa0c bellard
 * all we need to do is generate or queue a CPU exception
127 9fddaa0c bellard
 */
128 9fddaa0c bellard
static inline void cpu_ppc_decr_excp (CPUState *env)
129 9fddaa0c bellard
{
130 9fddaa0c bellard
    /* Raise it */
131 9fddaa0c bellard
#ifdef DEBUG_TB
132 9fddaa0c bellard
    printf("raise decrementer exception\n");
133 9fddaa0c bellard
#endif
134 9fddaa0c bellard
    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
135 9fddaa0c bellard
}
136 9fddaa0c bellard
137 9fddaa0c bellard
static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
138 9fddaa0c bellard
                                 uint32_t value, int is_excp)
139 9fddaa0c bellard
{
140 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
141 9fddaa0c bellard
    uint64_t now, next;
142 9fddaa0c bellard
143 9fddaa0c bellard
#ifdef DEBUG_TB
144 9fddaa0c bellard
    printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
145 9fddaa0c bellard
#endif
146 9fddaa0c bellard
    now = qemu_get_clock(vm_clock);
147 9fddaa0c bellard
    next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
148 9fddaa0c bellard
    if (is_excp)
149 9fddaa0c bellard
        next += tb_env->decr_next - now;
150 9fddaa0c bellard
    if (next == now)
151 76a66253 j_mayer
        next++;
152 9fddaa0c bellard
    tb_env->decr_next = next;
153 9fddaa0c bellard
    /* Adjust timer */
154 9fddaa0c bellard
    qemu_mod_timer(tb_env->decr_timer, next);
155 9fddaa0c bellard
    /* If we set a negative value and the decrementer was positive,
156 9fddaa0c bellard
     * raise an exception.
157 9fddaa0c bellard
     */
158 9fddaa0c bellard
    if ((value & 0x80000000) && !(decr & 0x80000000))
159 76a66253 j_mayer
        cpu_ppc_decr_excp(env);
160 9fddaa0c bellard
}
161 9fddaa0c bellard
162 9fddaa0c bellard
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
163 9fddaa0c bellard
{
164 9fddaa0c bellard
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
165 9fddaa0c bellard
}
166 9fddaa0c bellard
167 9fddaa0c bellard
static void cpu_ppc_decr_cb (void *opaque)
168 9fddaa0c bellard
{
169 9fddaa0c bellard
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
170 9fddaa0c bellard
}
171 9fddaa0c bellard
172 9fddaa0c bellard
/* Set up (once) timebase frequency (in Hz) */
173 9fddaa0c bellard
ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
174 9fddaa0c bellard
{
175 9fddaa0c bellard
    ppc_tb_t *tb_env;
176 9fddaa0c bellard
177 9fddaa0c bellard
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
178 9fddaa0c bellard
    if (tb_env == NULL)
179 9fddaa0c bellard
        return NULL;
180 9fddaa0c bellard
    env->tb_env = tb_env;
181 9fddaa0c bellard
    if (tb_env->tb_freq == 0 || 1) {
182 76a66253 j_mayer
        tb_env->tb_freq = freq;
183 76a66253 j_mayer
        /* Create new timer */
184 76a66253 j_mayer
        tb_env->decr_timer =
185 9fddaa0c bellard
            qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
186 76a66253 j_mayer
        /* There is a bug in Linux 2.4 kernels:
187 76a66253 j_mayer
         * if a decrementer exception is pending when it enables msr_ee,
188 76a66253 j_mayer
         * it's not ready to handle it...
189 76a66253 j_mayer
         */
190 76a66253 j_mayer
        _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
191 9fddaa0c bellard
    }
192 9fddaa0c bellard
193 9fddaa0c bellard
    return tb_env;
194 9fddaa0c bellard
}
195 9fddaa0c bellard
196 76a66253 j_mayer
/* Specific helpers for POWER & PowerPC 601 RTC */
197 76a66253 j_mayer
ppc_tb_t *cpu_ppc601_rtc_init (CPUState *env)
198 76a66253 j_mayer
{
199 76a66253 j_mayer
    return cpu_ppc_tb_init(env, 7812500);
200 76a66253 j_mayer
}
201 76a66253 j_mayer
202 76a66253 j_mayer
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
203 76a66253 j_mayer
__attribute__ (( alias ("cpu_ppc_store_tbu") ));
204 76a66253 j_mayer
205 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
206 76a66253 j_mayer
__attribute__ (( alias ("cpu_ppc_load_tbu") ));
207 76a66253 j_mayer
208 76a66253 j_mayer
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
209 76a66253 j_mayer
{
210 76a66253 j_mayer
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
211 76a66253 j_mayer
}
212 76a66253 j_mayer
213 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
214 76a66253 j_mayer
{
215 76a66253 j_mayer
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
216 76a66253 j_mayer
}
217 76a66253 j_mayer
218 76a66253 j_mayer
/* Embedded PowerPC timers */
219 76a66253 j_mayer
target_ulong load_40x_pit (CPUState *env)
220 76a66253 j_mayer
{
221 76a66253 j_mayer
    /* XXX: TODO */
222 76a66253 j_mayer
    return 0;
223 76a66253 j_mayer
}
224 76a66253 j_mayer
225 76a66253 j_mayer
void store_40x_pit (CPUState *env, target_ulong val)
226 76a66253 j_mayer
{
227 76a66253 j_mayer
    /* XXX: TODO */
228 76a66253 j_mayer
}
229 76a66253 j_mayer
230 76a66253 j_mayer
void store_booke_tcr (CPUState *env, target_ulong val)
231 76a66253 j_mayer
{
232 76a66253 j_mayer
    /* XXX: TODO */
233 76a66253 j_mayer
}
234 76a66253 j_mayer
235 76a66253 j_mayer
void store_booke_tsr (CPUState *env, target_ulong val)
236 76a66253 j_mayer
{
237 76a66253 j_mayer
    /* XXX: TODO */
238 76a66253 j_mayer
}
239 76a66253 j_mayer
240 9fddaa0c bellard
#if 0
241 9fddaa0c bellard
/*****************************************************************************/
242 9fddaa0c bellard
/* Handle system reset (for now, just stop emulation) */
243 9fddaa0c bellard
void cpu_ppc_reset (CPUState *env)
244 9fddaa0c bellard
{
245 9fddaa0c bellard
    printf("Reset asked... Stop emulation\n");
246 9fddaa0c bellard
    abort();
247 9fddaa0c bellard
}
248 9fddaa0c bellard
#endif
249 9fddaa0c bellard
250 64201201 bellard
/*****************************************************************************/
251 64201201 bellard
/* Debug port */
252 fd0bbb12 bellard
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
253 64201201 bellard
{
254 64201201 bellard
    addr &= 0xF;
255 64201201 bellard
    switch (addr) {
256 64201201 bellard
    case 0:
257 64201201 bellard
        printf("%c", val);
258 64201201 bellard
        break;
259 64201201 bellard
    case 1:
260 64201201 bellard
        printf("\n");
261 64201201 bellard
        fflush(stdout);
262 64201201 bellard
        break;
263 64201201 bellard
    case 2:
264 64201201 bellard
        printf("Set loglevel to %04x\n", val);
265 fd0bbb12 bellard
        cpu_set_log(val | 0x100);
266 64201201 bellard
        break;
267 64201201 bellard
    }
268 64201201 bellard
}
269 64201201 bellard
270 64201201 bellard
/*****************************************************************************/
271 64201201 bellard
/* NVRAM helpers */
272 64201201 bellard
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
273 64201201 bellard
{
274 819385c5 bellard
    m48t59_write(nvram, addr, value);
275 64201201 bellard
}
276 64201201 bellard
277 64201201 bellard
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
278 64201201 bellard
{
279 819385c5 bellard
    return m48t59_read(nvram, addr);
280 64201201 bellard
}
281 64201201 bellard
282 64201201 bellard
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
283 64201201 bellard
{
284 819385c5 bellard
    m48t59_write(nvram, addr, value >> 8);
285 819385c5 bellard
    m48t59_write(nvram, addr + 1, value & 0xFF);
286 64201201 bellard
}
287 64201201 bellard
288 64201201 bellard
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
289 64201201 bellard
{
290 64201201 bellard
    uint16_t tmp;
291 64201201 bellard
292 819385c5 bellard
    tmp = m48t59_read(nvram, addr) << 8;
293 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 1);
294 64201201 bellard
    return tmp;
295 64201201 bellard
}
296 64201201 bellard
297 64201201 bellard
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
298 64201201 bellard
{
299 819385c5 bellard
    m48t59_write(nvram, addr, value >> 24);
300 819385c5 bellard
    m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
301 819385c5 bellard
    m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
302 819385c5 bellard
    m48t59_write(nvram, addr + 3, value & 0xFF);
303 64201201 bellard
}
304 64201201 bellard
305 64201201 bellard
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
306 64201201 bellard
{
307 64201201 bellard
    uint32_t tmp;
308 64201201 bellard
309 819385c5 bellard
    tmp = m48t59_read(nvram, addr) << 24;
310 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 1) << 16;
311 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 2) << 8;
312 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 3);
313 76a66253 j_mayer
314 64201201 bellard
    return tmp;
315 64201201 bellard
}
316 64201201 bellard
317 64201201 bellard
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
318 64201201 bellard
                       const unsigned char *str, uint32_t max)
319 64201201 bellard
{
320 64201201 bellard
    int i;
321 64201201 bellard
322 64201201 bellard
    for (i = 0; i < max && str[i] != '\0'; i++) {
323 819385c5 bellard
        m48t59_write(nvram, addr + i, str[i]);
324 64201201 bellard
    }
325 819385c5 bellard
    m48t59_write(nvram, addr + max - 1, '\0');
326 64201201 bellard
}
327 64201201 bellard
328 64201201 bellard
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
329 64201201 bellard
{
330 64201201 bellard
    int i;
331 64201201 bellard
332 64201201 bellard
    memset(dst, 0, max);
333 64201201 bellard
    for (i = 0; i < max; i++) {
334 64201201 bellard
        dst[i] = NVRAM_get_byte(nvram, addr + i);
335 64201201 bellard
        if (dst[i] == '\0')
336 64201201 bellard
            break;
337 64201201 bellard
    }
338 64201201 bellard
339 64201201 bellard
    return i;
340 64201201 bellard
}
341 64201201 bellard
342 64201201 bellard
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
343 64201201 bellard
{
344 64201201 bellard
    uint16_t tmp;
345 64201201 bellard
    uint16_t pd, pd1, pd2;
346 64201201 bellard
347 64201201 bellard
    tmp = prev >> 8;
348 64201201 bellard
    pd = prev ^ value;
349 64201201 bellard
    pd1 = pd & 0x000F;
350 64201201 bellard
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
351 64201201 bellard
    tmp ^= (pd1 << 3) | (pd1 << 8);
352 64201201 bellard
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
353 64201201 bellard
354 64201201 bellard
    return tmp;
355 64201201 bellard
}
356 64201201 bellard
357 64201201 bellard
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
358 64201201 bellard
{
359 64201201 bellard
    uint32_t i;
360 64201201 bellard
    uint16_t crc = 0xFFFF;
361 64201201 bellard
    int odd;
362 64201201 bellard
363 64201201 bellard
    odd = count & 1;
364 64201201 bellard
    count &= ~1;
365 64201201 bellard
    for (i = 0; i != count; i++) {
366 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
367 64201201 bellard
    }
368 64201201 bellard
    if (odd) {
369 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
370 64201201 bellard
    }
371 64201201 bellard
372 64201201 bellard
    return crc;
373 64201201 bellard
}
374 64201201 bellard
375 fd0bbb12 bellard
#define CMDLINE_ADDR 0x017ff000
376 fd0bbb12 bellard
377 64201201 bellard
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
378 64201201 bellard
                          const unsigned char *arch,
379 64201201 bellard
                          uint32_t RAM_size, int boot_device,
380 64201201 bellard
                          uint32_t kernel_image, uint32_t kernel_size,
381 fd0bbb12 bellard
                          const char *cmdline,
382 64201201 bellard
                          uint32_t initrd_image, uint32_t initrd_size,
383 fd0bbb12 bellard
                          uint32_t NVRAM_image,
384 fd0bbb12 bellard
                          int width, int height, int depth)
385 64201201 bellard
{
386 64201201 bellard
    uint16_t crc;
387 64201201 bellard
388 64201201 bellard
    /* Set parameters for Open Hack'Ware BIOS */
389 64201201 bellard
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
390 64201201 bellard
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
391 64201201 bellard
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
392 64201201 bellard
    NVRAM_set_string(nvram, 0x20, arch, 16);
393 64201201 bellard
    NVRAM_set_lword(nvram,  0x30, RAM_size);
394 64201201 bellard
    NVRAM_set_byte(nvram,   0x34, boot_device);
395 64201201 bellard
    NVRAM_set_lword(nvram,  0x38, kernel_image);
396 64201201 bellard
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
397 fd0bbb12 bellard
    if (cmdline) {
398 fd0bbb12 bellard
        /* XXX: put the cmdline in NVRAM too ? */
399 fd0bbb12 bellard
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
400 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
401 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
402 fd0bbb12 bellard
    } else {
403 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, 0);
404 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, 0);
405 fd0bbb12 bellard
    }
406 64201201 bellard
    NVRAM_set_lword(nvram,  0x48, initrd_image);
407 64201201 bellard
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
408 64201201 bellard
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
409 fd0bbb12 bellard
410 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x54, width);
411 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x56, height);
412 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x58, depth);
413 fd0bbb12 bellard
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
414 fd0bbb12 bellard
    NVRAM_set_word(nvram,  0xFC, crc);
415 64201201 bellard
416 64201201 bellard
    return 0;
417 a541f297 bellard
}