1 /*
2  * Copyright (c) 2018 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/reg.h>
9 #include <lk/trace.h>
10 #include <kernel/thread.h>
11 #include <platform.h>
12 #include <platform/interrupts.h>
13 #include <platform/debug.h>
14 #include <platform/timer.h>
15 #include <platform/virt.h>
16 #include <sys/types.h>
17 #include <dev/virtio.h>
18 #include <dev/virtio/net.h>
19 #if WITH_LIB_MINIP
20 #include <lib/minip.h>
21 #endif
22 #if WITH_KERNEL_VM
23 #include <kernel/vm.h>
24 #else
25 #include <kernel/novm.h>
26 #endif
27 #if WITH_LIB_CONSOLE
28 #include <lib/console.h>
29 #endif
30 
31 #include "platform_p.h"
32 
33 #define LOCAL_TRACE 0
34 
35 extern ulong lk_boot_args[4];
36 
37 #if WITH_KERNEL_VM
38 #define DEFAULT_MEMORY_SIZE (MEMSIZE) /* try to fetch from the emulator via the fdt */
39 
40 static pmm_arena_t arena = {
41     .name = "ram",
42     .base = MEMORY_BASE_PHYS,
43     .size = DEFAULT_MEMORY_SIZE,
44     .flags = PMM_ARENA_FLAG_KMAP,
45 };
46 #endif
47 
platform_early_init(void)48 void platform_early_init(void) {
49     goldfish_tty_early_init();
50     pic_early_init();
51     goldfish_rtc_early_init();
52 #if 0
53     plic_early_init();
54 
55     LTRACEF("starting FDT scan\n");
56 
57     /* look for a flattened device tree in the second arg passed to us */
58     bool found_mem = false;
59     int cpu_count = 0;
60     const void *fdt = (void *)lk_boot_args[1];
61 #if WITH_KERNEL_VM
62     fdt = (const void *)((uintptr_t)fdt + PERIPHERAL_BASE_VIRT);
63 #endif
64 
65     struct fdt_walk_callbacks cb = {
66         .mem = memcallback,
67         .memcookie = &found_mem,
68         .cpu = cpucallback,
69         .cpucookie = &cpu_count,
70     };
71 
72     status_t err = fdt_walk(fdt, &cb);
73     LTRACEF("fdt_walk returns %d\n", err);
74 
75     if (err != 0) {
76         printf("FDT: error finding FDT at %p, using default memory & cpu count\n", fdt);
77     }
78 
79     if (!found_mem) {
80 #if WITH_KERNEL_VM
81         pmm_add_arena(&arena);
82 #else
83         novm_add_arena("default", MEMBASE, MEMSIZE);
84 #endif
85     }
86 
87     if (cpu_count > 0) {
88         printf("FDT: found %d cpus\n", cpu_count);
89         riscv_set_secondary_count(cpu_count - 1);
90     }
91 
92 #if WITH_KERNEL_VM
93     /* reserve the first 256K of ram which is marked protected by the PMP in firmware */
94     struct list_node list = LIST_INITIAL_VALUE(list);
95     pmm_alloc_range(MEMBASE, 0x40000 / PAGE_SIZE, &list);
96 #endif
97 
98     LTRACEF("done scanning FDT\n");
99 
100     /* save a copy of the pointer to the poweroff/reset register */
101     /* TODO: read it from the FDT */
102 #if WITH_KERNEL_VM
103     power_reset_reg = paddr_to_kvaddr(0x100000);
104 #else
105     power_reset_reg = (void *)0x100000;
106 #endif
107 #endif
108 }
109 
platform_init(void)110 void platform_init(void) {
111     pic_init();
112     goldfish_tty_init();
113     goldfish_rtc_init();
114 #if 0
115     plic_init();
116     uart_init();
117 
118     /* detect any virtio devices */
119     uint virtio_irqs[NUM_VIRTIO_TRANSPORTS];
120     for (int i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
121         virtio_irqs[i] = IRQ_VIRTIO_BASE + i;
122     }
123 
124     virtio_mmio_detect((void *)VIRTIO_BASE_VIRT, NUM_VIRTIO_TRANSPORTS, virtio_irqs, VIRTIO_STRIDE);
125 
126 #if WITH_LIB_MINIP
127     if (virtio_net_found() > 0) {
128         uint8_t mac_addr[6];
129 
130         virtio_net_get_mac_addr(mac_addr);
131 
132         TRACEF("found virtio networking interface\n");
133 
134         /* start minip */
135         minip_set_macaddr(mac_addr);
136 
137         __UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99);
138         __UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0);
139         __UNUSED uint32_t ip_gateway = IPV4_NONE;
140 
141         //minip_init(virtio_net_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway);
142         minip_init_dhcp(virtio_net_send_minip_pkt, NULL);
143 
144         virtio_net_start();
145     }
146 #endif
147 #endif
148 }
149 
150 #if 0
151 void platform_halt(platform_halt_action suggested_action,
152                           platform_halt_reason reason) {
153     switch (suggested_action) {
154         case HALT_ACTION_SHUTDOWN:
155             dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
156             *power_reset_reg = 0x5555;
157             break;
158         case HALT_ACTION_REBOOT:
159             dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
160             *power_reset_reg = 0x7777;
161             break;
162         case HALT_ACTION_HALT:
163 #if ENABLE_PANIC_SHELL
164             if (reason == HALT_REASON_SW_PANIC) {
165                 dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
166                 arch_disable_ints();
167                 panic_shell_start();
168             }
169 #endif  // ENABLE_PANIC_SHELL
170             dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
171             break;
172     }
173 
174     arch_disable_ints();
175     for (;;)
176         arch_idle();
177 }
178 #endif
179