modules: Reimplement loadable kernel modules
This commit is contained in:
parent
b5d33500a6
commit
236c8bacb3
2
Makefile
2
Makefile
@ -91,7 +91,7 @@ system: image.iso
|
||||
$(BASE)/mod/%.ko: modules/%.c | dirs
|
||||
${CC} -c ${KERNEL_CFLAGS} -mcmodel=large -o $@ $<
|
||||
|
||||
ramdisk.igz: $(wildcard $(BASE)/* $(BASE)/*/* $(BASE)/*/*/* $(BASE)/*/*/*/* $(BASE)/*/*/*/*/*) $(APPS_X) $(LIBS_X) $(KRK_MODS_X) $(BASE)/bin/kuroko $(BASE)/lib/ld.so $(APPS_KRK_X) $(KRK_MODS) $(APPS_SH_X)
|
||||
ramdisk.igz: $(wildcard $(BASE)/* $(BASE)/*/* $(BASE)/*/*/* $(BASE)/*/*/*/* $(BASE)/*/*/*/*/*) $(APPS_X) $(LIBS_X) $(KRK_MODS_X) $(BASE)/bin/kuroko $(BASE)/lib/ld.so $(APPS_KRK_X) $(KRK_MODS) $(APPS_SH_X) $(MODULES)
|
||||
python3 util/createramdisk.py
|
||||
|
||||
KRK_SRC = $(sort $(wildcard kuroko/src/*.c))
|
||||
|
34
apps/lspci.c
34
apps/lspci.c
@ -174,7 +174,9 @@ static void show_usage(char * argv[]) {
|
||||
int main(int argc, char * argv[]) {
|
||||
int numeric = 0;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "n?")) != -1) {
|
||||
char * query = NULL;
|
||||
|
||||
while ((opt = getopt(argc, argv, "nq:?")) != -1) {
|
||||
switch (opt) {
|
||||
case '?':
|
||||
show_usage(argv);
|
||||
@ -182,6 +184,9 @@ int main(int argc, char * argv[]) {
|
||||
case 'n':
|
||||
numeric = 1;
|
||||
break;
|
||||
case 'q':
|
||||
query = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +240,31 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
*last_paren = '\0';
|
||||
|
||||
if (numeric) {
|
||||
if (query) {
|
||||
unsigned short vendor_id = strtoul(device_vendor, NULL, 16);
|
||||
unsigned short device_id = strtoul(device_code, NULL, 16);
|
||||
|
||||
char * start = query;
|
||||
while (start) {
|
||||
char * colon = strchr(start, ':');
|
||||
if (!colon) return 2; /* Invalid query string */
|
||||
*colon = '\0';
|
||||
char * comma = strchr(colon+1, ',');
|
||||
if (comma) *comma = '\0';
|
||||
unsigned long query_man = strtoul(start,NULL,16);
|
||||
unsigned long query_dev = strtoul(colon+1,NULL,16);
|
||||
|
||||
if (query_man == vendor_id && query_dev == device_id) return 0;
|
||||
|
||||
*colon = ':';
|
||||
if (comma) {
|
||||
*comma = ',';
|
||||
start = comma + 1;
|
||||
} else {
|
||||
start = NULL;
|
||||
}
|
||||
}
|
||||
} else if (numeric) {
|
||||
fprintf(stdout, "%s %s: %s:%s\n", device_bus, device_class, device_vendor, device_code);
|
||||
} else {
|
||||
unsigned short class_id = strtoul(device_class, NULL, 16);
|
||||
@ -256,5 +285,6 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (query) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
11
base/etc/startup.d/04_modprobe.sh
Executable file
11
base/etc/startup.d/04_modprobe.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Add module descriptions here...
|
||||
if lspci -q 8086:2415 then insmod /mod/ac97.ko
|
||||
if lspci -q 1234:1111 then insmod /mod/vmware.ko
|
||||
if lspci -q 80EE:CAFE then insmod /mod/vbox.ko
|
||||
if lspci -q 8086:0046 then insmod /mod/i965.ko
|
||||
|
||||
if lspci -q 8086:100e,8086:1004,8086:100f,8086:10ea,8086:10d3 then insmod /mod/e1000.ko
|
||||
|
||||
|
@ -32,6 +32,7 @@ uintptr_t mmu_allocate_n_frames(int n);
|
||||
union PML * mmu_get_kernel_directory(void);
|
||||
void * mmu_map_from_physical(uintptr_t frameaddress);
|
||||
void * mmu_map_mmio_region(uintptr_t physical_address, size_t size);
|
||||
void * mmu_map_module(size_t size);
|
||||
|
||||
size_t mmu_count_user(union PML * from);
|
||||
size_t mmu_count_shm(union PML * from);
|
||||
|
7
base/usr/include/kernel/module.h
Normal file
7
base/usr/include/kernel/module.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct Module {
|
||||
const char * name;
|
||||
int (*init)(int argc, char * argv[]);
|
||||
int (*fini)(void);
|
||||
};
|
@ -41,6 +41,7 @@ extern void portio_initialize(void);
|
||||
extern void ps2hid_install(void);
|
||||
extern void serial_initialize(void);
|
||||
extern void fbterm_initialize(void);
|
||||
extern void xhci_initialize(void);
|
||||
|
||||
#define EARLY_LOG_DEVICE 0x3F8
|
||||
static size_t _early_log_write(size_t size, uint8_t * buffer) {
|
||||
@ -290,30 +291,8 @@ int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) {
|
||||
ps2hid_install();
|
||||
serial_initialize();
|
||||
portio_initialize();
|
||||
|
||||
extern void xhci_initialize(void);
|
||||
xhci_initialize();
|
||||
|
||||
/* Special drivers should probably be modules... */
|
||||
extern void ac97_install(void);
|
||||
ac97_install();
|
||||
|
||||
if (!args_present("novmware")) {
|
||||
extern void vmware_initialize(void);
|
||||
vmware_initialize();
|
||||
}
|
||||
|
||||
if (!args_present("novbox")) {
|
||||
extern void vbox_initialize(void);
|
||||
vbox_initialize();
|
||||
}
|
||||
|
||||
extern void i965_initialize(void);
|
||||
i965_initialize();
|
||||
|
||||
extern void e1000_initialize(void);
|
||||
e1000_initialize();
|
||||
|
||||
/* Yield to the generic main, which starts /bin/init */
|
||||
return generic_main();
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ static uint32_t nframes;
|
||||
#define KERNEL_HEAP_START 0xFFFFff0000000000UL
|
||||
#define MMIO_BASE_START 0xffffff1fc0000000UL
|
||||
#define HIGH_MAP_REGION 0xffffff8000000000UL
|
||||
#define MODULE_BASE_START 0xffffffff80000000UL
|
||||
|
||||
/* These are actually defined in the shm layer... */
|
||||
#define USER_SHM_LOW 0x0000000200000000UL
|
||||
@ -86,6 +87,7 @@ int mmu_frame_test(uintptr_t frame_addr) {
|
||||
static spin_lock_t frame_alloc_lock = { 0 };
|
||||
static spin_lock_t kheap_lock = { 0 };
|
||||
static spin_lock_t mmio_space_lock = { 0 };
|
||||
static spin_lock_t module_space_lock = { 0 };
|
||||
|
||||
/**
|
||||
* @brief Find the first range of @p n contiguous frames.
|
||||
@ -807,3 +809,33 @@ void * mmu_map_mmio_region(uintptr_t physical_address, size_t size) {
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static uintptr_t module_base_address = MODULE_BASE_START;
|
||||
|
||||
/**
|
||||
* @brief Obtain space to load a module in the -2GiB region.
|
||||
*
|
||||
* This should really start immediately after the kernel, but we don't
|
||||
* yet load the kernel in the -2GiB region... it might also be worthwhile
|
||||
* to implement some ASLR here, especially given that we're loading
|
||||
* relocatable ELF object files and can stick them anywhere.
|
||||
*/
|
||||
void * mmu_map_module(size_t size) {
|
||||
if (size & PAGE_LOW_MASK) {
|
||||
size += (PAGE_LOW_MASK + 1) - (size & PAGE_LOW_MASK);
|
||||
}
|
||||
|
||||
spin_lock(module_space_lock);
|
||||
void * out = (void*)module_base_address;
|
||||
for (size_t i = 0; i < size; i += PAGE_SIZE) {
|
||||
union PML * p = mmu_get_page(module_base_address + i, MMU_GET_MAKE);
|
||||
mmu_frame_allocate(p, MMU_FLAG_KERNEL | MMU_FLAG_WRITABLE);
|
||||
mmu_invalidate(module_base_address + i);
|
||||
}
|
||||
module_base_address += size;
|
||||
spin_unlock(module_space_lock);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/mmu.h>
|
||||
#include <kernel/misc.h>
|
||||
#include <kernel/ksym.h>
|
||||
|
||||
static Elf64_Shdr * elf_getSection(Elf64_Header * this, Elf64_Word index) {
|
||||
return (Elf64_Shdr*)((uintptr_t)this + this->e_shoff + index * this->e_shentsize);
|
||||
@ -49,6 +50,11 @@ static const char * sectionHeaderTypeToStr(Elf64_Word type) {
|
||||
}
|
||||
}
|
||||
|
||||
struct Module {
|
||||
const char * name;
|
||||
int (*init)(int argc, char * argv[]);
|
||||
int (*fini)(void);
|
||||
};
|
||||
|
||||
int elf_module(const char * path) {
|
||||
Elf64_Header header;
|
||||
@ -80,69 +86,105 @@ int elf_module(const char * path) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printf("Loading module...\n");
|
||||
/* Just slap the whole thing into memory, why not... */
|
||||
char * module_load_address = mmu_map_module(file->length);
|
||||
read_fs(file, 0, file->length, (void*)module_load_address);
|
||||
|
||||
/**
|
||||
* Load the section string table, we'll want this for debugging, mostly.
|
||||
*/
|
||||
Elf64_Shdr shstr_hdr;
|
||||
read_fs(file, header.e_shoff + header.e_shentsize * header.e_shstrndx, sizeof(Elf64_Shdr), (uint8_t*)&shstr_hdr);
|
||||
|
||||
char * stringTable = malloc(shstr_hdr.sh_size);
|
||||
read_fs(file, shstr_hdr.sh_offset, shstr_hdr.sh_size, (uint8_t*)stringTable);
|
||||
|
||||
/**
|
||||
* Modules are relocatable objects, so we have to link them by sections,
|
||||
* not by PHDRs - they don't have those. We'll generally see a lot more
|
||||
* relocations but usually of a smaller set.
|
||||
*/
|
||||
printf("\nSection Headers:\n");
|
||||
printf(" [Nr] Name Type Address Offset\n");
|
||||
printf(" Size EntSize Flags Link Info Align\n");
|
||||
for (unsigned int i = 0; i < header.e_shnum; ++i) {
|
||||
Elf64_Shdr sectionHeader;
|
||||
read_fs(file, header.e_shoff + header.e_shentsize * i, sizeof(Elf64_Shdr), (uint8_t*)§ionHeader);
|
||||
if (sectionHeader.sh_type == SHT_PROGBITS) {
|
||||
printf("progbits: %s\n", stringTable + sectionHeader.sh_name);
|
||||
} else if (sectionHeader.sh_type == SHT_NOBITS) {
|
||||
printf("nobits: %s\n", stringTable + sectionHeader.sh_name);
|
||||
}
|
||||
#if 0
|
||||
printf(" [%2d] %-17.17s %-16.16s %016lx %08lx\n",
|
||||
i, stringTable + sectionHeader.sh_name, sectionHeaderTypeToStr(sectionHeader.sh_type),
|
||||
sectionHeader.sh_addr, sectionHeader.sh_offset);
|
||||
printf(" %016lx %016lx %4ld %6d %5d %5ld\n",
|
||||
sectionHeader.sh_size, sectionHeader.sh_entsize, sectionHeader.sh_flags,
|
||||
sectionHeader.sh_link, sectionHeader.sh_info, sectionHeader.sh_addralign);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to load a module, we need to link it as an object
|
||||
* into the running kernel using the symbol table we integrated
|
||||
* into our binary.
|
||||
*/
|
||||
//char * shrstrtab = (char*)elfHeader + elf_getSection(elfHeader, elfHeader->e_shstrndx)->sh_offset;
|
||||
|
||||
/**
|
||||
* First, we're going to check sections and update their addresses.
|
||||
* Locate the section string table, which we'll use for debugging and to check
|
||||
* for special section names (eg. dependencies, PCI mappings...)
|
||||
*/
|
||||
#if 0
|
||||
for (unsigned int i = 0; i < elfHeader->e_shnum; ++i) {
|
||||
Elf64_Shdr * shdr = elf_getSection(elfHeader, i);
|
||||
if (shdr->sh_type == SHT_NOBITS) {
|
||||
if (shdr->sh_size) {
|
||||
printf("Warning: Module needs %lu bytes for BSS, we don't have an allocator.\n",
|
||||
shdr->sh_size);
|
||||
}
|
||||
/* otherwise, skip bss */
|
||||
} else {
|
||||
shdr->sh_addr = (uintptr_t)atAddress + shdr->sh_offset;
|
||||
}
|
||||
}
|
||||
Elf64_Shdr * shstr_hdr = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * header.e_shstrndx);
|
||||
char * stringTable = (char*)(module_load_address + shstr_hdr->sh_offset);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
/**
|
||||
* Set up section header entries to have correct loaded addresses, and map
|
||||
* any NOBITS sections to new memory. We'll page-align anything, which
|
||||
* should be good enough for any object files we make...
|
||||
*/
|
||||
for (unsigned int i = 0; i < header.e_shnum; ++i) {
|
||||
Elf64_Shdr * sectionHeader = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * i);
|
||||
if (sectionHeader->sh_type == SHT_NOBITS) {
|
||||
sectionHeader->sh_addr = (uintptr_t)mmu_map_module(sectionHeader->sh_size);
|
||||
memset((void*)sectionHeader->sh_addr, 0, sectionHeader->sh_size);
|
||||
} else {
|
||||
sectionHeader->sh_addr = (uintptr_t)(module_load_address + sectionHeader->sh_offset);
|
||||
}
|
||||
}
|
||||
|
||||
struct Module * moduleData = NULL;
|
||||
|
||||
/**
|
||||
* Let's start loading symbols...
|
||||
*/
|
||||
for (unsigned int i = 0; i < header.e_shnum; ++i) {
|
||||
Elf64_Shdr * sectionHeader = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * i);
|
||||
if (sectionHeader->sh_type != SHT_SYMTAB) continue;
|
||||
Elf64_Shdr * strtab_hdr = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * sectionHeader->sh_link);
|
||||
char * symNames = (char*)strtab_hdr->sh_addr;
|
||||
Elf64_Sym * symTable = (Elf64_Sym*)sectionHeader->sh_addr;
|
||||
/* Uh, we should be able to figure out how many symbols we have by doing something less dumb than
|
||||
* just checking the size of the section, right? */
|
||||
for (unsigned int sym = 0; sym < sectionHeader->sh_size / sizeof(Elf64_Sym); ++sym) {
|
||||
/* TODO: We need to share symbols... */
|
||||
#if 0
|
||||
int binding = (symTable[sym].st_info >> 4);
|
||||
int type = (symTable[sym].st_info & 0xF);
|
||||
#endif
|
||||
|
||||
if (symTable[sym].st_shndx > 0 && symTable[sym].st_shndx < SHN_LOPROC) {
|
||||
Elf64_Shdr * sh_hdr = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * symTable[sym].st_shndx);
|
||||
symTable[sym].st_value = symTable[sym].st_value + sh_hdr->sh_addr;
|
||||
} else if (symTable[sym].st_shndx == SHN_UNDEF) {
|
||||
symTable[sym].st_value = (uintptr_t)ksym_lookup(symNames + symTable[sym].st_name);
|
||||
}
|
||||
|
||||
if (symTable[sym].st_name && !strcmp(symNames + symTable[sym].st_name, "metadata")) {
|
||||
moduleData = (void*)symTable[sym].st_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!moduleData) {
|
||||
printf("No module data, bailing.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < header.e_shnum; ++i) {
|
||||
Elf64_Shdr * sectionHeader = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * i);
|
||||
if (sectionHeader->sh_type != SHT_RELA) continue;
|
||||
|
||||
Elf64_Rela * table = (Elf64_Rela*)sectionHeader->sh_addr;
|
||||
|
||||
/* Get the section these relocations apply to */
|
||||
Elf64_Shdr * targetSection = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * sectionHeader->sh_info);
|
||||
|
||||
/* Get the symbol table */
|
||||
Elf64_Shdr * symbolSection = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * sectionHeader->sh_link);
|
||||
Elf64_Sym * symbolTable = (Elf64_Sym *)symbolSection->sh_addr;
|
||||
|
||||
for (unsigned int rela = 0; rela < sectionHeader->sh_size / sizeof(Elf64_Rela); ++rela) {
|
||||
uintptr_t target = table[rela].r_offset + targetSection->sh_addr;
|
||||
switch (ELF64_R_TYPE(table[rela].r_info)) {
|
||||
case R_X86_64_64:
|
||||
*(uint64_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend;
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
*(uint32_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend;
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
*(uint32_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend - target;
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported relocation: %ld\n", ELF64_R_TYPE(table[rela].r_info));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moduleData->init(0,NULL);
|
||||
}
|
||||
|
||||
int elf_exec(const char * path, fs_node_t * file, int argc, const char *const argv[], const char *const env[], int interp) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
* Copyright (C) 2015-2021 K. Lange
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/string.h>
|
||||
#include <kernel/printf.h>
|
||||
@ -26,6 +27,7 @@
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/mmu.h>
|
||||
#include <kernel/list.h>
|
||||
#include <kernel/module.h>
|
||||
#include <kernel/mod/snd.h>
|
||||
|
||||
#include <kernel/arch/x86_64/ports.h>
|
||||
@ -241,11 +243,11 @@ static int ac97_mixer_write(uint32_t knob_id, uint32_t val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ac97_install(void) {
|
||||
static int ac97_install(int argc, char * argv[]) {
|
||||
//debug_print(NOTICE, "Initializing AC97");
|
||||
pci_scan(&find_ac97, -1, &_device);
|
||||
if (!_device.pci_device) {
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
_device.nabmbar = pci_read_field(_device.pci_device, AC97_NABMBAR, 2) & ((uint32_t) -1) << 1;
|
||||
_device.nambar = pci_read_field(_device.pci_device, PCI_BAR0, 4) & ((uint32_t) -1) << 1;
|
||||
@ -300,10 +302,9 @@ void ac97_install(void) {
|
||||
|
||||
//debug_print(NOTICE, "AC97 initialized successfully");
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int fini(void) {
|
||||
snd_unregister(&_snd);
|
||||
|
||||
@ -313,5 +314,10 @@ static int fini(void) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Module metadata = {
|
||||
.name = "ac97",
|
||||
.init = ac97_install,
|
||||
.fini = fini,
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <kernel/mod/net.h>
|
||||
#include <kernel/net/netif.h>
|
||||
#include <kernel/net/eth.h>
|
||||
#include <kernel/module.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <kernel/arch/x86_64/irq.h>
|
||||
@ -370,8 +371,15 @@ static int wait_e1000(fs_node_t *node, void * process) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void e1000_init(void * data) {
|
||||
static void e1000_process(void * data) {
|
||||
struct e1000_nic * nic = data;
|
||||
while (1) {
|
||||
struct ethernet_packet * packet = dequeue_packet(nic);
|
||||
net_eth_handle(packet, nic->eth.device_node);
|
||||
}
|
||||
}
|
||||
|
||||
static void e1000_init(struct e1000_nic * nic) {
|
||||
uint32_t e1000_device_pci = nic->pci_device;
|
||||
|
||||
nic->rx_phys = mmu_allocate_a_frame() << 12;
|
||||
@ -511,11 +519,9 @@ static void e1000_init(void * data) {
|
||||
|
||||
net_add_interface(nic->eth.if_name, nic->eth.device_node);
|
||||
|
||||
/* Now wait for packets */
|
||||
while (1) {
|
||||
struct ethernet_packet * packet = dequeue_packet(nic);
|
||||
net_eth_handle(packet, nic->eth.device_node);
|
||||
}
|
||||
char worker_name[34];
|
||||
snprintf(worker_name, 33, "[%s]", nic->eth.if_name);
|
||||
spawn_worker_thread(e1000_process, worker_name, nic);
|
||||
}
|
||||
|
||||
static void find_e1000(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * found) {
|
||||
@ -531,21 +537,31 @@ static void find_e1000(uint32_t device, uint16_t vendorid, uint16_t deviceid, vo
|
||||
(int)pci_extract_bus(device),
|
||||
(int)pci_extract_slot(device));
|
||||
|
||||
char worker_name[34];
|
||||
snprintf(worker_name, 33, "[%s]", nic->eth.if_name);
|
||||
spawn_worker_thread(e1000_init, worker_name, nic);
|
||||
|
||||
e1000_init(nic);
|
||||
*(int*)found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void e1000_initialize(void) {
|
||||
static int e1000_install(int argc, char * argv[]) {
|
||||
uint32_t found = 0;
|
||||
pci_scan(&find_e1000, -1, &found);
|
||||
|
||||
if (!found) {
|
||||
/* TODO: Clean up? Remove ourselves? */
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
/* TODO: Uninstall device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Module metadata = {
|
||||
.name = "e1000",
|
||||
.init = e1000_install,
|
||||
.fini = fini,
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
* for the panel on one particular model of Lenovo ThinkPad and then sets
|
||||
* a handful of registers to get the framebuffer into the right resolution.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <kernel/printf.h>
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/video.h>
|
||||
@ -14,6 +15,7 @@
|
||||
#include <kernel/mmu.h>
|
||||
#include <kernel/vfs.h>
|
||||
#include <kernel/args.h>
|
||||
#include <kernel/module.h>
|
||||
|
||||
#define REG_PIPEASRC 0x6001C
|
||||
#define REG_PIPEACONF 0x70008
|
||||
@ -82,7 +84,19 @@ static void find_intel(uint32_t device, uint16_t v, uint16_t d, void * extra) {
|
||||
}
|
||||
}
|
||||
|
||||
void i965_initialize(void) {
|
||||
if (args_present("noi965")) return;
|
||||
static int i965_install(int argc, char * argv[]) {
|
||||
if (args_present("noi965")) return -ENODEV;
|
||||
pci_scan(find_intel, -1, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Module metadata = {
|
||||
.name = "i965",
|
||||
.init = i965_install,
|
||||
.fini = fini,
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include <kernel/printf.h>
|
||||
#include <kernel/module.h>
|
||||
|
||||
static int init(int argc, char * argv[]) {
|
||||
printf("Hello, world.\n");
|
||||
printf("Hello, modules.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -9,11 +10,7 @@ static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Module {
|
||||
const char * name;
|
||||
int (*init)(int argc, char * argv[]);
|
||||
int (*fini)(void);
|
||||
} module_info_test = {
|
||||
struct Module metadata = {
|
||||
.name = "test",
|
||||
.init = init,
|
||||
.fini = fini,
|
||||
|
@ -14,7 +14,7 @@
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2016-2021 K. Lange
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/vfs.h>
|
||||
#include <kernel/printf.h>
|
||||
@ -24,6 +24,7 @@
|
||||
#include <kernel/pipe.h>
|
||||
#include <kernel/mouse.h>
|
||||
#include <kernel/args.h>
|
||||
#include <kernel/module.h>
|
||||
|
||||
#include <kernel/arch/x86_64/regs.h>
|
||||
#include <kernel/arch/x86_64/ports.h>
|
||||
@ -276,183 +277,194 @@ static void * kvmalloc_p(size_t size, uint32_t * outphys) {
|
||||
return mmu_map_from_physical(index);
|
||||
}
|
||||
|
||||
void vbox_initialize(void) {
|
||||
static int vbox_install(int argc, char * argv[]) {
|
||||
if (args_present("novbox")) return -ENODEV;
|
||||
pci_scan(vbox_scan_pci, -1, &vbox_device);
|
||||
if (!vbox_device) return -ENODEV;
|
||||
|
||||
if (vbox_device) {
|
||||
if (!args_present("novboxdebug")) {
|
||||
vbox_set_log();
|
||||
}
|
||||
|
||||
uintptr_t t = pci_read_field(vbox_device, PCI_BAR0, 4);
|
||||
if (t > 0) {
|
||||
vbox_port = (t & 0xFFFFFFF0);
|
||||
}
|
||||
|
||||
uint16_t c = pci_read_field(vbox_device, PCI_COMMAND, 2);
|
||||
//fprintf(&vb, "Command register: 0x%4x\n", c);
|
||||
if (!!(c & (1 << 10))) {
|
||||
//fprintf(&vb, "Interrupts are disabled\n");
|
||||
}
|
||||
|
||||
|
||||
mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
mouse_pipe->ioctl = ioctl_mouse;
|
||||
|
||||
vfs_mount("/dev/absmouse", mouse_pipe);
|
||||
|
||||
vbox_irq = pci_get_interrupt(vbox_device);
|
||||
//fprintf(&vb, "irq line is %d\n", vbox_irq);
|
||||
irq_install_handler(vbox_irq, vbox_irq_handler, "vbox");
|
||||
|
||||
uint32_t vbox_phys = 0;
|
||||
struct vbox_guest_info * packet = (void*)kvmalloc_p(0x1000, &vbox_phys);
|
||||
packet->header.size = sizeof(struct vbox_guest_info);
|
||||
packet->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
packet->header.requestType = VMM_ReportGuestInfo;
|
||||
packet->header.rc = 0;
|
||||
packet->header.reserved1 = 0;
|
||||
packet->header.reserved2 = 0;
|
||||
packet->version = VMMDEV_VERSION;
|
||||
packet->ostype = 0x00100; /* Unknown, x86-64 */
|
||||
|
||||
outportl(vbox_port, vbox_phys);
|
||||
|
||||
struct vbox_guest_caps * caps = (void*)kvmalloc_p(0x1000, &vbox_phys);
|
||||
caps->header.size = sizeof(struct vbox_guest_caps);
|
||||
caps->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
caps->header.requestType = VMM_ReportGuestCapabilities;
|
||||
caps->header.rc = 0;
|
||||
caps->header.reserved1 = 0;
|
||||
caps->header.reserved2 = 0;
|
||||
caps->caps = VMMCAP_Graphics | (args_present("novboxseamless") ? 0 : VMMCAP_SeamlessMode);
|
||||
outportl(vbox_port, vbox_phys);
|
||||
|
||||
vbox_irq_ack = (void*)kvmalloc_p(0x1000, &vbox_phys_ack);
|
||||
vbox_irq_ack->header.size = sizeof(struct vbox_ack_events);
|
||||
vbox_irq_ack->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_irq_ack->header.requestType = VMM_AcknowledgeEvents;
|
||||
vbox_irq_ack->header.rc = 0;
|
||||
vbox_irq_ack->header.reserved1 = 0;
|
||||
vbox_irq_ack->header.reserved2 = 0;
|
||||
vbox_irq_ack->events = 0;
|
||||
|
||||
|
||||
vbox_disp = (void*)kvmalloc_p(0x1000, &vbox_phys_disp);
|
||||
vbox_disp->header.size = sizeof(struct vbox_display_change);
|
||||
vbox_disp->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_disp->header.requestType = VMM_GetDisplayChangeRequest;
|
||||
vbox_disp->header.rc = 0;
|
||||
vbox_disp->header.reserved1 = 0;
|
||||
vbox_disp->header.reserved2 = 0;
|
||||
vbox_disp->xres = 0;
|
||||
vbox_disp->yres = 0;
|
||||
vbox_disp->bpp = 0;
|
||||
vbox_disp->eventack = 1;
|
||||
|
||||
vbox_m = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse);
|
||||
mouse_on_off(VBOX_MOUSE_ON);
|
||||
|
||||
/* For use with later receives */
|
||||
vbox_mg = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse_get);
|
||||
vbox_mg->header.size = sizeof(struct vbox_mouse);
|
||||
vbox_mg->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_mg->header.requestType = VMM_GetMouseState;
|
||||
vbox_mg->header.rc = 0;
|
||||
vbox_mg->header.reserved1 = 0;
|
||||
vbox_mg->header.reserved2 = 0;
|
||||
|
||||
if (!args_present("novboxpointer")) {
|
||||
vbox_pointershape = (void*)kvmalloc_p(0x4000, &vbox_phys_pointershape);
|
||||
|
||||
if (vbox_pointershape) {
|
||||
//fprintf(&vb, "Got a valid set of pages to load up a cursor.\n");
|
||||
vbox_pointershape->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_pointershape->header.requestType = VMM_SetPointerShape;
|
||||
vbox_pointershape->header.rc = 0;
|
||||
vbox_pointershape->header.reserved1 = 0;
|
||||
vbox_pointershape->header.reserved2 = 0;
|
||||
vbox_pointershape->flags = (1 << 0) | (1 << 1) | (1 << 2);
|
||||
vbox_pointershape->xHot = 26;
|
||||
vbox_pointershape->yHot = 26;
|
||||
vbox_pointershape->width = 48;
|
||||
vbox_pointershape->height = 48;
|
||||
|
||||
unsigned int mask_bytes = ((vbox_pointershape->width + 7) / 8) * vbox_pointershape->height;
|
||||
|
||||
for (uint32_t i = 0; i < mask_bytes; ++i) {
|
||||
vbox_pointershape->data[i] = 0x00;
|
||||
}
|
||||
|
||||
while (mask_bytes & 3) {
|
||||
mask_bytes++;
|
||||
}
|
||||
int base = mask_bytes;
|
||||
//fprintf(&vb, "mask_bytes = %d\n", mask_bytes);
|
||||
|
||||
vbox_pointershape->header.size = sizeof(struct vbox_pointershape) + (48*48*4)+mask_bytes; /* update later */
|
||||
|
||||
for (int i = 0; i < 48 * 48; ++i) {
|
||||
vbox_pointershape->data[base+i*4] = 0x00; /* blue */
|
||||
vbox_pointershape->data[base+i*4+1] = 0x00; /* red */
|
||||
vbox_pointershape->data[base+i*4+2] = 0x00; /* green */
|
||||
vbox_pointershape->data[base+i*4+3] = 0x00; /* alpha */
|
||||
}
|
||||
outportl(vbox_port, vbox_phys_pointershape);
|
||||
|
||||
if (vbox_pointershape->header.rc < 0) {
|
||||
//fprintf(&vb, "Bad response code: -%d\n", -vbox_pointershape->header.rc);
|
||||
} else {
|
||||
/* Success, let's install the device file */
|
||||
//fprintf(&vb, "Successfully initialized cursor, going to allow compositor to set it.\n");
|
||||
pointer_pipe = malloc(sizeof(fs_node_t));
|
||||
memset(pointer_pipe, 0, sizeof(fs_node_t));
|
||||
pointer_pipe->mask = 0666;
|
||||
pointer_pipe->flags = FS_CHARDEVICE;
|
||||
pointer_pipe->write = write_pointer;
|
||||
|
||||
vfs_mount("/dev/vboxpointer", pointer_pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!args_present("novboxseamless")) {
|
||||
vbox_visibleregion = (void*)kvmalloc_p(0x1000, &vbox_phys_visibleregion);
|
||||
vbox_visibleregion->header.size = sizeof(struct vbox_header) + sizeof(uint32_t) + sizeof(int32_t) * 4; /* TODO + more for additional rects? */
|
||||
vbox_visibleregion->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_visibleregion->header.requestType = VMM_VideoSetVisibleRegion;
|
||||
vbox_visibleregion->header.rc = 0;
|
||||
vbox_visibleregion->header.reserved1 = 0;
|
||||
vbox_visibleregion->header.reserved2 = 0;
|
||||
vbox_visibleregion->count = 1;
|
||||
vbox_visibleregion->rect[0].xLeft = 0;
|
||||
vbox_visibleregion->rect[0].yTop = 0;
|
||||
vbox_visibleregion->rect[0].xRight = 1440;
|
||||
vbox_visibleregion->rect[0].yBottom = 900;
|
||||
outportl(vbox_port, vbox_phys_visibleregion);
|
||||
|
||||
rect_pipe = malloc(sizeof(fs_node_t));
|
||||
memset(rect_pipe, 0, sizeof(fs_node_t));
|
||||
rect_pipe->mask = 0666;
|
||||
rect_pipe->flags = FS_CHARDEVICE;
|
||||
rect_pipe->write = write_rectpipe;
|
||||
|
||||
vfs_mount("/dev/vboxrects", rect_pipe);
|
||||
}
|
||||
|
||||
/* device memory region mapping? */
|
||||
{
|
||||
uintptr_t t = pci_read_field(vbox_device, PCI_BAR1, 4);
|
||||
//fprintf(&vb, "mapping vmm_dev = 0x%x\n", t);
|
||||
if (t > 0) {
|
||||
vbox_vmmdev = mmu_map_from_physical(t & 0xFFFFFFF0);
|
||||
printf("Setting vbox mem device at %p\n", (void*)vbox_vmmdev);
|
||||
}
|
||||
}
|
||||
|
||||
vbox_vmmdev[3] = 0xFFFFFFFF; /* Enable all for now */
|
||||
if (!args_present("novboxdebug")) {
|
||||
vbox_set_log();
|
||||
}
|
||||
|
||||
uintptr_t t = pci_read_field(vbox_device, PCI_BAR0, 4);
|
||||
if (t > 0) {
|
||||
vbox_port = (t & 0xFFFFFFF0);
|
||||
}
|
||||
|
||||
uint16_t c = pci_read_field(vbox_device, PCI_COMMAND, 2);
|
||||
//fprintf(&vb, "Command register: 0x%4x\n", c);
|
||||
if (!!(c & (1 << 10))) {
|
||||
//fprintf(&vb, "Interrupts are disabled\n");
|
||||
}
|
||||
|
||||
|
||||
mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
mouse_pipe->ioctl = ioctl_mouse;
|
||||
|
||||
vfs_mount("/dev/absmouse", mouse_pipe);
|
||||
|
||||
vbox_irq = pci_get_interrupt(vbox_device);
|
||||
//fprintf(&vb, "irq line is %d\n", vbox_irq);
|
||||
irq_install_handler(vbox_irq, vbox_irq_handler, "vbox");
|
||||
|
||||
uint32_t vbox_phys = 0;
|
||||
struct vbox_guest_info * packet = (void*)kvmalloc_p(0x1000, &vbox_phys);
|
||||
packet->header.size = sizeof(struct vbox_guest_info);
|
||||
packet->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
packet->header.requestType = VMM_ReportGuestInfo;
|
||||
packet->header.rc = 0;
|
||||
packet->header.reserved1 = 0;
|
||||
packet->header.reserved2 = 0;
|
||||
packet->version = VMMDEV_VERSION;
|
||||
packet->ostype = 0x00100; /* Unknown, x86-64 */
|
||||
|
||||
outportl(vbox_port, vbox_phys);
|
||||
|
||||
struct vbox_guest_caps * caps = (void*)kvmalloc_p(0x1000, &vbox_phys);
|
||||
caps->header.size = sizeof(struct vbox_guest_caps);
|
||||
caps->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
caps->header.requestType = VMM_ReportGuestCapabilities;
|
||||
caps->header.rc = 0;
|
||||
caps->header.reserved1 = 0;
|
||||
caps->header.reserved2 = 0;
|
||||
caps->caps = VMMCAP_Graphics | (args_present("novboxseamless") ? 0 : VMMCAP_SeamlessMode);
|
||||
outportl(vbox_port, vbox_phys);
|
||||
|
||||
vbox_irq_ack = (void*)kvmalloc_p(0x1000, &vbox_phys_ack);
|
||||
vbox_irq_ack->header.size = sizeof(struct vbox_ack_events);
|
||||
vbox_irq_ack->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_irq_ack->header.requestType = VMM_AcknowledgeEvents;
|
||||
vbox_irq_ack->header.rc = 0;
|
||||
vbox_irq_ack->header.reserved1 = 0;
|
||||
vbox_irq_ack->header.reserved2 = 0;
|
||||
vbox_irq_ack->events = 0;
|
||||
|
||||
|
||||
vbox_disp = (void*)kvmalloc_p(0x1000, &vbox_phys_disp);
|
||||
vbox_disp->header.size = sizeof(struct vbox_display_change);
|
||||
vbox_disp->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_disp->header.requestType = VMM_GetDisplayChangeRequest;
|
||||
vbox_disp->header.rc = 0;
|
||||
vbox_disp->header.reserved1 = 0;
|
||||
vbox_disp->header.reserved2 = 0;
|
||||
vbox_disp->xres = 0;
|
||||
vbox_disp->yres = 0;
|
||||
vbox_disp->bpp = 0;
|
||||
vbox_disp->eventack = 1;
|
||||
|
||||
vbox_m = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse);
|
||||
mouse_on_off(VBOX_MOUSE_ON);
|
||||
|
||||
/* For use with later receives */
|
||||
vbox_mg = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse_get);
|
||||
vbox_mg->header.size = sizeof(struct vbox_mouse);
|
||||
vbox_mg->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_mg->header.requestType = VMM_GetMouseState;
|
||||
vbox_mg->header.rc = 0;
|
||||
vbox_mg->header.reserved1 = 0;
|
||||
vbox_mg->header.reserved2 = 0;
|
||||
|
||||
if (!args_present("novboxpointer")) {
|
||||
vbox_pointershape = (void*)kvmalloc_p(0x4000, &vbox_phys_pointershape);
|
||||
|
||||
if (vbox_pointershape) {
|
||||
//fprintf(&vb, "Got a valid set of pages to load up a cursor.\n");
|
||||
vbox_pointershape->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_pointershape->header.requestType = VMM_SetPointerShape;
|
||||
vbox_pointershape->header.rc = 0;
|
||||
vbox_pointershape->header.reserved1 = 0;
|
||||
vbox_pointershape->header.reserved2 = 0;
|
||||
vbox_pointershape->flags = (1 << 0) | (1 << 1) | (1 << 2);
|
||||
vbox_pointershape->xHot = 26;
|
||||
vbox_pointershape->yHot = 26;
|
||||
vbox_pointershape->width = 48;
|
||||
vbox_pointershape->height = 48;
|
||||
|
||||
unsigned int mask_bytes = ((vbox_pointershape->width + 7) / 8) * vbox_pointershape->height;
|
||||
|
||||
for (uint32_t i = 0; i < mask_bytes; ++i) {
|
||||
vbox_pointershape->data[i] = 0x00;
|
||||
}
|
||||
|
||||
while (mask_bytes & 3) {
|
||||
mask_bytes++;
|
||||
}
|
||||
int base = mask_bytes;
|
||||
//fprintf(&vb, "mask_bytes = %d\n", mask_bytes);
|
||||
|
||||
vbox_pointershape->header.size = sizeof(struct vbox_pointershape) + (48*48*4)+mask_bytes; /* update later */
|
||||
|
||||
for (int i = 0; i < 48 * 48; ++i) {
|
||||
vbox_pointershape->data[base+i*4] = 0x00; /* blue */
|
||||
vbox_pointershape->data[base+i*4+1] = 0x00; /* red */
|
||||
vbox_pointershape->data[base+i*4+2] = 0x00; /* green */
|
||||
vbox_pointershape->data[base+i*4+3] = 0x00; /* alpha */
|
||||
}
|
||||
outportl(vbox_port, vbox_phys_pointershape);
|
||||
|
||||
if (vbox_pointershape->header.rc < 0) {
|
||||
//fprintf(&vb, "Bad response code: -%d\n", -vbox_pointershape->header.rc);
|
||||
} else {
|
||||
/* Success, let's install the device file */
|
||||
//fprintf(&vb, "Successfully initialized cursor, going to allow compositor to set it.\n");
|
||||
pointer_pipe = malloc(sizeof(fs_node_t));
|
||||
memset(pointer_pipe, 0, sizeof(fs_node_t));
|
||||
pointer_pipe->mask = 0666;
|
||||
pointer_pipe->flags = FS_CHARDEVICE;
|
||||
pointer_pipe->write = write_pointer;
|
||||
|
||||
vfs_mount("/dev/vboxpointer", pointer_pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!args_present("novboxseamless")) {
|
||||
vbox_visibleregion = (void*)kvmalloc_p(0x1000, &vbox_phys_visibleregion);
|
||||
vbox_visibleregion->header.size = sizeof(struct vbox_header) + sizeof(uint32_t) + sizeof(int32_t) * 4; /* TODO + more for additional rects? */
|
||||
vbox_visibleregion->header.version = VBOX_REQUEST_HEADER_VERSION;
|
||||
vbox_visibleregion->header.requestType = VMM_VideoSetVisibleRegion;
|
||||
vbox_visibleregion->header.rc = 0;
|
||||
vbox_visibleregion->header.reserved1 = 0;
|
||||
vbox_visibleregion->header.reserved2 = 0;
|
||||
vbox_visibleregion->count = 1;
|
||||
vbox_visibleregion->rect[0].xLeft = 0;
|
||||
vbox_visibleregion->rect[0].yTop = 0;
|
||||
vbox_visibleregion->rect[0].xRight = 1440;
|
||||
vbox_visibleregion->rect[0].yBottom = 900;
|
||||
outportl(vbox_port, vbox_phys_visibleregion);
|
||||
|
||||
rect_pipe = malloc(sizeof(fs_node_t));
|
||||
memset(rect_pipe, 0, sizeof(fs_node_t));
|
||||
rect_pipe->mask = 0666;
|
||||
rect_pipe->flags = FS_CHARDEVICE;
|
||||
rect_pipe->write = write_rectpipe;
|
||||
|
||||
vfs_mount("/dev/vboxrects", rect_pipe);
|
||||
}
|
||||
|
||||
/* device memory region mapping? */
|
||||
{
|
||||
uintptr_t t = pci_read_field(vbox_device, PCI_BAR1, 4);
|
||||
//fprintf(&vb, "mapping vmm_dev = 0x%x\n", t);
|
||||
if (t > 0) {
|
||||
vbox_vmmdev = mmu_map_from_physical(t & 0xFFFFFFF0);
|
||||
printf("Setting vbox mem device at %p\n", (void*)vbox_vmmdev);
|
||||
}
|
||||
}
|
||||
|
||||
vbox_vmmdev[3] = 0xFFFFFFFF; /* Enable all for now */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Module metadata = {
|
||||
.name = "vbox",
|
||||
.init = vbox_install,
|
||||
.fini = fini,
|
||||
};
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <kernel/mouse.h>
|
||||
#include <kernel/time.h>
|
||||
#include <kernel/args.h>
|
||||
#include <kernel/module.h>
|
||||
#include <kernel/arch/x86_64/ports.h>
|
||||
|
||||
#define VMWARE_MAGIC 0x564D5868 /* hXMV */
|
||||
@ -484,32 +485,42 @@ static int ioctl_mouse(fs_node_t * node, unsigned long request, void * argp) {
|
||||
}
|
||||
}
|
||||
|
||||
void vmware_initialize(void) {
|
||||
if (detect_device()) {
|
||||
static int vmware_initialize(int argc, char * argv[]) {
|
||||
if (!detect_device()) return -ENODEV;
|
||||
|
||||
mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
|
||||
vfs_mount("/dev/vmmouse", mouse_pipe);
|
||||
vfs_mount("/dev/vmmouse", mouse_pipe);
|
||||
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
mouse_pipe->ioctl = ioctl_mouse;
|
||||
mouse_pipe->flags = FS_CHARDEVICE;
|
||||
mouse_pipe->ioctl = ioctl_mouse;
|
||||
|
||||
/*
|
||||
* We have a hack in the PS/2 mouse driver that lets us
|
||||
* take over for the normal mouse driver and essential
|
||||
* intercept the interrputs when they are valid.
|
||||
*/
|
||||
ps2_mouse_alternate = vmware_mouse;
|
||||
/*
|
||||
* We have a hack in the PS/2 mouse driver that lets us
|
||||
* take over for the normal mouse driver and essential
|
||||
* intercept the interrputs when they are valid.
|
||||
*/
|
||||
ps2_mouse_alternate = vmware_mouse;
|
||||
|
||||
mouse_absolute();
|
||||
|
||||
#if 0
|
||||
if (lfb_driver_name && !strcmp(lfb_driver_name, "vmware") && !args_present("novmwareresset")) {
|
||||
create_kernel_tasklet(vmware_resize, "[vmware]", NULL);
|
||||
}
|
||||
#endif
|
||||
mouse_absolute();
|
||||
|
||||
#if 0
|
||||
if (lfb_driver_name && !strcmp(lfb_driver_name, "vmware") && !args_present("novmwareresset")) {
|
||||
create_kernel_tasklet(vmware_resize, "[vmware]", NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Module metadata = {
|
||||
.name = "vmware",
|
||||
.init = vmware_initialize,
|
||||
.fini = fini,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user