summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/sparc64/boot.c
blob: 5107be6cab8964512fdb188d9854992a56f033f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 *
 */
#undef BOOTSTRAP
#include "config.h"
#include "libopenbios/bindings.h"
#include "arch/common/nvram.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "libopenbios/sys_info.h"
#include "boot.h"

uint64_t kernel_image;
uint64_t kernel_size;
uint64_t qemu_cmdline;
uint64_t cmdline_size;
char boot_device;

extern int sparc64_of_client_interface( int *params );


void go(void)
{
	ucell address, type, size;
	int image_retval = 0;

	/* Get the entry point and the type (see forth/debugging/client.fs) */
	feval("saved-program-state >sps.entry @");
	address = POP();
	feval("saved-program-state >sps.file-type @");
	type = POP();
	feval("saved-program-state >sps.file-size @");
	size = POP();

	printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);

	switch (type) {
		case 0x0:
			/* Start ELF boot image */
			image_retval = start_elf(address, (uint64_t)&elf_boot_notes);
			break;

		case 0x1:
			/* Start ELF image */
			image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
			break;

		case 0x5:
			/* Start a.out image */
			image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
			break;

		case 0x10:
			/* Start Fcode image */
			printk("Evaluating FCode...\n");
			PUSH(address);
			PUSH(1);
			fword("byte-load");
			image_retval = 0;
			break;

		case 0x11:
			/* Start Forth image */
			PUSH(address);
			PUSH(size);
			fword("eval2");
			image_retval = 0;
			break;
	}

	printk("Image returned with return value %#x\n", image_retval);
}

/* ( path len -- path len ) */

void boot(void)
{
	char *path, *param;

	/* Copy the incoming path */
	fword("2dup");
	path = pop_fstr_copy();

	/* Boot preloaded kernel */
        if (kernel_size) {
            void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3,
                          unsigned long p4, unsigned long p5);

            printk("[sparc64] Kernel already loaded\n");
            entry = (void *) (unsigned long)kernel_image;
            entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface);
        }

	/* Invoke Linux directly -- probably not supported */
	if(!path) {
            /* No path specified, so grab defaults from /chosen */
            push_str("bootpath");
	    push_str("/chosen");
            fword("(find-dev)");
            POP();
            fword("get-package-property");
            POP();
	    /* Update our local copy of path as well as the one on the stack */
	    fword("2dup");
            path = pop_fstr_copy();
	}

        if (path) {
            param = strchr(path, ' ');
            if(param) {
                *param = '\0';
                param++;
            } else if (cmdline_size) {
                param = (char *)qemu_cmdline;
            } else {
                push_str("boot-args");
                push_str("/options");
                fword("(find-dev)");
                POP();
                fword("get-package-property");
                POP();
                param = pop_fstr_copy();
            }

            /* Invoke platform-specific Linux loader */
            linux_load(&sys_info, path, param);

            free(path);
        }
}