kernel.early-console is used to specify which output device the kernel boot log should be written to. the first thing the kernel does on boot after initialising the bootstrap processor is initialise the early console, making it useful for debugging problems that occur early in the boot process. this arg accepts a list of hard-coded values for output devices, such as tty0 for the display or ttyS0 for the serial port. the exact values supported will depend on the platform. once all drivers are loaded, the kernel switches to the device specified by kernel.console for output. unlike kernel.early-console, this arg specifies the name of a tty device in /dev/tty. this means that, not only are more devices supported (any device provided by a tty driver), but the kernel can also get input from the user using this console too (not used by the kernel itself, but will be used by the user to interact with userspace programs, like the shell).
201 lines
4.8 KiB
C
201 lines
4.8 KiB
C
#include <socks/pmap.h>
|
|
#include <socks/device.h>
|
|
#include <socks/arg.h>
|
|
#include <socks/tty.h>
|
|
#include <socks/kext.h>
|
|
#include <socks/clock.h>
|
|
#include <socks/types.h>
|
|
#include <socks/object.h>
|
|
#include <arch/e820.h>
|
|
#include <socks/init.h>
|
|
#include <socks/percpu.h>
|
|
#include <socks/cpu.h>
|
|
#include <socks/memblock.h>
|
|
#include <socks/vm.h>
|
|
#include <socks/printk.h>
|
|
#include <socks/console.h>
|
|
#include <socks/machine/cpu.h>
|
|
#include <socks/libc/stdio.h>
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_ACPI
|
|
#include <arch/acpi.h>
|
|
#endif
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_FBCON
|
|
#include <socks/fbcon.h>
|
|
#endif
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_SERIALCON
|
|
#include <socks/serialcon.h>
|
|
#endif
|
|
|
|
#define PTR32(x) ((void *)((uintptr_t)(x)))
|
|
|
|
static ml_cpu_block g_bootstrap_cpu = {0};
|
|
static struct framebuffer_varinfo __bootfb_varinfo;
|
|
static struct framebuffer_fixedinfo __bootfb_fixedinfo;
|
|
|
|
/* start and end of kernel image (physical addresses) */
|
|
extern char __pstart[], __pend[];
|
|
|
|
static void bootstrap_cpu_init(void)
|
|
{
|
|
ml_cpu_block_init(&g_bootstrap_cpu);
|
|
ml_cpu_block_use(&g_bootstrap_cpu);
|
|
}
|
|
|
|
static void early_vm_init(void)
|
|
{
|
|
uintptr_t alloc_start = VM_KERNEL_VOFFSET;
|
|
/* boot code mapped 2 GiB of memory from
|
|
VM_KERNEL_VOFFSET */
|
|
uintptr_t alloc_end = VM_KERNEL_VOFFSET + 0x7fffffff;
|
|
|
|
memblock_init(alloc_start, alloc_end, VM_KERNEL_VOFFSET);
|
|
printk("memblock: allocating from [0x%llx-0x%llx]", alloc_start, alloc_end);
|
|
|
|
memblock_reserve(0x00, (uintptr_t)__pend);
|
|
printk("memblock: reserved bios+kernel at [0x%016llx-0x%016llx]", 0, (uintptr_t)__pend);
|
|
}
|
|
|
|
void early_console_init(void)
|
|
{
|
|
const char *dest = arg_value("kernel.early-console");
|
|
if (!dest) {
|
|
return;
|
|
}
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_FBCON
|
|
if (!strcmp(dest, "tty0")) {
|
|
early_vgacon_init();
|
|
}
|
|
#endif
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_SERIALCON
|
|
if (!strncmp(dest, "ttyS0", 5)) {
|
|
/* TODO allow specifying baud rate from command line */
|
|
unsigned int baud = 115200;
|
|
early_serialcon_init(baud);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void init_bootfb(multiboot_info_t *mb)
|
|
{
|
|
__bootfb_varinfo.fb_xres = mb->framebuffer_width;
|
|
__bootfb_varinfo.fb_yres = mb->framebuffer_height;
|
|
__bootfb_varinfo.fb_bpp = mb->framebuffer_bpp;
|
|
__bootfb_varinfo.fb_stride = mb->framebuffer_pitch;
|
|
|
|
__bootfb_fixedinfo.fb_baseptr = mb->framebuffer_addr;
|
|
|
|
switch (mb->framebuffer_type) {
|
|
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
|
__bootfb_varinfo.fb_flags = FB_MODE_PALETTE;
|
|
__bootfb_varinfo.fb_palette_addr = mb->framebuffer_palette_addr;
|
|
__bootfb_varinfo.fb_palette_nr_colours = mb->framebuffer_palette_num_colors;
|
|
break;
|
|
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
|
__bootfb_varinfo.fb_flags = FB_MODE_RGB;
|
|
__bootfb_varinfo.fb_red.b_length = mb->framebuffer_red_mask_size;
|
|
__bootfb_varinfo.fb_red.b_offset = mb->framebuffer_red_field_position;
|
|
|
|
__bootfb_varinfo.fb_green.b_length = mb->framebuffer_green_mask_size;
|
|
__bootfb_varinfo.fb_green.b_offset = mb->framebuffer_green_field_position;
|
|
|
|
__bootfb_varinfo.fb_blue.b_length = mb->framebuffer_blue_mask_size;
|
|
__bootfb_varinfo.fb_blue.b_offset = mb->framebuffer_blue_field_position;
|
|
|
|
__bootfb_varinfo.fb_alpha.b_length = 0;
|
|
__bootfb_varinfo.fb_alpha.b_offset = 0;
|
|
break;
|
|
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
|
__bootfb_fixedinfo.fb_baseptr = 0xb8000;
|
|
__bootfb_varinfo.fb_flags = FB_MODE_VGATEXT;
|
|
__bootfb_varinfo.fb_xcells = 80;
|
|
__bootfb_varinfo.fb_ycells = 25;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void use_uniprocessor_topology(void)
|
|
{
|
|
cpu_set_available(0);
|
|
cpu_set_online(0);
|
|
}
|
|
|
|
int ml_init(uintptr_t arg)
|
|
{
|
|
multiboot_info_t *mb = (multiboot_info_t *)arg;
|
|
|
|
parse_cmdline(PTR32(mb->cmdline));
|
|
|
|
init_bootfb(mb);
|
|
|
|
bootstrap_cpu_init();
|
|
clock_calibrate(500);
|
|
|
|
early_console_init();
|
|
|
|
print_kernel_banner();
|
|
|
|
early_vm_init();
|
|
printk("video mode: %ux%u", mb->framebuffer_width, mb->framebuffer_height);
|
|
|
|
e820_scan(PTR32(mb->mmap_addr), mb->mmap_length);
|
|
|
|
pmap_bootstrap();
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_ACPI
|
|
acpi_scan_cpu_topology();
|
|
#else
|
|
use_uniprocessor_topology();
|
|
#endif
|
|
|
|
init_per_cpu_areas();
|
|
|
|
struct cpu_data *this_cpu = get_this_cpu();
|
|
memset(this_cpu, 0x0, sizeof *this_cpu);
|
|
|
|
this_cpu->c_flags = CPU_ONLINE;
|
|
this_cpu->c_id = this_cpu();
|
|
g_bootstrap_cpu.c_data = this_cpu;
|
|
put_cpu(this_cpu);
|
|
|
|
struct vm_zone_descriptor vm_zones[] = {
|
|
{ .zd_id = VM_ZONE_DMA, .zd_node = 0, .zd_name = "dma", .zd_base = 0x00, .zd_limit = 0xffffff },
|
|
{ .zd_id = VM_ZONE_NORMAL, .zd_node = 0, .zd_name = "normal", .zd_base = 0x1000000, .zd_limit = UINTPTR_MAX },
|
|
};
|
|
|
|
vm_bootstrap(vm_zones, sizeof vm_zones / sizeof vm_zones[0]);
|
|
|
|
object_bootstrap();
|
|
init_kernel_kext();
|
|
|
|
sched_init();
|
|
|
|
device_init();
|
|
|
|
#ifdef KEXT_NET_DOORSTUCK_SOCKS_ACPI
|
|
acpi_init();
|
|
#endif
|
|
|
|
tty_bootstrap();
|
|
|
|
ml_int_enable();
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct framebuffer_varinfo *bootfb_varinfo(void)
|
|
{
|
|
return &__bootfb_varinfo;
|
|
}
|
|
|
|
const struct framebuffer_fixedinfo *bootfb_fixedinfo(void)
|
|
{
|
|
return &__bootfb_fixedinfo;
|
|
}
|