1 /*	$NetBSD: kloader_machdep.c,v 1.3 2009/03/15 02:23:52 nonaka Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: kloader_machdep.c,v 1.3 2009/03/15 02:23:52 nonaka Exp $");
31 
32 #include "debug_kloader.h"
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/disklabel.h>
37 
38 #include <machine/kloader.h>
39 #include <machine/pmap.h>
40 
41 #include <arm/cpufunc.h>
42 #include <arm/xscale/pxa2x0reg.h>
43 
44 #include <zaurus/zaurus/zaurus_var.h>
45 
46 #ifndef KERNEL_BASE
47 #define	KERNEL_BASE	0xc0000000
48 #endif
49 
50 kloader_jumpfunc_t kloader_zaurus_jump __attribute__((__noreturn__));
51 kloader_bootfunc_t kloader_zaurus_boot __attribute__((__noreturn__));
52 void kloader_zaurus_reset(void);
53 
54 struct kloader_ops kloader_zaurus_ops = {
55 	.jump = kloader_zaurus_jump,
56 	.boot = kloader_zaurus_boot,
57 	.reset = kloader_zaurus_reset,
58 };
59 
60 void
61 kloader_reboot_setup(const char *filename)
62 {
63 
64 	__kloader_reboot_setup(&kloader_zaurus_ops, filename);
65 }
66 
67 void
68 kloader_zaurus_reset(void)
69 {
70 
71 	zaurus_restart();
72 	/*NOTREACHED*/
73 }
74 
75 void
76 kloader_zaurus_jump(kloader_bootfunc_t func, vaddr_t sp,
77     struct kloader_bootinfo *kbi, struct kloader_page_tag *tag)
78 {
79 	extern int kloader_howto;
80 	void (*bootinfop)(void *, void *) = (void *)(0xc0200000 - PAGE_SIZE);
81 	uint32_t *bootmagicp = (uint32_t *)(0xc0200000 - BOOTARGS_BUFSIZ);
82 	vaddr_t top, ptr;
83 	struct bootinfo *bootinfo;
84 	struct btinfo_howto *bi_howto;
85 	struct btinfo_rootdevice *bi_rootdv;
86 
87 	disable_interrupts(I32_bit|F32_bit);
88 
89 	/* copy 2nd boot-loader to va=pa page */
90 	memmove(bootinfop, func, PAGE_SIZE);
91 
92 	/*
93 	 * make bootinfo
94 	 */
95 	memset(bootmagicp, 0, BOOTARGS_BUFSIZ);
96 	bootinfo = (struct bootinfo *)(bootmagicp + 1);
97 	bootinfo->nentries = 0;
98 	top = ptr = (vaddr_t)bootinfo->info;
99 
100 	/* pass to howto for new kernel */
101 	bi_howto = (struct btinfo_howto *)ptr;
102 	bi_howto->common.len = sizeof(struct btinfo_howto);
103 	bi_howto->common.type = BTINFO_HOWTO;
104 	bi_howto->howto = kloader_howto;
105 	bootinfo->nentries++;
106 	ptr += bi_howto->common.len;
107 
108 	/* set previous root device for new boot device */
109 	if (root_device != NULL
110 	 && device_class(root_device) == DV_DISK
111 	 && !device_is_a(root_device, "dk")) {
112 		bi_rootdv = (struct btinfo_rootdevice *)ptr;
113 		bi_rootdv->common.len = sizeof(struct btinfo_rootdevice);
114 		bi_rootdv->common.type = BTINFO_ROOTDEVICE;
115 		snprintf(bi_rootdv->devname, sizeof(bi_rootdv->devname), "%s%c",
116 		    device_xname(root_device), (int)DISKPART(rootdev) + 'a');
117 		bootinfo->nentries++;
118 		ptr += bi_rootdv->common.len;
119 	}
120 
121 	if (bootinfo->nentries > 0)
122 		*bootmagicp = BOOTARGS_MAGIC;
123 	cpu_idcache_wbinv_all();
124 
125 	/* jump to 2nd boot-loader */
126 	(*bootinfop)(kbi, tag);
127 
128 	/*NOTREACHED*/
129 	for (;;)
130 		continue;
131 }
132 
133 /*
134  * Physcal address to virtual address
135  */
136 vaddr_t
137 kloader_phystov(paddr_t pa)
138 {
139 	vaddr_t va;
140 	int error;
141 
142 	va = KERNEL_BASE + pa - 0xa0000000UL;
143 	error = pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 0);
144 	if (error) {
145 		printf("%s: map failed: pa=0x%lx, va=0x%lx, error=%d\n",
146 		    __func__, pa, va, error);
147 	}
148 	return va;
149 }
150