1/*
2 * Copyright 2008-2020, Fran��ois Revol, revol@free.fr. All rights reserved.
3 * Copyright 2003-2010, Axel D��rfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include <KernelExport.h>
9#include <boot/platform.h>
10#include <boot/heap.h>
11#include <boot/stage2.h>
12#include <arch/cpu.h>
13
14#include <string.h>
15
16#include "console.h"
17#include "cpu.h"
18#include "mmu.h"
19#include "keyboard.h"
20#include "nextrom.h"
21
22#define HEAP_SIZE 65536
23
24// GCC defined globals
25extern void (*__ctor_list)(void);
26extern void (*__ctor_end)(void);
27extern uint8 __bss_start;
28extern uint8 _end;
29
30extern "C" int main(stage2_args *args);
31extern "C" void _start(void);
32
33// the boot rom monitor entry point
34struct mon_global *mg = NULL;
35
36static uint32 sBootOptions;
37
38
39static void
40clear_bss(void)
41{
42	memset(&__bss_start, 0, &_end - &__bss_start);
43}
44
45
46static void
47call_ctors(void)
48{
49	void (**f)(void);
50
51	for (f = &__ctor_list; f < &__ctor_end; f++) {
52		(**f)();
53	}
54}
55
56
57extern "C" uint32
58platform_boot_options(void)
59{
60#if 0
61	if (!gKernelArgs.fb.enabled)
62		sBootOptions |= check_for_boot_keys();
63#endif
64	return sBootOptions;
65}
66
67
68extern "C" void
69platform_start_kernel(void)
70{
71#if 0
72	static struct kernel_args *args = &gKernelArgs;
73		// something goes wrong when we pass &gKernelArgs directly
74		// to the assembler inline below - might be a bug in GCC
75		// or I don't see something important...
76	addr_t stackTop
77		= gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
78
79	preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
80		gKernelArgs.kernel_image.Pointer());
81
82	//smp_init_other_cpus();
83	//serial_cleanup();
84	mmu_init_for_kernel();
85	//smp_boot_other_cpus();
86
87#warning M68K: stop ints
88
89	dprintf("kernel entry at %lx\n", image->elf_header.e_entry);
90
91	asm volatile (
92		"move.l	%0,%%sp;	"			// move stack out of way
93		: : "m" (stackTop));
94
95	asm volatile (
96		"or	#0x0700,%%sr; " : : );		// disable interrupts
97
98	asm volatile (
99		"move.l  #0x0,-(%%sp); "		// we're the BSP cpu (0)
100		"move.l 	%0,-(%%sp);	"		// kernel args
101		"move.l 	#0x0,-(%%sp);"		// dummy retval for call to main
102		"move.l 	%1,-(%%sp);	"		// this is the start address
103		"rts;		"					// jump.
104		: : "g" (args), "g" (image->elf_header.e_entry));
105
106	// Huston, we have a problem!
107
108	asm volatile (
109		"and	#0xf8ff,%%sr; " : : );		// reenable interrupts
110
111	panic("kernel returned!\n");
112#endif
113
114}
115
116
117extern "C" void
118platform_exit(void)
119{
120	// TODO
121	while (true);
122}
123
124inline void dump_mg(struct mon_global *mg)
125{
126	int i;
127	dprintf("mg@ %p\n", (void*)mg);
128
129	dprintf("mg_flags\t%x\n", (unsigned char)mg->mg_flags);
130	dprintf("mg_sid\t%x\n", mg->mg_sid);
131	dprintf("mg_pagesize\t%x\n", mg->mg_pagesize);
132	dprintf("mg_mon_stack\t%x\n", mg->mg_mon_stack);
133	dprintf("mg_vbr\t%x\n", mg->mg_vbr);
134	dprintf("mg_console_i\t%x\n", mg->mg_console_i);
135	dprintf("mg_console_o\t%x\n", mg->mg_console_o);
136
137	for (i = 0; i < N_SIMM; i++) {
138		dprintf("mg_region[%d] = {%08lx, %08lx}\n", i,
139				mg->mg_region[i].first_phys_addr,
140				mg->mg_region[i].last_phys_addr);
141	}
142
143	dprintf("mg_boot_dev\t%s\n", mg->mg_boot_dev);
144	dprintf("mg_boot_arg\t%s\n", mg->mg_boot_arg);
145	dprintf("mg_boot_info\t%s\n", mg->mg_boot_info);
146	dprintf("mg_boot_file\t%s\n", mg->mg_boot_file);
147	dprintf("mg_boot_dev\t%s\n", mg->mg_boot_dev);
148	dprintf("mg_boot_how\t%d\n", mg->mg_boot_how);
149
150	dprintf("mg_sddp\t%p\n", mg->mg_sddp);
151	dprintf("mg_dgp\t%p\n", mg->mg_dgp);
152		// "dlV3" (disk label signature ?) SCSI boot gives "@dlV3"
153	dprintf("mg_fdgp\t%p\n", mg->mg_fdgp);	// "A" ?? SCSI: "to become ready"
154	dprintf("mg_s5cp\t%p\n", mg->mg_s5cp);
155	dprintf("mg_odc\t%p\n", mg->mg_odc);
156	dprintf("mg_odd\t%p\n", mg->mg_odd);
157
158#if 0
159	for (int i = 0; i < sizeof(struct mon_global); i++) {
160		uint8 *p = ((uint8 *)mg)+i;
161		if (i % 32 == 0)
162			dprintf("%04x", i);
163		if (i % 4 == 0)
164			dprintf(" ");
165		if (i % 8 == 0)
166			dprintf(" ");
167		dprintf("%02x", *p);
168		if (i % 32 == 31 || i == sizeof(struct mon_global) - 1)
169			dprintf("\n");
170	}
171	//while(true);
172#endif
173
174
175	dprintf("mg_si\t%p\n", mg->mg_si);
176	/* XXX:the pointer seems completely random, sadly.
177	 * Possibly the kernel is supposed to set it?
178	 */
179#if 0
180	for (int i = 0; i < sizeof(struct sio); i++) {
181		uint8 *p = ((uint8 *)mg->mg_si)+i;
182		if (i % 32 == 0)
183			dprintf("%04x", i);
184		if (i % 4 == 0)
185			dprintf(" ");
186		if (i % 8 == 0)
187			dprintf(" ");
188		dprintf("%02x", *p);
189		if (i % 32 == 31 || i == sizeof(struct sio) - 1)
190			dprintf("\n");
191	}
192	for (i = 0; i < 5; i++) {
193		struct sio *s = &mg->mg_si[i];
194		dprintf("sio[%d] = {%08x, %u, %u, %u, %p, %u, %u, %p, %p, %p}\n", i,
195				s->si_args, s->si_ctrl, s->si_unit, s->si_part,
196				s->si_dev, s->si_blklen, s->si_lastlba,
197				s->si_sadmem, s->si_protomem, s->si_devmem);
198		s++;
199	}
200#endif
201
202	//dprintf("test_msg\t%p\n", mg->test_msg);
203	/* Framebuffer info */
204#if 1
205	dprintf("km_coni = {%d, %d, %d, %d, %d, ... %d, %d, %d, ...%d}\n",
206			mg->km_coni.pixels_per_word,
207			mg->km_coni.bytes_per_scanline,
208			mg->km_coni.dspy_w,
209			mg->km_coni.dspy_max_w,
210			mg->km_coni.dspy_h,
211			//...
212			mg->km_coni.slot_num,
213			mg->km_coni.fb_num,
214			mg->km_coni.byte_lane_id,
215			mg->km_coni.access_stack);
216	for (i = 0; i < KM_CON_MAP_ENTRIES; i++) {
217		dprintf("km_coni.map_addr[%d] = {%08lx, %08lx, %08lx}\n", i,
218				mg->km_coni.map_addr[i].phys_addr,
219				mg->km_coni.map_addr[i].virt_addr,
220				mg->km_coni.map_addr[i].size);
221	}
222#endif
223
224	//XXX: this one crashes on older ROMs
225	//dprintf("mg_cpu_clk\t%d\n", mg->mg_cpu_clk);
226}
227
228
229extern "C" void *
230start_next(const char *boot_args, struct mon_global *monitor)
231{
232	stage2_args args;
233
234	monitor->mg_putc('H');
235
236	//asm("cld");			// Ain't nothing but a GCC thang.
237	//asm("fninit");		// initialize floating point unit
238
239	//clear_bss();
240	/* save monitor ROM entry */
241	mg = monitor;
242	// DEBUG
243	mg->mg_putc('A');
244
245	call_ctors();
246		// call C++ constructors before doing anything else
247	mg->mg_putc('I');
248
249	args.heap_size = HEAP_SIZE;
250	args.arguments = NULL;
251
252	//serial_init();
253	mg->mg_putc('K');
254	console_init();
255	mg->mg_putc('U');
256	mg->mg_putc('\n');
257
258	dump_mg(mg);
259	//while(1);
260	//return NULL;
261	cpu_init();
262#if 0
263	// TODO
264	mmu_init();
265
266	// wait a bit to give the user the opportunity to press a key
267	spin(750000);
268
269	// reading the keyboard doesn't seem to work in graphics mode (maybe a bochs problem)
270	sBootOptions = check_for_boot_keys();
271	//if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
272		//serial_enable();
273
274	//apm_init();
275	//smp_init();
276#endif
277	main(&args);
278	return NULL;
279}
280