1 /*        $NetBSD: kloader_machdep.c,v 1.8 2021/08/17 22:00:31 andvar Exp $     */
2 
3 /*-
4  * Copyright (C) 2009-2012 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: kloader_machdep.c,v 1.8 2021/08/17 22:00:31 andvar Exp $");
30 
31 #include "debug_kloader.h"
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.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 #define   KERNEL_TEXT_BASE    ((vaddr_t)&KERNEL_BASE_virt)
47 
48 kloader_jumpfunc_t kloader_zaurus_jump __attribute__((__noreturn__));
49 kloader_bootfunc_t kloader_zaurus_boot __attribute__((__noreturn__));
50 void kloader_zaurus_reset(void);
51 
52 struct kloader_ops kloader_zaurus_ops = {
53           .jump = kloader_zaurus_jump,
54           .boot = kloader_zaurus_boot,
55           .reset = kloader_zaurus_reset,
56 };
57 
58 void
kloader_reboot_setup(const char * filename)59 kloader_reboot_setup(const char *filename)
60 {
61 
62           __kloader_reboot_setup(&kloader_zaurus_ops, filename);
63 }
64 
65 void
kloader_zaurus_reset(void)66 kloader_zaurus_reset(void)
67 {
68 
69           zaurus_restart();
70           /*NOTREACHED*/
71 }
72 
73 void
kloader_zaurus_jump(kloader_bootfunc_t func,vaddr_t sp,struct kloader_bootinfo * kbi,struct kloader_page_tag * tag)74 kloader_zaurus_jump(kloader_bootfunc_t func, vaddr_t sp,
75     struct kloader_bootinfo *kbi, struct kloader_page_tag *tag)
76 {
77           extern int kloader_howto;
78           extern char KERNEL_BASE_virt[];
79           void (*bootinfop)(void *, void *);
80           uint32_t *bootmagicp;
81           vaddr_t ptr;
82           struct bootinfo *bootinfo;
83           struct btinfo_howto *bi_howto;
84           struct btinfo_rootdevice *bi_rootdv;
85 
86           disable_interrupts(I32_bit|F32_bit);
87 
88           /* copy 2nd boot-loader to va=pa page */
89           bootinfop = (void *)(KERNEL_TEXT_BASE - PAGE_SIZE);
90           memmove(bootinfop, func, PAGE_SIZE);
91 
92           /*
93            * make bootinfo
94            */
95           bootmagicp = (uint32_t *)(KERNEL_TEXT_BASE - BOOTARGS_BUFSIZ);
96           memset(bootmagicp, 0, BOOTARGS_BUFSIZ);
97           bootinfo = (struct bootinfo *)(bootmagicp + 1);
98           bootinfo->nentries = 0;
99           ptr = (vaddr_t)bootinfo->info;
100 
101           /* pass to howto for new kernel */
102           bi_howto = (struct btinfo_howto *)ptr;
103           bi_howto->common.len = sizeof(struct btinfo_howto);
104           bi_howto->common.type = BTINFO_HOWTO;
105           bi_howto->howto = kloader_howto;
106           bootinfo->nentries++;
107           ptr += bi_howto->common.len;
108 
109           /* set previous root device for new boot device */
110           if (root_device != NULL
111            && device_class(root_device) == DV_DISK
112            && !device_is_a(root_device, "dk")) {
113                     bi_rootdv = (struct btinfo_rootdevice *)ptr;
114                     bi_rootdv->common.len = sizeof(struct btinfo_rootdevice);
115                     bi_rootdv->common.type = BTINFO_ROOTDEVICE;
116                     snprintf(bi_rootdv->devname, sizeof(bi_rootdv->devname), "%s%c",
117                         device_xname(root_device), (int)DISKPART(rootdev) + 'a');
118                     bootinfo->nentries++;
119                     ptr += bi_rootdv->common.len;
120           }
121 
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  * Physical address to virtual address
135  */
136 vaddr_t
kloader_phystov(paddr_t pa)137 kloader_phystov(paddr_t pa)
138 {
139           vaddr_t va;
140           int error;
141 
142           va = KERNEL_BASE + pa - PXA2X0_SDRAM0_START;
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