diff options
41 files changed, 88 insertions, 2373 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/main.yml index cb9660e..3984c6e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/main.yml @@ -1,9 +1,23 @@ -name: Project build and test +name: lint, build, test, release on: push jobs: - build-and-test: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install + run: sudo apt-get update && sudo apt-get install -y build-essential ctags ccache clang-tidy-11 clang-format-11 + - name: Generate linting instructions + run: sh run sync + - name: Lint + run: sh run lint + + build-test-release: + needs: [lint] runs-on: ubuntu-latest steps: @@ -16,7 +30,7 @@ jobs: uses: actions/cache@v1 with: path: cross - key: toolchain + key: cached-toolchain - name: Build cross compiler if: steps.cache-cross.outputs.cache-hit != 'true' run: sh run cross -y @@ -9,7 +9,7 @@ endef PREPROCESSOR_FLAGS = $(foreach flag, $(ALL_PREPROCESSOR_FLAGS), $(call PREPROCESSOR_FLAG_TEMPLATE,$(flag))) -CFLAGS_WARNINGS = -Wall -Wextra -Werror -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wnested-externs -Wformat=2 -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wswitch-default -Wswitch-enum -Wlogical-op -Wunreachable-code -Wundef -Wold-style-definition -Wvla -Winline -pedantic-errors +CFLAGS_WARNINGS = -Wall -Wextra -Werror -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wnested-externs -Wformat=2 -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wswitch-default -Wswitch-enum -Wunreachable-code -Wundef -Wold-style-definition -Wvla -Winline -pedantic-errors CFLAGS_DEFAULT = $(CFLAGS_WARNINGS) -std=c99 -m32 -nostdlib -nostdinc -fno-builtin -fno-profile-generate -fno-omit-frame-pointer -fno-common -fno-asynchronous-unwind-tables -mno-red-zone -mno-80387 -mno-mmx -mno-sse -mno-sse2 $(CONFIG_OPTIMIZATION) $(CONFIG_EXTRA_CFLAGS) $(PREPROCESSOR_FLAGS) CC = $(CONFIG_CACHE) $(PWD)/cross/opt/bin/i686-elf-gcc diff --git a/kernel/drivers/acpi.c b/kernel/drivers/acpi.c index 6860a43..13c132c 100644 --- a/kernel/drivers/acpi.c +++ b/kernel/drivers/acpi.c @@ -1,13 +1,13 @@ // MIT License, Copyright (c) 2020 Marvin Borner -#include <drivers/acpi.h> #include <assert.h> -#include <drivers/cpu.h> #include <def.h> +#include <drivers/acpi.h> +#include <drivers/cpu.h> #include <mem.h> #include <print.h> -int check_sdt(struct sdt_header *header) +static int check_sdt(struct sdt_header *header) { u8 sum = 0; @@ -17,7 +17,7 @@ int check_sdt(struct sdt_header *header) return sum == 0; } -int check_sdp(struct sdp_header *header) +static int check_sdp(struct sdp_header *header) { u8 sum = 0; @@ -27,7 +27,7 @@ int check_sdp(struct sdp_header *header) return sum == 0; } -struct rsdp *find_rsdp(void) +static struct rsdp *find_rsdp(void) { // Main BIOS area for (int i = 0xe0000; i < 0xfffff; i++) { @@ -45,7 +45,7 @@ struct rsdp *find_rsdp(void) return NULL; } -void *find_sdt(struct rsdt *rsdt, const char *signature) +static void *find_sdt(struct rsdt *rsdt, const char *signature) { u32 entries = (rsdt->header.length - sizeof(rsdt->header)) / 4; diff --git a/kernel/drivers/cpu.c b/kernel/drivers/cpu.c index 8927d1d..8694fc2 100644 --- a/kernel/drivers/cpu.c +++ b/kernel/drivers/cpu.c @@ -2,8 +2,8 @@ // This file is a wrapper around some CPU asm calls #include <assert.h> -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> #include <mem.h> #include <print.h> diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index e9ab0ce..39a59a0 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -2,14 +2,14 @@ // TODO: Remove some magic numbers #include <assert.h> -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> #include <drivers/interrupts.h> +#include <drivers/serial.h> #include <mem.h> #include <mm.h> #include <print.h> #include <proc.h> -#include <drivers/serial.h> /** * IDT diff --git a/kernel/drivers/mbr.c b/kernel/drivers/mbr.c index c9eba15..d5f7a40 100644 --- a/kernel/drivers/mbr.c +++ b/kernel/drivers/mbr.c @@ -1,9 +1,9 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include <def.h> -#include <fs.h> #include <drivers/ide.h> #include <drivers/mbr.h> +#include <fs.h> #include <mem.h> #include <print.h> #include <str.h> diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c index 55806c2..0aab8e5 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci.c @@ -2,10 +2,10 @@ // Uses parts of the ToAruOS Project, released under the terms of the NCSA // Copyright (C) 2011-2018 K. Lange -#include <drivers/cpu.h> #include <def.h> -#include <mem.h> +#include <drivers/cpu.h> #include <drivers/pci.h> +#include <mem.h> CLEAR void pci_write_field(u32 device, int field, u32 value) { diff --git a/kernel/drivers/ps2/keyboard.c b/kernel/drivers/ps2/keyboard.c index bddb280..bf1a520 100644 --- a/kernel/drivers/ps2/keyboard.c +++ b/kernel/drivers/ps2/keyboard.c @@ -1,14 +1,14 @@ // MIT License, Copyright (c) 2020 Marvin Borner -#include <drivers/cpu.h> #include <def.h> -#include <errno.h> +#include <drivers/cpu.h> #include <drivers/interrupts.h> +#include <drivers/ps2.h> +#include <errno.h> #include <io.h> #include <mem.h> #include <print.h> #include <proc.h> -#include <drivers/ps2.h> #include <stack.h> #include <str.h> #include <sys.h> diff --git a/kernel/drivers/ps2/mouse.c b/kernel/drivers/ps2/mouse.c index 2942e34..680183d 100644 --- a/kernel/drivers/ps2/mouse.c +++ b/kernel/drivers/ps2/mouse.c @@ -2,13 +2,13 @@ #include <assert.h> #include <drivers/cpu.h> -#include <errno.h> #include <drivers/interrupts.h> +#include <drivers/ps2.h> +#include <errno.h> #include <io.h> #include <mem.h> #include <print.h> #include <proc.h> -#include <drivers/ps2.h> #include <stack.h> #include <str.h> #include <sys.h> diff --git a/kernel/drivers/ps2/ps2.c b/kernel/drivers/ps2/ps2.c index f8d849b..0206892 100644 --- a/kernel/drivers/ps2/ps2.c +++ b/kernel/drivers/ps2/ps2.c @@ -1,10 +1,10 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include <assert.h> -#include <drivers/cpu.h> #include <def.h> -#include <print.h> +#include <drivers/cpu.h> #include <drivers/ps2.h> +#include <print.h> #define PS2_TIMEOUT 100 diff --git a/kernel/drivers/rtc.c b/kernel/drivers/rtc.c index 63d9461..b67829e 100644 --- a/kernel/drivers/rtc.c +++ b/kernel/drivers/rtc.c @@ -1,12 +1,12 @@ // MIT License, Copyright (c) 2021 Marvin Borner -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> +#include <drivers/rtc.h> +#include <drivers/timer.h> #include <fs.h> #include <mem.h> -#include <drivers/rtc.h> #include <str.h> -#include <drivers/timer.h> static u8 rtc_busy(void) { diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c deleted file mode 100644 index 8e7bc88..0000000 --- a/kernel/drivers/rtl8139.c +++ /dev/null @@ -1,177 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner -// Uses parts of the ToAruOS Project, released under the terms of the NCSA -// Copyright (C) 2011-2018 K. Lange - -#include <def.h> -#include <drivers/cpu.h> -#include <drivers/interrupts.h> -#include <drivers/pci.h> -#include <drivers/rtl8139.h> -#include <mem.h> -#include <net.h> -#include <print.h> - -static int rtl_irq = 0; -static u8 mac[6] = { 0 }; -static u8 *last_packet = NULL; -static u8 *rtl_rx_buffer = NULL; -static u32 rtl_device_pci = 0; -static u32 rtl_iobase = 0; -static u32 cur_rx = 0; - -u8 *rtl8139_get_mac(void) -{ - if (!rtl_device_pci) - return NULL; - - return mac; -} - -static void rtl8139_receive_packet(void) -{ - while ((inb(rtl_iobase + RTL_PORT_CMD) & 0x01) == 0) { - int offset = cur_rx % 0x2000; - - u32 *buf_start = (u32 *)((u32)rtl_rx_buffer + offset); - u32 rx_status = buf_start[0]; - u32 rx_size = rx_status >> 16; - - if (rx_status & (0x0020 | 0x0010 | 0x0004 | 0x0002)) { - print("RX Error\n"); - } else { - u8 *buf_8 = (u8 *)&(buf_start[1]); - - last_packet = malloc(rx_size); - - u32 packet_end = (u32)buf_8 + rx_size; - if (packet_end > (u32)rtl_rx_buffer + 0x2000) { - u32 s = ((u32)rtl_rx_buffer + 0x2000) - (u32)buf_8; - memcpy(last_packet, buf_8, s); - memcpy((void *)((u32)last_packet + s), rtl_rx_buffer, rx_size - s); - } else { - memcpy(last_packet, buf_8, rx_size); - } - - u16 *t = (u16 *)(rtl_rx_buffer + cur_rx); - ethernet_handle_packet((struct ethernet_packet *)last_packet, *(t + 1)); - } - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - outw(rtl_iobase + RTL_PORT_RXPTR, cur_rx - 16); - } -} - -static u8 tsad_array[4] = { 0x20, 0x24, 0x28, 0x2C }; -static u8 tsd_array[4] = { 0x10, 0x14, 0x18, 0x1C }; -static u8 tx_current = 0; -void rtl8139_send_packet(void *data, u32 len) -{ - if (!rtl_device_pci) - return; - - outl(rtl_iobase + tsad_array[tx_current], (u32)data); - outl(rtl_iobase + tsd_array[tx_current++], len); - if (tx_current > 3) - tx_current = 0; -} - -static void rtl8139_find(u32 device, u16 vendor_id, u16 device_id, void *extra) -{ - if ((vendor_id == 0x10ec) && (device_id == 0x8139)) - *((u32 *)extra) = device; -} - -static void rtl8139_irq_handler(struct regs *r) -{ - UNUSED(r); - u16 status = inw(rtl_iobase + RTL_PORT_ISR); - if (!status) - return; - outw(rtl_iobase + RTL_PORT_ISR, status); - - if (status & 0x01 || status & 0x02) - rtl8139_receive_packet(); -} - -static void rtl8139_init(void) -{ - if (!rtl_device_pci) - return; - - u16 command_reg = (u16)pci_read_field(rtl_device_pci, PCI_COMMAND, 4); - if ((command_reg & (1 << 2)) == 0) { - command_reg |= (1 << 2); - pci_write_field(rtl_device_pci, PCI_COMMAND, command_reg); - } - - rtl_irq = pci_get_interrupt(rtl_device_pci); - irq_install_handler(rtl_irq, rtl8139_irq_handler); - - u32 rtl_bar0 = pci_read_field(rtl_device_pci, PCI_BAR0, 4); - /* u32 rtl_bar1 = pci_read_field(rtl_device_pci, PCI_BAR1, 4); */ - rtl_iobase = 0; - - if (rtl_bar0 & 0x00000001) - rtl_iobase = rtl_bar0 & 0xFFFFFFFC; - - // Get mac address - for (int i = 0; i < 6; ++i) - mac[i] = inb(rtl_iobase + RTL_PORT_MAC + i); - printf("Mac address: %x:%x:%x:%x:%x:%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - // Activate - outb(rtl_iobase + RTL_PORT_CONFIG, 0x0); - - // Reset - outb((u16)(rtl_iobase + RTL_PORT_CMD), 0x10); - while ((inb(rtl_iobase + RTL_PORT_CMD) & 0x10) != 0) - ; - - // Set receive buffer - rtl_rx_buffer = (u8 *)malloc(0x3000); - memset(rtl_rx_buffer, 0, 0x3000); - outl(rtl_iobase + RTL_PORT_RBSTART, (u32)rtl_rx_buffer); - - // Enable IRQs - outw(rtl_iobase + RTL_PORT_IMR, 0x8000 | /* PCI error */ - 0x4000 | /* PCS timeout */ - 0x40 | /* Rx FIFO over */ - 0x20 | /* Rx underrun */ - 0x10 | /* Rx overflow */ - 0x08 | /* Tx error */ - 0x04 | /* Tx okay */ - 0x02 | /* Rx error */ - 0x01 /* Rx okay */ - ); - - // Configure transmit - outl(rtl_iobase + RTL_PORT_TCR, 0); - - // Configure receive - outl(rtl_iobase + RTL_PORT_RCR, (0) | /* 8K receive */ - 0x08 | /* broadcast */ - 0x01 /* all physical */ - ); - - // Enable receive and transmit - outb(rtl_iobase + RTL_PORT_CMD, 0x08 | 0x04); - - // Reset rx statistics - outl(rtl_iobase + RTL_PORT_RXMISS, 0); -} - -int rtl8139_installed(void) -{ - return rtl_device_pci != 0; -} - -int rtl8139_install(void) -{ - pci_scan(&rtl8139_find, -1, &rtl_device_pci); - - if (rtl_device_pci) { - print("Found rtl8139 card\n"); - rtl8139_init(); - } - return rtl_device_pci; -} diff --git a/kernel/drivers/serial.c b/kernel/drivers/serial.c index 95ac02d..281772d 100644 --- a/kernel/drivers/serial.c +++ b/kernel/drivers/serial.c @@ -1,8 +1,8 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <assert.h> -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> #include <drivers/serial.h> #include <str.h> diff --git a/kernel/drivers/timer.c b/kernel/drivers/timer.c index c586088..3ddc229 100644 --- a/kernel/drivers/timer.c +++ b/kernel/drivers/timer.c @@ -1,13 +1,13 @@ // MIT License, Copyright (c) 2020 Marvin Borner -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> #include <drivers/interrupts.h> +#include <drivers/rtc.h> +#include <drivers/timer.h> #include <io.h> #include <mem.h> #include <proc.h> -#include <drivers/rtc.h> -#include <drivers/timer.h> static u32 timer_ticks = 0; PROTECTED static u8 call_scheduler = 0; diff --git a/kernel/drivers/vmware.c b/kernel/drivers/vmware.c index 6f95d02..169865f 100644 --- a/kernel/drivers/vmware.c +++ b/kernel/drivers/vmware.c @@ -3,12 +3,12 @@ #include <def.h> #include <drivers/interrupts.h> +#include <drivers/ps2.h> +#include <drivers/vmware.h> #include <io.h> #include <mem.h> #include <print.h> -#include <drivers/ps2.h> #include <stack.h> -#include <drivers/vmware.h> #define VMWARE_CMD_VERSION 0x0a diff --git a/kernel/features/bus.c b/kernel/features/bus.c index d58cee3..3757a3a 100644 --- a/kernel/features/bus.c +++ b/kernel/features/bus.c @@ -2,9 +2,9 @@ #include <assert.h> #include <bus.h> -#include <drivers/cpu.h> #include <crypto.h> #include <def.h> +#include <drivers/cpu.h> #include <errno.h> #include <io.h> #include <list.h> diff --git a/kernel/features/fs.c b/kernel/features/fs.c index c5ebfcd..7e79a42 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -1,13 +1,13 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <assert.h> -#include <drivers/cpu.h> #include <crypto.h> #include <def.h> -#include <errno.h> -#include <fs.h> +#include <drivers/cpu.h> #include <drivers/ide.h> #include <drivers/mbr.h> +#include <errno.h> +#include <fs.h> #include <mem.h> #include <mm.h> #include <print.h> diff --git a/kernel/features/logger.c b/kernel/features/logger.c index 23efa93..fd5d730 100644 --- a/kernel/features/logger.c +++ b/kernel/features/logger.c @@ -1,13 +1,13 @@ // MIT License, Copyright (c) 2021 Marvin Borner -#include <drivers/cpu.h> #include <def.h> +#include <drivers/cpu.h> +#include <drivers/serial.h> #include <errno.h> #include <io.h> #include <logger.h> #include <mem.h> #include <print.h> -#include <drivers/serial.h> static res logger_write(const void *buf, u32 offset, u32 count) { diff --git a/kernel/features/net.c b/kernel/features/net.c deleted file mode 100644 index 9e40ea6..0000000 --- a/kernel/features/net.c +++ /dev/null @@ -1,865 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#include <assert.h> -#include <drivers/cpu.h> -#include <def.h> -#include <list.h> -#include <mem.h> -#include <net.h> -#include <drivers/pci.h> -#include <print.h> -#include <rand.h> -#include <drivers/rtl8139.h> -#include <socket.h> -#include <str.h> -#include <drivers/timer.h> - -static u32 current_ip_addr = 0; -static u32 gateway_addr = 0; -static u32 subnet_mask = 0; -static u8 gateway_mac[6] = { 0 }; - -static struct list *tcp_sockets = NULL; -static struct list *udp_sockets = NULL; - -/** - * Socket functions - */ - -static struct list *socket_list(enum socket_type type) -{ - struct list *list = NULL; - if (type == S_TCP) - list = tcp_sockets; - else if (type == S_UDP) - list = udp_sockets; - return list; -} - -static struct socket *socket_get(enum socket_type type, u32 port) -{ - struct list *list = socket_list(type); - - if (!list || !list->head || !port) - return NULL; - - struct node *iterator = list->head; - while (iterator != NULL && iterator->data != NULL) { - if (((struct socket *)iterator->data)->src_port == port) - return iterator->data; - iterator = iterator->next; - } - - return NULL; -} - -static struct socket *socket_new(enum socket_type type) -{ - struct list *list = socket_list(type); - - if (!list) - return NULL; - - struct socket *socket = malloc(sizeof(*socket)); - memset(socket, 0, sizeof(*socket)); - if (!list_add(list, socket)) - return NULL; - - return socket; -} - -static int socket_close(struct socket *socket) -{ - if (!socket) - return 0; - - struct list *list = socket_list(socket->type); - - if (!list) - return 0; - - struct node *iterator = list->head; - while (iterator != NULL && iterator->data != NULL) { - if (iterator->data == socket) - list_remove(list, iterator); - iterator = iterator->next; - } - - socket->state = S_CLOSED; - free(socket); - - return 1; -} - -/** - * Helper functions - */ - -static u16 next_port(void) -{ - static u16 port = 49152; - return port++; -} - -static int same_net(u32 ip_addr) -{ - if (gateway_addr && ip_addr > 1) - return (ip_addr & subnet_mask) == (gateway_addr & subnet_mask); - else - return 0; -} - -static u16 ip_calculate_checksum(struct ip_packet *packet) -{ - int array_size = sizeof(*packet) / 2; - u16 *array = (u16 *)packet; - u32 sum = 0; - for (int i = 0; i < array_size; i++) { - sum += (u32)htons(array[i]); - } - u32 carry = sum >> 16; - sum = sum & 0x0000ffff; - sum = sum + carry; - u16 ret = (u16)~sum; - return ret; -} - -static u16 tcp_calculate_checksum(struct tcp_packet *packet, struct tcp_pseudo_header *header, - void *data, u32 len) -{ - u32 sum = 0; - u16 *s = (u16 *)header; - - // TODO: Checksums for options? - for (int i = 0; i < 6; i++) { - sum += (u32)ntohs(s[i]); - if (sum > 0xffff) { - sum = (sum >> 16) + (sum & 0xffff); - } - } - - s = (u16 *)packet; - for (int i = 0; i < 10; i++) { - sum += (u32)ntohs(s[i]); - if (sum > 0xffff) { - sum = (sum >> 16) + (sum & 0xffff); - } - } - - u16 d_words = (u16)(len / 2); - - s = (u16 *)data; - for (u32 i = 0; i < d_words; ++i) { - sum += (u32)ntohs(s[i]); - if (sum > 0xffff) { - sum = (sum >> 16) + (sum & 0xffff); - } - } - - if (d_words * 2 != len) { - u8 *t = (u8 *)data; - u8 tmp[2]; - tmp[0] = t[d_words * sizeof(u16)]; - tmp[1] = 0; - - u16 *f = (u16 *)tmp; - - sum += (u32)ntohs(f[0]); - if (sum > 0xffff) { - sum = (sum >> 16) + (sum & 0xffff); - } - } - - return ~(sum & 0xffff) & 0xffff; -} - -static u16 icmp_calculate_checksum(struct icmp_packet *packet) -{ - u32 sum = 0; - u16 *s = (u16 *)packet; - - for (int i = 0; i < 5; i++) - sum += s[i]; - - if (sum > 0xffff) - sum = (sum >> 16) + (sum & 0xffff); - - return (u16)~sum; -} - -static void *dhcp_get_options(struct dhcp_packet *packet, u8 type) -{ - u8 *options = packet->options + 4; - u8 curr_type = 0; - while ((curr_type = *options) != 0xff) { - u8 len = *(options + 1); - if (curr_type == type) { - void *ret = malloc(len); - memcpy(ret, options + 2, len); - return ret; - } - options += (2 + len); - } - return NULL; -} - -/** - * Requests - */ - -static void ethernet_send_packet(u8 *dst, u8 *data, int len, int prot) -{ - print("Ethernet send packet\n"); - struct ethernet_packet *packet = malloc(sizeof(*packet) + (u32)len); - memcpy(packet->src, rtl8139_get_mac(), 6); - memcpy(packet->dst, dst, 6); - memcpy(packet->data, data, (u32)len); - packet->type = (u16)htons(prot); - rtl8139_send_packet(packet, sizeof(*packet) + (u32)len); - free(packet); -} - -static u8 broadcast_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static void arp_send_packet(u8 *dst_mac, u32 dst_protocol_addr, u8 opcode) -{ - print("ARP send packet\n"); - struct arp_packet *packet = malloc(sizeof(*packet)); - - memcpy(packet->src_mac, rtl8139_get_mac(), 6); - packet->src_protocol_addr = htonl(current_ip_addr); - memcpy(packet->dst_mac, dst_mac, 6); - packet->dst_protocol_addr = htonl(dst_protocol_addr); - packet->opcode = (u16)htons(opcode); - packet->hardware_addr_len = 6; - packet->protocol_addr_len = 4; - packet->hardware_type = htons(HARDWARE_TYPE_ETHERNET); - packet->protocol = htons(ETHERNET_TYPE_IP4); - - ethernet_send_packet(broadcast_mac, (u8 *)packet, sizeof(*packet), ETHERNET_TYPE_ARP); - free(packet); -} - -static int arp_lookup(u8 *ret_hardware_addr, u32 ip_addr); -static void ip_send_packet(u32 dst, void *data, int len, u8 prot) -{ - print("IP send packet\n"); - struct ip_packet *packet = malloc(sizeof(*packet) + (u32)len); - memset(packet, 0, sizeof(*packet)); - packet->version_ihl = ((0x4 << 4) | (0x5 << 0)); - packet->length = (u16)sizeof(*packet) + (u16)len; - packet->id = htons(1); // TODO: IP fragmentation - /* packet->flags_fragment = htons(1); */ - packet->ttl = 64; - packet->protocol = prot; - packet->src = htonl(current_ip_addr); - packet->dst = htonl(dst); - packet->length = (u16)htons(sizeof(*packet) + (u32)len); - packet->checksum = (u16)htons(ip_calculate_checksum(packet)); - - if (data) - memcpy(packet->data, data, (u32)len); - - u8 zero_hardware_addr[] = { 0, 0, 0, 0, 0, 0 }; - u8 dst_mac[6]; - if (same_net(dst)) { - scheduler_disable(); - sti(); - int arp_sent = 3; - while (!arp_lookup(dst_mac, dst)) { - if (arp_sent) { - arp_sent--; - arp_send_packet(zero_hardware_addr, dst, ARP_REQUEST); - } else { - break; - } - } - cli(); - scheduler_enable(); - } else { - memcpy(dst_mac, gateway_mac, 6); - } - - printf("Destination: %x:%x:%x:%x:%x:%x\n", dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], - dst_mac[4], dst_mac[5]); - ethernet_send_packet(dst_mac, (u8 *)packet, htons(packet->length), ETHERNET_TYPE_IP4); - - free(packet); -} - -static void udp_send_packet(struct socket *socket, void *data, int len) -{ - print("UDP send packet\n"); - if (!socket || socket->state == S_FAILED) - return; - - u32 length = sizeof(struct udp_packet) + (u32)len; - struct udp_packet *packet = malloc(length); - memset(packet, 0, sizeof(*packet)); - packet->src_port = (u16)htons(socket->src_port); - packet->dst_port = (u16)htons(socket->dst_port); - packet->length = (u16)htons(length); - packet->checksum = 0; // Optional - - if (data) - memcpy(packet->data, data, (u32)len); - - ip_send_packet(socket->ip_addr, packet, (int)length, IP_PROT_UDP); - free(packet); -} - -//void tcp_send_packet(u32 dst, u16 src_port, u16 dst_port, u16 flags, void *data, int len) -static void tcp_send_packet(struct socket *socket, u16 flags, void *data, int len) -{ - print("TCP send packet\n"); - - if (!socket || socket->state == S_FAILED) - return; - - u32 length = sizeof(struct tcp_packet) + (u32)len; - struct tcp_packet *packet = malloc(length); - memset(packet, 0, sizeof(*packet)); - packet->src_port = (u16)htons(socket->src_port); - packet->dst_port = (u16)htons(socket->dst_port); - packet->seq_number = htonl(socket->prot.tcp.seq_no); - packet->ack_number = (flags & TCP_FLAG_ACK) ? htonl(socket->prot.tcp.ack_no) : 0; - packet->flags = (u16)htons(0x5000 ^ (flags & 0xff)); - packet->window_size = htons(U16_MAX); // TODO: Support TCP windows - packet->urgent = 0; - packet->checksum = 0; // Later - - if (data) - memcpy(packet->data, data, (u32)len); - - struct tcp_pseudo_header checksum_hd = { - .src = htonl(current_ip_addr), - .dst = htonl(socket->ip_addr), - .zeros = 0, - .protocol = 6, - .tcp_len = (u16)htons(length), - }; - u16 checksum = tcp_calculate_checksum(packet, &checksum_hd, data, - length - ((u32)htons(packet->flags) >> 12) * 4); - packet->checksum = (u16)htons(checksum); - - ip_send_packet(socket->ip_addr, packet, (int)length, IP_PROT_TCP); - free(packet); -} - -static void dhcp_make_packet(struct dhcp_packet *packet, u8 msg_type); -static void dhcp_request(void) -{ - struct socket *socket = net_open(S_UDP); - if (!socket || !net_connect(socket, 0xffffffff, 67)) - return; - - struct dhcp_packet *packet = malloc(sizeof(*packet)); - memset(packet, 0, sizeof(*packet)); - dhcp_make_packet(packet, 3); - net_send(socket, packet, sizeof(*packet)); - free(packet); -} - -/** - * Responses - */ - -static void icmp_handle_packet(struct icmp_packet *request_packet, u32 dst) -{ - struct icmp_packet *packet = malloc(sizeof(*packet)); - memset(packet, 0, sizeof(*packet)); - packet->type = 0; // Ping reponse - packet->version = 0; - packet->checksum = 0; - packet->identifier = request_packet->identifier; - packet->sequence = request_packet->sequence; - packet->checksum = icmp_calculate_checksum(packet); - ip_send_packet(dst, packet, sizeof(*packet), IP_PROT_ICMP); - free(packet); -} - -static void dhcp_handle_packet(struct dhcp_packet *packet) -{ - print("DHCP!\n"); - if (packet->op == DHCP_REPLY && htonl(packet->xid) == DHCP_TRANSACTION_IDENTIFIER) { - u8 *type = dhcp_get_options(packet, 53); - if (*type == 2) { // Offer - print("DHCP offer\n"); - dhcp_request(); - } else if (*type == 5) { // ACK - current_ip_addr = htonl(packet->your_ip); - - memcpy(&subnet_mask, dhcp_get_options(packet, 1), 4); - memcpy(&gateway_addr, dhcp_get_options(packet, 3), 4); - memcpy(gateway_mac, dhcp_get_options(packet, 3), 4); - subnet_mask = htonl(subnet_mask); - gateway_addr = htonl(gateway_addr); - - u8 zero_hardware_addr[] = { 0, 0, 0, 0, 0, 0 }; - printf("New IP: %x\n", current_ip_addr); - printf("Gateway: %x\n", gateway_addr); - if (same_net(current_ip_addr)) - arp_send_packet(zero_hardware_addr, gateway_addr, ARP_REQUEST); - /* sti(); */ - /* while (!arp_lookup(gateway_mac, gateway_addr)) */ - /* hlt(); */ - } - free(type); - } -} - -// enum tcp_state { TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECIEVED, TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, TCP_CLOSE_WAIT, TCP_CLOSING, TCP_LAST_ACK, TCP_TIME_WAIT, TCP_CLOSED }; -static void tcp_handle_packet(struct tcp_packet *packet, u32 dst, int len) -{ - printf("TCP Port: %d\n", ntohs(packet->dst_port)); - - struct socket *socket = NULL; - if (!(socket = socket_get(S_TCP, ntohs(packet->dst_port))) || socket->state == S_CLOSED || - socket->state == S_FAILED) { - print("Port isn't mapped!\n"); - return; - } - struct tcp_socket *tcp = &socket->prot.tcp; - - u32 data_length = (u32)len - (ntohs(packet->flags) >> 12) * 4; - u16 flags = (u16)ntohs(packet->flags); - - u32 recv_ack = ntohl(packet->ack_number); - u32 recv_seq = ntohl(packet->seq_number); - - // TODO: Verify checksum first, then send ACK - - if (flags & TCP_FLAG_RST) { - proc_from_pid(socket->pid)->state = PROC_RUNNING; - socket->state = S_FAILED; - tcp->state = 0; - return; - } - - // Serve - if (tcp->state == 0 && (flags & 0xff) == TCP_FLAG_SYN) { - socket->ip_addr = ntohl(dst); - socket->dst_port = ntohs(packet->src_port); - tcp->ack_no = recv_seq + 1; - tcp->seq_no = 1000; - tcp_send_packet(socket, TCP_FLAG_SYN | TCP_FLAG_ACK, NULL, 0); - tcp->state++; - return; - } else if (tcp->state == 1 && (flags & 0xff) == TCP_FLAG_ACK) { - tcp->state++; - return; - } else if (tcp->state == 2 && (flags & 0xff) == (TCP_FLAG_ACK | TCP_FLAG_PSH)) { - struct socket_data *sdata = malloc(sizeof(*sdata)); - sdata->length = data_length; - if (sdata->length) { - sdata->data = malloc(data_length); - memcpy(sdata->data, packet->data, data_length); - } else { - sdata->data = NULL; - } - list_add(socket->packets, sdata); - proc_from_pid(socket->pid)->state = PROC_RUNNING; - - tcp->ack_no += data_length; - tcp->seq_no++; - - tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0); - - socket->state = S_CONNECTED; - tcp->state++; - return; - } else if (tcp->state == 3 && (flags & 0xff) == TCP_FLAG_ACK) { - tcp->ack_no = recv_seq + 1; - tcp->seq_no = recv_ack; - - socket->state = S_CONNECTED; - tcp->state++; // ? - return; - } else if (tcp->state == 4 && (flags & 0xff) == (TCP_FLAG_ACK | TCP_FLAG_FIN)) { - tcp->ack_no = recv_seq + 1; - tcp->seq_no = recv_ack; - - tcp_send_packet(socket, TCP_FLAG_FIN | TCP_FLAG_ACK, NULL, 0); - - socket->state = S_CONNECTED; - tcp->state++; - return; - } else if (tcp->state == 5 && (flags & 0xff) == TCP_FLAG_ACK) { - proc_from_pid(socket->pid)->state = PROC_RUNNING; - - socket->state = S_CLOSED; - tcp->state = 0; - } - - // Receive - if (tcp->state == 0 && (flags & 0xff) == (TCP_FLAG_ACK | TCP_FLAG_SYN)) { - tcp->ack_no = recv_seq + 1; - tcp->seq_no = recv_ack; - - tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0); - - socket->state = S_CONNECTED; - tcp->state = 6; // TODO: TCP enum state machine - return; - } else if (tcp->state == 6 && (flags & 0xff) == TCP_FLAG_ACK) { - tcp->ack_no = recv_seq; - tcp->seq_no = recv_ack; - - socket->state = S_CONNECTED; - tcp->state++; - return; - } else if (tcp->state == 7 && flags & TCP_FLAG_ACK) { - struct socket_data *sdata = malloc(sizeof(*sdata)); - sdata->length = data_length; - if (sdata->length) { - sdata->data = malloc(data_length); - memcpy(sdata->data, packet->data, data_length); - } else { - sdata->data = NULL; - } - list_add(socket->packets, sdata); - - tcp->ack_no += data_length; - tcp->seq_no = recv_ack; - - tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0); - - socket->state = S_CONNECTED; - return; - } else if (tcp->state == 8 && (flags & 0xff) == (TCP_FLAG_ACK | TCP_FLAG_FIN)) { - tcp->ack_no = recv_seq + 1; - tcp->seq_no = recv_ack; - - tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0); - - socket->state = S_CLOSED; - tcp->state = 0; - return; - } -} - -static void udp_handle_packet(struct udp_packet *packet) -{ - printf("UDP Port: %d\n", ntohs(packet->dst_port)); - - void *data_ptr = packet->data; - - if (ntohs(packet->dst_port) == DHCP_PORT) { - dhcp_handle_packet(data_ptr); - return; - } - - struct socket *socket = NULL; - if (!(socket = socket_get(S_UDP, ntohs(packet->dst_port))) || socket->state == S_CLOSED || - socket->state == S_FAILED) { - print("Port isn't mapped!\n"); - return; - } - - struct socket_data *sdata = malloc(sizeof(*sdata)); - sdata->length = ntohs(packet->length); - if (sdata->length) { - sdata->data = malloc(sdata->length); - memcpy(sdata->data, packet->data, sdata->length); - } else { - sdata->data = NULL; - } - list_add(socket->packets, sdata); -} - -static void ip_handle_packet(struct ip_packet *packet, int len) -{ - (void)len; - switch (packet->protocol) { - case IP_PROT_ICMP: - print("ICMP Packet!\n"); - icmp_handle_packet((struct icmp_packet *)packet->data, packet->src); - break; - case IP_PROT_TCP: - print("TCP Packet!\n"); - tcp_handle_packet((struct tcp_packet *)packet->data, packet->src, - ntohs(packet->length) - sizeof(*packet)); - break; - case IP_PROT_UDP: - print("UDP Packet!\n"); - udp_handle_packet((struct udp_packet *)packet->data); - break; - default: - break; - } -} - -static struct arp_table_entry arp_table[512] = { 0 }; -static int arp_table_size = 0; -static void arp_handle_packet(struct arp_packet *packet, int len) -{ - (void)len; - u8 dst_mac[6]; - memcpy(dst_mac, packet->src_mac, 6); - u32 dst_protocol_addr = htonl(packet->src_protocol_addr); - if (ntohs(packet->opcode) == ARP_REQUEST) { - print("Got ARP request\n"); - if (htonl(packet->dst_protocol_addr) == current_ip_addr) { - print("Returning ARP request\n"); - arp_send_packet(dst_mac, dst_protocol_addr, ARP_REPLY); - } - return; - } else if (ntohs(packet->opcode) == ARP_REPLY) { - print("Got ARP reply\n"); - } else { - printf("Got unknown ARP, opcode = %d\n", packet->opcode); - return; - } - - // Store - arp_table[arp_table_size].ip_addr = dst_protocol_addr; - memcpy(&arp_table[arp_table_size].mac_addr, dst_mac, 6); - if (arp_table_size < 512) - arp_table_size++; - else - arp_table_size = 0; - - if (dst_protocol_addr == gateway_addr) - memcpy(gateway_mac, dst_mac, 6); -} - -void ethernet_handle_packet(struct ethernet_packet *packet, int len) -{ - void *data = packet->data; - int data_len = len - (int)sizeof(*packet); - if (ntohs(packet->type) == ETHERNET_TYPE_ARP) { - print("ARP PACKET\n"); - arp_handle_packet(data, data_len); - } else if (ntohs(packet->type) == ETHERNET_TYPE_IP4) { - print("IP4 PACKET\n"); - ip_handle_packet(data, data_len); - } else if (ntohs(packet->type) == ETHERNET_TYPE_IP6) { - print("IP6 PACKET\n"); - /* ip_handle_packet(data, data_len); */ - } else { - /* printf("Unknown packet %x\n", ntohs(packet->type)); */ - } -} - -/** - * DHCP - */ - -static void dhcp_make_packet(struct dhcp_packet *packet, u8 msg_type) -{ - packet->op = DHCP_REQUEST; - packet->hardware_type = HARDWARE_TYPE_ETHERNET; - packet->mac_len = 6; - packet->hops = 0; - packet->xid = htonl(DHCP_TRANSACTION_IDENTIFIER); - packet->flags = htons(0x0001); - memcpy(packet->client_mac, rtl8139_get_mac(), 6); - - // Magic Cookie - u8 *options = packet->options; - *((u32 *)(options)) = htonl(0x63825363); - options += 4; - - // First option, message type = DHCP_DISCOVER/DHCP_REQUEST - *(options++) = 53; - *(options++) = 1; - *(options++) = msg_type; - - // End - *(options++) = 0xff; -} - -static int dhcp_discover(void) -{ - print("DHCP discover\n"); - struct socket *socket = net_open(S_UDP); - if (socket) - socket->src_port = DHCP_PORT; - if (!socket || !net_connect(socket, 0xffffffff, 67)) - return 0; - - struct dhcp_packet *packet = malloc(sizeof(*packet)); - memset(packet, 0, sizeof(*packet)); - dhcp_make_packet(packet, 1); - net_send(socket, packet, sizeof(*packet)); - free(packet); - return 1; -} - -/** - * ARP - */ - -static void arp_lookup_add(u8 *ret_hardware_addr, u32 ip_addr) -{ - arp_table[arp_table_size].ip_addr = ip_addr; - memcpy(&arp_table[arp_table_size].mac_addr, ret_hardware_addr, 6); - if (arp_table_size < 512) - arp_table_size++; - else - arp_table_size = 0; -} - -static int arp_lookup(u8 *ret_hardware_addr, u32 ip_addr) -{ - for (int i = 0; i < arp_table_size; i++) { - if (arp_table[i].ip_addr == ip_addr) { - memcpy(ret_hardware_addr, &arp_table[i].mac_addr, 6); - return 1; - } - } - return 0; -} - -/** - * Wrappers - */ - -struct socket *net_open(enum socket_type type) -{ - if (!net_installed()) - return NULL; - - struct socket *socket = socket_new(type); - if (!socket) - return NULL; - - socket->type = type; - socket->state = S_OPEN; - socket->packets = list_new(); - socket->pid = proc_current()->pid; - return socket; -} - -int net_close(struct socket *socket) -{ - if (!net_installed()) - return 1; - - if (socket->state == S_CLOSING) - return 0; - - if (socket->type == S_TCP && socket->state != S_CLOSED) { - tcp_send_packet(socket, TCP_FLAG_FIN | TCP_FLAG_ACK, NULL, 0); - socket->state = S_CLOSING; - socket->prot.tcp.state++; - return 0; - } - - return socket_close(socket); -} - -int net_connect(struct socket *socket, u32 ip_addr, u16 dst_port) -{ - if (!net_installed() || socket->state != S_OPEN || !ip_addr || !dst_port) - return 0; - - socket->ip_addr = ip_addr; - socket->dst_port = dst_port; - if (!socket->src_port) - socket->src_port = next_port(); - - if (socket->type == S_TCP) { - srand(timer_get()); - socket->prot.tcp.seq_no = rand(); - socket->prot.tcp.ack_no = 0; - socket->prot.tcp.state = 0; - socket->state = S_CONNECTING; - tcp_send_packet(socket, TCP_FLAG_SYN, NULL, 0); - return 0; - } else if (socket->type == S_UDP) { - socket->state = S_CONNECTED; - return 1; - } else { - socket->state = S_FAILED; - return 0; - } -} - -void net_send(struct socket *socket, void *data, u32 len) -{ - if (!net_installed() || socket->state != S_CONNECTED) - return; - - if (socket->type == S_TCP) { - tcp_send_packet(socket, TCP_FLAG_PSH | TCP_FLAG_ACK, data, len); - socket->prot.tcp.ack_no += len; - } else if (socket->type == S_UDP) { - udp_send_packet(socket, data, len); - } else { - print("Unknown socket type!\n"); - } -} - -int net_receive(struct socket *socket, void *buf, u32 len) -{ - if (!net_installed() || !socket->packets) - return 0; - - u32 offset = 0; - struct node *iterator = socket->packets->head; - while (iterator != NULL) { - struct socket_data *sdata = iterator->data; - u32 length = sdata->length; - // TODO: Fix underflow breaking - if (offset + length < len) { - memcpy((u8 *)buf + offset, sdata->data, length); - offset += length; - } else { - break; - }; - iterator = iterator->next; - } - - return offset; -} - -/** - * Install - */ - -int net_installed(void) -{ - return rtl8139_installed() != 0; -} - -void net_install(void) -{ - if (!rtl8139_install()) - return; - - sti(); - - tcp_sockets = list_new(); - udp_sockets = list_new(); - - arp_lookup_add(broadcast_mac, 0xffffffff); - if (!dhcp_discover()) { - print("DHCP discover failed\n"); - loop(); - return; - } - - // DHCP timeout (no gateway address) - sti(); - u32 time = timer_get(); - while (!gateway_addr && timer_get() - time < 1000) - ; - - if (timer_get() - time >= 1000) { - print("DHCP timeout\n"); - loop(); - return; - } - - // ARP lookup timeout - sti(); - time = timer_get(); - while (!arp_lookup(gateway_mac, gateway_addr) && timer_get() - time < 1000) - ; - - if (timer_get() - time >= 1000) { - printf("Gateway ARP timeout at address %x\n", gateway_addr); - loop(); - return; - } -} diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 019b0ed..8fc922e 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -2,9 +2,10 @@ #include <assert.h> #include <drivers/cpu.h> +#include <drivers/gdt.h> +#include <drivers/timer.h> #include <errno.h> #include <fs.h> -#include <drivers/gdt.h> #include <load.h> #include <mem.h> #include <mm.h> @@ -12,7 +13,6 @@ #include <proc.h> #include <stack.h> #include <str.h> -#include <drivers/timer.h> #define PROC(node) ((struct proc *)node->data) diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index b376a13..9efb849 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -1,20 +1,19 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <drivers/cpu.h> +#include <drivers/interrupts.h> +#include <drivers/timer.h> #include <errno.h> #include <fs.h> -#include <drivers/interrupts.h> #include <io.h> #include <load.h> #include <mem.h> #include <mm.h> -#include <net.h> #include <print.h> #include <proc.h> #include <str.h> #include <sys.h> #include <syscall.h> -#include <drivers/timer.h> static void syscall_handler(struct regs *r) { diff --git a/kernel/inc/drivers/cpu.h b/kernel/inc/drivers/cpu.h index 7ac6074..75e0495 100644 --- a/kernel/inc/drivers/cpu.h +++ b/kernel/inc/drivers/cpu.h @@ -5,7 +5,7 @@ #include <def.h> -static inline void spinlock(u32 *ptr) +UNUSED_FUNC static inline void spinlock(u32 *ptr) { u32 prev; do diff --git a/kernel/inc/drivers/pci.h b/kernel/inc/drivers/pci.h index 9429f29..ac288c6 100644 --- a/kernel/inc/drivers/pci.h +++ b/kernel/inc/drivers/pci.h @@ -76,14 +76,14 @@ static inline u8 pci_extract_func(u32 device) return (u8)(device); } -static inline u32 pci_get_addr(u32 device, int field) +UNUSED_FUNC static inline u32 pci_get_addr(u32 device, int field) { return 0x80000000 | (u32)(pci_extract_bus(device) << 16) | (u32)(pci_extract_slot(device) << 11) | (u32)(pci_extract_func(device) << 8) | ((field)&0xFC); } -static inline u32 pci_box_device(int bus, int slot, int func) +UNUSED_FUNC static inline u32 pci_box_device(int bus, int slot, int func) { return (u32)((bus << 16) | (slot << 8) | func); } diff --git a/kernel/inc/drivers/rtl8139.h b/kernel/inc/drivers/rtl8139.h deleted file mode 100644 index 0d748af..0000000 --- a/kernel/inc/drivers/rtl8139.h +++ /dev/null @@ -1,36 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef RTL8139_H -#define RTL8139_H - -#include <def.h> - -#define RX_BUF_SIZE 0x2000 - -#define RTL8139_VENDOR_ID 0x10ec -#define RTL8139_DEVICE_ID 0x8139 - -#define RTL_ROK (1 << 0) -#define RTL_TOK (1 << 2) - -#define RTL_PORT_MAC 0x00 -#define RTL_PORT_MAR 0x08 -#define RTL_PORT_TXSTAT 0x10 -#define RTL_PORT_TXBUF 0x20 -#define RTL_PORT_RBSTART 0x30 -#define RTL_PORT_CMD 0x37 -#define RTL_PORT_RXPTR 0x38 -#define RTL_PORT_RXADDR 0x3A -#define RTL_PORT_IMR 0x3C -#define RTL_PORT_ISR 0x3E -#define RTL_PORT_TCR 0x40 -#define RTL_PORT_RCR 0x44 -#define RTL_PORT_RXMISS 0x4C -#define RTL_PORT_CONFIG 0x52 - -int rtl8139_install(void); -int rtl8139_installed(void); -void rtl8139_send_packet(void *data, u32 len) NONNULL; -u8 *rtl8139_get_mac(void); - -#endif diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 8f6f06a..0a2bb81 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -4,8 +4,8 @@ #define PAGING_H #include <def.h> -#include <errno.h> #include <drivers/interrupts.h> +#include <errno.h> struct memory_range { u32 base; diff --git a/kernel/inc/net.h b/kernel/inc/net.h deleted file mode 100644 index 62ff5e5..0000000 --- a/kernel/inc/net.h +++ /dev/null @@ -1,168 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef NET_H -#define NET_H - -#include <def.h> -#include <socket.h> - -#define htonl(l) \ - ((((l)&0xff) << 24) | (((l)&0xff00) << 8) | (((l)&0xff0000) >> 8) | \ - (((l)&0xff000000) >> 24)) -#define htons(s) ((((s)&0xff) << 8) | (((s)&0xff00) >> 8)) -#define ntohl(l) htonl((l)) -#define ntohs(s) htons((s)) -#define ip(a, b, c, d) \ - ((((a)&0xff) << 24) | (((b)&0xff) << 16) | (((c)&0xff) << 8) | (((d)&0xff) << 0)) - -#define ETHERNET_TYPE_IP4 0x0800 -#define ETHERNET_TYPE_IP6 0x86dd -#define ETHERNET_TYPE_ARP 0x0806 - -#define IP_PROT_ICMP 0x01 -#define IP_PROT_TCP 0x06 -#define IP_PROT_UDP 0x11 - -#define TCP_FLAG_FIN (1 << 0) -#define TCP_FLAG_SYN (1 << 1) -#define TCP_FLAG_RST (1 << 2) -#define TCP_FLAG_PSH (1 << 3) -#define TCP_FLAG_ACK (1 << 4) -#define TCP_FLAG_URG (1 << 5) -#define TCP_FLAG_ECE (1 << 6) -#define TCP_FLAG_CWR (1 << 7) -#define TCP_FLAG_NS (1 << 8) - -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - -#define DHCP_REQUEST 1 -#define DHCP_REPLY 2 -#define DHCP_TRANSACTION_IDENTIFIER 0x18122002 - -#define HARDWARE_TYPE_ETHERNET 0x01 - -// Hardcoded ports - TODO! -#define DHCP_PORT 68 -#define DNS_PORT 50053 - -// Protocol structs - -struct ethernet_packet { - u8 dst[6]; - u8 src[6]; - u16 type; - u8 data[]; -} PACKED; - -struct arp_packet { - u16 hardware_type; - u16 protocol; - u8 hardware_addr_len; - u8 protocol_addr_len; - u16 opcode; - u8 src_mac[6]; - u32 src_protocol_addr; - u8 dst_mac[6]; - u32 dst_protocol_addr; -} PACKED; - -struct ip_packet { - u8 version_ihl; - u8 dscp_ecn; - u16 length; - u16 id; - u16 flags_fragment; - u8 ttl; - u8 protocol; - u16 checksum; - u32 src; - u32 dst; - u8 data[]; -} PACKED; - -struct dhcp_packet { - u8 op; - u8 hardware_type; - u8 mac_len; - u8 hops; - u32 xid; - u16 seconds; - u16 flags; - u32 client_ip; - u32 your_ip; - u32 server_ip; - u32 gateway_ip; - u8 client_mac[6]; - u8 reserved[10]; - u8 server_name[64]; - u8 file[128]; - u8 options[64]; -} PACKED; - -struct dns_packet { - u16 qid; - u16 flags; - u16 questions; - u16 answers; - u16 authorities; - u16 additional; - u8 data[]; -} PACKED; - -struct udp_packet { - u16 src_port; - u16 dst_port; - u16 length; - u16 checksum; - u8 data[]; -} PACKED; - -struct tcp_packet { - u16 src_port; - u16 dst_port; - u32 seq_number; - u32 ack_number; - u16 flags; - u16 window_size; - u16 checksum; - u16 urgent; - u8 data[]; -} PACKED; - -struct tcp_pseudo_header { - u32 src; - u32 dst; - u8 zeros; - u8 protocol; - u16 tcp_len; - u8 tcp_packet[]; -}; - -struct icmp_packet { - u8 type; - u8 version; - u16 checksum; - u16 identifier; - u16 sequence; -} PACKED; - -// Other structs - -struct arp_table_entry { - u32 ip_addr; - u64 mac_addr; -}; - -void ethernet_handle_packet(struct ethernet_packet *packet, int len) NONNULL; - -struct socket *net_open(enum socket_type type); -int net_close(struct socket *socket) NONNULL; -int net_connect(struct socket *socket, u32 ip_addr, u16 dst_port) NONNULL; -void net_send(struct socket *socket, void *data, u32 len) NONNULL; -int net_receive(struct socket *socket, void *buf, u32 len) NONNULL; - -int net_installed(void); -void net_install(void); - -#endif diff --git a/kernel/main.c b/kernel/main.c index 76d8412..44198e4 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,20 +1,19 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <drivers/cpu.h> -#include <fs.h> #include <drivers/gdt.h> #include <drivers/ide.h> #include <drivers/interrupts.h> +#include <drivers/pci.h> +#include <drivers/rtc.h> +#include <drivers/serial.h> +#include <fs.h> #include <io.h> #include <load.h> #include <mem.h> #include <mm.h> #include <multiboot.h> -#include <net.h> -#include <drivers/pci.h> #include <rand.h> -#include <drivers/rtc.h> -#include <drivers/serial.h> #include <syscall.h> PROTECTED extern u32 __stack_chk_guard; diff --git a/libs/libc/print.c b/libs/libc/print.c index 46483cd..2eb119a 100644 --- a/libs/libc/print.c +++ b/libs/libc/print.c @@ -188,9 +188,9 @@ int print(const char *str) // The kernel prints everything into the serial console #include <drivers/cpu.h> +#include <drivers/serial.h> #include <mm.h> #include <proc.h> -#include <drivers/serial.h> static void print_kernel(const char *str) { diff --git a/libs/libgui/png.c b/libs/libgui/png.c index c405c3c..d2053ca 100644 --- a/libs/libgui/png.c +++ b/libs/libgui/png.c @@ -408,7 +408,6 @@ u32 png_load_file(u8 **out, u32 *outsize, const char *filename) /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ u32 png_save_file(const u8 *buffer, u32 buffersize, const char *filename) { - err(1, "Not implemented!\n"); if (write(filename, buffer, 0, buffersize) <= 0) return 79; return 0; diff --git a/libs/libnet/Makefile b/libs/libnet/Makefile deleted file mode 100644 index 53cb7a9..0000000 --- a/libs/libnet/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# MIT License, Copyright (c) 2020 Marvin Borner - -COBJS = dns.o http.o ip.o - -CFLAGS = $(CFLAGS_DEFAULT) -I$(LIBS) -I$(LIBS)/libc/inc/ -pie -fPIE -fPIC -DUSER - -all: libtxt - -%.o: %.c - @$(CC) -c $(CFLAGS) $< -o $@ - -libtxt: $(COBJS) - @mkdir -p $(BUILD) - @$(AR) rcs $(BUILD)/libnet.a $+ - -clean: - @find . -name "*.o" -type f -delete diff --git a/libs/libnet/dns.c b/libs/libnet/dns.c deleted file mode 100644 index e179bd6..0000000 --- a/libs/libnet/dns.c +++ /dev/null @@ -1,116 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner -// TODO: Less magic, auto xld splitting -// TODO: DNS cache - -#include <def.h> -#include <libnet/net.h> -#include <libnet/socket.h> -#include <mem.h> -#include <print.h> -#include <random.h> -#include <str.h> - -static u32 dns_ip_addr = ip(1, 1, 1, 1); - -struct dns_packet { - u16 qid; - u16 flags; - u16 questions; - u16 answers; - u16 authorities; - u16 additional; - u8 data[]; -} PACKED; - -static u32 part_count(const char *name) -{ - u32 cnt = 0; - for (u32 i = 0; i < strlen(name); i++) { - if (name[i] == '.') - cnt++; - } - return cnt + 1; -} - -static u32 part_len(const char *name, u32 index) -{ - const char *data = name; - - u32 cnt = 0; - for (u32 i = 0; i < strlen(name); i++) { - if (cnt == index) { - data += i; - break; - } - - if (name[i] == '.') - cnt++; - } - - for (cnt = 0; cnt < strlen(data); cnt++) { - if (data[cnt] == '.' || data[cnt] == '\0') - break; - } - - return cnt; -} - -static void dns_make_packet(struct dns_packet *packet, const char *name) -{ - packet->qid = htons(rand()); - packet->flags = htons(0x0100); // Standard query - packet->questions = htons(1); - packet->answers = htons(0); - packet->authorities = htons(0); - packet->additional = htons(0); - - u8 *data = packet->data; - u32 cnt = 0; - for (u32 i = 0; i < part_count(name) * 2; i += 2) { - data[cnt] = part_len(name, i / 2); - memcpy(&data[cnt + 1], &name[cnt], data[cnt]); - cnt += data[cnt] + 1; - } - - packet->data[cnt + 0] = 0x00; // Name end - packet->data[cnt + 2] = 0x01; // A - packet->data[cnt + 4] = 0x01; // IN -} - -static u32 dns_handle_packet(struct dns_packet *packet) -{ - u16 flags = htons(packet->flags); - u8 reply_code = flags & 0xf; - if (reply_code != DNS_NOERROR) { - printf("DNS error: %d\n", reply_code); - return 0; - } - - u8 *start = &packet->data[1] + strlen((char *)&packet->data[1]); - printf("TTL of %s: %ds\n", &packet->data[1], (u32)start[14]); - u8 *ip = &start[17]; - printf("IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); - return ip(ip[0], ip[1], ip[2], ip[3]); -} - -u32 dns_request(const char *name) -{ - struct socket *socket = net_open(S_UDP); - if (!socket || !net_connect(socket, dns_ip_addr, 53, NET_TIMEOUT) || part_count(name) == 1) - return 0; - - u32 length = sizeof(struct dns_packet) + strlen(name) + part_count(name) + 4; - struct dns_packet *packet = malloc(length); - memset(packet, 0, length); - dns_make_packet(packet, name); - net_send(socket, packet, length); - free(packet); - - u8 buf[1024] = { 0 }; - int l = net_receive(socket, buf, 1024, NET_TIMEOUT); - net_close(socket); - if (l > 0) - return dns_handle_packet((void *)buf); - else - return 0; -} diff --git a/libs/libnet/dns.h b/libs/libnet/dns.h deleted file mode 100644 index d6673e6..0000000 --- a/libs/libnet/dns.h +++ /dev/null @@ -1,21 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef DNS_H -#define DNS_H - -#include <def.h> - -#define DNS_NOERROR 0 -#define DNS_FORMERR 1 -#define DNS_SERVFAIL 2 -#define DNS_NXDOMAIN 3 -#define DNS_NOTIMP 4 -#define DNS_REFUSED 5 -#define DNS_YXDOMAIN 6 -#define DNS_XRRSET 7 -#define DNS_NOTAUTH 8 -#define DNS_NOTZONE 9 - -u32 dns_request(const char *name); - -#endif diff --git a/libs/libnet/http.c b/libs/libnet/http.c deleted file mode 100644 index 808d4c2..0000000 --- a/libs/libnet/http.c +++ /dev/null @@ -1,134 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#include <assert.h> -#include <conv.h> -#include <def.h> -#include <libnet/http.h> -#include <libnet/net.h> -#include <libnet/socket.h> -#include <mem.h> -#include <print.h> -#include <str.h> - -char *http_data(char *r) -{ - char *h = NULL; - for (u32 i = 0; i < strlen(r); ++i) { - if (r[i] == '\r' && r[i + 1] == '\n' && r[i + 2] == '\r' && r[i + 3] == '\n') { - h = &r[i + 4]; - break; - } - } - return h; -} - -char *http_header_key(char *r, const char *key) -{ - char *res = NULL; - for (char *p = r; *p; p++) { - /* printf("'%c%c%c' vs '%c%c%c'\n", p[0], p[1], p[2], key[0], key[1], key[2]); */ - if (strlen(p) >= strlen(key) && !memcmp(p, key, strlen(key))) { - char *start = p + strlen(key) + 2; - char *end = start; - for (; *end != '\n'; end++) - ; - res = malloc(end - start); - memcpy(res, start, end - start - 1); - res[end - start] = '\0'; - break; - } - } - return res; -} - -u32 http_content_length(char *r) -{ - char *value = http_header_key(r, "Content-Length"); - int length = value ? atoi(value) : 0; - free(value); - return length; -} - -char *http_code(char *r) -{ - char *code = malloc(4); - char tmp = r[12]; - r[12] = '\0'; - memcpy(code, r + 9, 3); - code[3] = '\0'; - r[12] = tmp; - return code; -} - -u32 http_response(const char *http_code, u32 content_length, const char *data, char *resp) -{ - char buf[16] = { 0 }; - - resp[0] = '\0'; - strcat(resp, "HTTP/1.1 "); - strcat(resp, buf); - strcat(resp, http_code); - strcat(resp, "\r\n"); - strcat(resp, "Content-Length: "); - strcat(resp, conv_base(content_length, buf, 10, 0)); - strcat(resp, "\r\n"); - strcat(resp, "Server: Melvix\r\n"); - strcat(resp, "Content-Type: text/html\r\n"); - strcat(resp, "Connection: close\r\n\r\n"); - u32 len = strlen(resp); - memcpy(&resp[len], data, content_length); - - return len + content_length; -} - -char *http_query_get(const char *url, const char *path) -{ - char *query = malloc(27 + strlen(url)); // TODO: Dynamic http length etc - query[0] = '\0'; - strcat(query, "GET "); - if (path[0] != '/') - strcat(query, "/"); - strcat(query, path); - strcat(query, " HTTP/1.1\r\nHost: "); - strcat(query, url); - strcat(query, "\r\n\r\n"); - return query; -} - -char *http_query_path(const char *query, char *path) -{ - u8 b = 0; - u32 s = 0; - u32 e = 0; - - while (1) { - if (!b && query[e] == ' ' && query[++e]) { - s = e; - b = 1; - } else if (b && query[e] == ' ') { - strncat(path, &query[s], e - s); - break; - } else if (query[e] == '\0') { - return NULL; - } - e++; - } - - return path; -} - -char *http_receive(struct socket *socket) -{ - char buf[4096] = { 0 }; - if (!net_receive(socket, buf, 4096, NET_TIMEOUT)) - return NULL; - - u32 length = http_content_length(buf); - char *data = malloc(strlen(buf) + length); - memcpy(data, buf, strlen(buf)); - while (strlen(http_data(data)) != length) { - if (!net_receive(socket, data, length, NET_TIMEOUT)) - break; - } - return data; -} diff --git a/libs/libnet/http.h b/libs/libnet/http.h deleted file mode 100644 index b9160ad..0000000 --- a/libs/libnet/http.h +++ /dev/null @@ -1,82 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef HTTP_H -#define HTTP_H - -#include <def.h> -#include <libnet/socket.h> - -char *http_data(char *response); -char *http_header_key(char *r, const char *key); -u32 http_content_length(char *r); -char *http_code(char *r); -u32 http_response(const char *http_code, u32 content_length, const char *data, char *resp); -char *http_query_get(const char *url, const char *path); -char *http_query_path(const char *query, char *path); -char *http_receive(struct socket *socket); - -#define HTTP_100 "100 Continue" -#define HTTP_101 "101 Switching Protocol" -#define HTTP_102 "102 Processing" -#define HTTP_103 "103 Early Hints" -#define HTTP_200 "200 OK" -#define HTTP_201 "201 Created" -#define HTTP_202 "202 Accepted" -#define HTTP_203 "203 Non-Authoritative Information" -#define HTTP_204 "204 No Content" -#define HTTP_205 "205 Reset Content" -#define HTTP_206 "206 Partial Content" -#define HTTP_207 "207 Multi-Status" -#define HTTP_208 "208 Already Reported" -#define HTTP_226 "226 IM Used" -#define HTTP_300 "300 Multiple Choice" -#define HTTP_301 "301 Moved Permanently" -#define HTTP_302 "302 Found" -#define HTTP_303 "303 See Other" -#define HTTP_304 "304 Not Modified" -#define HTTP_305 "305 Use Proxy" -#define HTTP_306 "306 Unused" -#define HTTP_307 "307 Temporary Redirect" -#define HTTP_308 "308 Permanent Redirect" -#define HTTP_400 "400 Bad Request" -#define HTTP_401 "401 Unauthorized" -#define HTTP_402 "402 Payment Required" -#define HTTP_403 "403 Forbidden" -#define HTTP_404 "404 Not Found" -#define HTTP_405 "405 Method Not Allowed" -#define HTTP_406 "406 Not Acceptable" -#define HTTP_407 "407 Proxy Authentication Required" -#define HTTP_408 "408 Request Timeout" -#define HTTP_409 "409 Conflict" -#define HTTP_410 "410 Gone" -#define HTTP_411 "411 Length Required" -#define HTTP_412 "412 Precondition Failed" -#define HTTP_413 "413 Payload Too Large" -#define HTTP_414 "414 URI Too Long" -#define HTTP_415 "415 Unsupported Media Type" -#define HTTP_416 "416 Range Not Satisfiable" -#define HTTP_417 "417 Expectation Failed" -#define HTTP_418 "418 I'm a teapot" -#define HTTP_421 "421 Misdirected Request" -#define HTTP_422 "422 Unprocessable Entity" -#define HTTP_423 "423 Locked" -#define HTTP_424 "424 Failed Dependency" -#define HTTP_425 "425 Too Early" -#define HTTP_426 "426 Upgrade Required" -#define HTTP_428 "428 Precondition Required" -#define HTTP_429 "429 Too Many Request" -#define HTTP_431 "431 Request Header Fields Too Large" -#define HTTP_451 "451 Unavailable For Legal Reasons" -#define HTTP_500 "500 Internal Server Error" -#define HTTP_501 "501 Not Implemented" -#define HTTP_502 "502 Bad Gateway" -#define HTTP_503 "503 Service Unavailable" -#define HTTP_504 "504 Gateway Timeout" -#define HTTP_505 "505 HTTP Version Not Supported" -#define HTTP_506 "506 Variant Also Negotiates" -#define HTTP_507 "507 Insufficient Storage" -#define HTTP_508 "508 Loop Detected" -#define HTTP_510 "510 Not Extended" -#define HTTP_511 "511 Network Authentication Required" - -#endif diff --git a/libs/libnet/ip.c b/libs/libnet/ip.c deleted file mode 100644 index 66fd8eb..0000000 --- a/libs/libnet/ip.c +++ /dev/null @@ -1,48 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner -// Most net/ip handlers are in the kernel space -// This is a userspace wrapper for some things - -#include <def.h> -#include <libnet/net.h> -#include <mem.h> -#include <str.h> - -// Inspired by Paul Vixie, 1996 -int ip_pton(const char *src, u32 *dst) -{ - const char *end = src + strlen(src); - u8 tmp[4], *tp; - int saw_digit = 0; - int octets = 0; - *(tp = tmp) = 0; - - while (src < end) { - int ch = *src++; - if (ch >= '0' && ch <= '9') { - u32 new = *tp * 10 + (ch - '0'); - - if ((saw_digit && *tp == 0) || new > 255) - return 0; - - *tp = new; - if (!saw_digit) { - if (++octets > 4) - return 0; - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return 0; - *++tp = 0; - saw_digit = 0; - } else { - return 0; - } - } - - if (octets < 4) - return 0; - - *dst = htonl(*(u32 *)tmp); - return 1; -} diff --git a/libs/libnet/ip.h b/libs/libnet/ip.h deleted file mode 100644 index e06aba2..0000000 --- a/libs/libnet/ip.h +++ /dev/null @@ -1,12 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner -// Most net/ip handlers are in the kernel space -// This is a userspace wrapper for some things - -#ifndef IP_H -#define IP_H - -#include <def.h> - -int ip_pton(const char *src, u32 *dst); - -#endif diff --git a/libs/libnet/net.h b/libs/libnet/net.h deleted file mode 100644 index 4bfda2b..0000000 --- a/libs/libnet/net.h +++ /dev/null @@ -1,73 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef NET_H -#define NET_H - -#include <libnet/dns.h> -#include <libnet/ip.h> -#include <libnet/socket.h> -#include <print.h> -#include <sys.h> - -#define htonl(l) \ - ((((l)&0xff) << 24) | (((l)&0xff00) << 8) | (((l)&0xff0000) >> 8) | \ - (((l)&0xff000000) >> 24)) -#define htons(s) ((((s)&0xff) << 8) | (((s)&0xff00) >> 8)) -#define ntohl(l) htonl((l)) -#define ntohs(s) htons((s)) -#define ip(a, b, c, d) \ - ((((a)&0xff) << 24) | (((b)&0xff) << 16) | (((c)&0xff) << 8) | (((d)&0xff) << 0)) - -#define NET_TIMEOUT 2000 -#define NET_NO_TIMEOUT 0 - -static inline int net_data_available(struct socket *socket) -{ - return (socket && socket->packets && socket->packets->head && socket->packets->head->data && - ((struct socket_data *)socket->packets->head->data)->length > 0); -} - -#define net_open(type) (void *)sys1(SYS_NET_OPEN, (int)(type)) -#define net_send(socket, data, len) (void)sys3(SYS_NET_SEND, (int)(socket), (int)(data), (int)(len)) - -static inline int net_connect(struct socket *socket, u32 ip_addr, u16 dst_port, u32 timeout) -{ - if (!socket || !ip_addr || !dst_port) - return 0; - sys3(SYS_NET_CONNECT, (int)(socket), (int)(ip_addr), (int)(dst_port)); - int time = time(); - while (socket->state != S_CONNECTED) { - if (socket->state == S_FAILED || (timeout && time() - time >= timeout)) - return 0; - yield(); - } - return 1; -} - -static inline int net_close(struct socket *socket) -{ - if (!socket) - return 0; - int res = 0; - while (socket->state == S_CLOSING || !(res = (int)sys1(SYS_NET_CLOSE, (int)(socket)))) - yield(); - return res; -} - -static inline int net_receive(struct socket *socket, void *buf, u32 len, u32 timeout) -{ - if (!socket || !buf || !len) - return 0; - - int time = time(); - while (!net_data_available(socket)) { - if (socket->state == S_FAILED || (timeout && time() - time >= timeout)) - return 0; - yield(); - } - - // TODO: Only return once all segments are received? - return (int)sys3(SYS_NET_RECEIVE, (int)(socket), (int)(buf), (int)(len)); -} - -#endif diff --git a/libs/libtxt/xml.c b/libs/libtxt/xml.c deleted file mode 100644 index 9a5fd76..0000000 --- a/libs/libtxt/xml.c +++ /dev/null @@ -1,514 +0,0 @@ -// Inspired by sxml (capmar) -// MIT License, Copyright (c) 2020 Marvin Borner - -#include <assert.h> -#include <libtxt/xml.h> -#include <mem.h> -#include <str.h> - -static const char *str_findchr(const char *start, const char *end, int c) -{ - const char *it; - - assert(start <= end); - assert(0 <= c && c <= 127); - - it = (const char *)memchr((void *)start, c, end - start); - return (it != NULL) ? it : end; -} - -static const char *str_findstr(const char *start, const char *end, const char *needle) -{ - u32 needlelen; - int first; - assert(start <= end); - - needlelen = strlen(needle); - assert(0 < needlelen); - first = (u8)needle[0]; - - while (start + needlelen <= end) { - const char *it = - (const char *)memchr((void *)start, first, (end - start) - (needlelen - 1)); - if (it == NULL) - break; - - if (memcmp(it, needle, needlelen) == 0) - return it; - - start = it + 1; - } - - return end; -} - -static int str_starts_with(const char *start, const char *end, const char *prefix) -{ - long nbytes; - assert(start <= end); - - nbytes = strlen(prefix); - if (end - start < nbytes) - return 0; - - return memcmp(prefix, start, nbytes) == 0; -} - -static int white_space(int c) -{ - switch (c) { - case ' ': - case '\t': - case '\r': - case '\n': - return 1; - } - - return 0; -} - -static int name_start_char(int c) -{ - if (0x80 <= c) - return 1; - - return c == ':' || ('A' <= c && c <= 'Z') || c == '_' || ('a' <= c && c <= 'z'); -} - -static int name_char(int c) -{ - return name_start_char(c) || c == '-' || c == '.' || ('0' <= c && c <= '9') || c == 0xB7 || - (0x0300 <= c && c <= 0x036F) || (0x203F <= c && c <= 0x2040); -} - -#define is_space(c) (white_space(((u8)(c)))) -#define is_alpha(c) (name_start_char(((u8)(c)))) -#define is_alnum(c) (name_char(((u8)(c)))) - -static const char *str_ltrim(const char *start, const char *end) -{ - const char *it; - assert(start <= end); - - for (it = start; it != end && is_space(*it); it++) - ; - - return it; -} - -static const char *str_rtrim(const char *start, const char *end) -{ - const char *it, *prev; - assert(start <= end); - - for (it = end; start != it; it = prev) { - prev = it - 1; - if (!is_space(*prev)) - return it; - } - - return start; -} - -static const char *str_find_notalnum(const char *start, const char *end) -{ - const char *it; - assert(start <= end); - - for (it = start; it != end && is_alnum(*it); it++) - ; - - return it; -} - -#define buffer_from_offset(args, i) ((args)->buffer + (i)) -#define buffer_tooffset(args, ptr) (unsigned)((ptr) - (args)->buffer) -#define buffer_getend(args) ((args)->buffer + (args)->buffer_length) - -static int state_push_token(struct xml *state, struct xml_args *args, enum xml_type type, - const char *start, const char *end) -{ - struct xml_token *token; - u32 i; - if (args->num_tokens <= state->ntokens) - return 0; - - i = state->ntokens++; - token = &args->tokens[i]; - token->type = type; - token->start_pos = buffer_tooffset(args, start); - token->end_pos = buffer_tooffset(args, end); - token->size = 0; - - switch (type) { - case XML_START_TAG: - state->tag_level++; - break; - - case XML_END_TAG: - assert(0 < state->tag_level); - state->tag_level--; - break; - - default: - break; - } - - return 1; -} - -static enum xml_error state_set_pos(struct xml *state, const struct xml_args *args, const char *ptr) -{ - state->buffer_pos = buffer_tooffset(args, ptr); - return (state->ntokens <= args->num_tokens) ? XML_SUCCESS : XML_ERROR_TOKENSFULL; -} - -#define state_commit(dest, src) memcpy((dest), (src), sizeof(struct xml)) - -#define XML_ERROR_STRICT XML_ERROR_INVALID -#define ENTITY_MAXLEN 8 -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -static enum xml_error parse_characters(struct xml *state, struct xml_args *args, const char *end) -{ - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *limit, *colon, *ampr = str_findchr(start, end, '&'); - assert(end <= buffer_getend(args)); - - if (ampr != start) - state_push_token(state, args, XML_CHARACTER, start, ampr); - - if (ampr == end) - return state_set_pos(state, args, ampr); - - limit = MIN(ampr + ENTITY_MAXLEN, end); - colon = str_findchr(ampr, limit, ';'); - if (colon == limit) - return (limit == end) ? XML_ERROR_BUFFERDRY : XML_ERROR_INVALID; - - start = colon + 1; - state_push_token(state, args, XML_CHARACTER, ampr, start); - return state_set_pos(state, args, start); -} - -static enum xml_error parse_attrvalue(struct xml *state, struct xml_args *args, const char *end) -{ - while (buffer_from_offset(args, state->buffer_pos) != end) { - enum xml_error error = parse_characters(state, args, end); - if (error != XML_SUCCESS) - return error; - } - - return XML_SUCCESS; -} - -static enum xml_error parse_attributes(struct xml *state, struct xml_args *args) -{ - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - const char *name = str_ltrim(start, end); - - u32 ntokens = state->ntokens; - assert(0 < ntokens); - - while (name != end && is_alpha(*name)) { - const char *eq, *space, *quot, *value; - enum xml_error error; - - eq = str_findchr(name, end, '='); - if (eq == end) - return XML_ERROR_BUFFERDRY; - - space = str_rtrim(name, eq); - state_push_token(state, args, XML_CDATA, name, space); - - quot = str_ltrim(eq + 1, end); - if (quot == end) - return XML_ERROR_BUFFERDRY; - else if (*quot != '\'' && *quot != '"') - return XML_ERROR_INVALID; - - value = quot + 1; - quot = str_findchr(value, end, *quot); - if (quot == end) - return XML_ERROR_BUFFERDRY; - - state_set_pos(state, args, value); - error = parse_attrvalue(state, args, quot); - if (error != XML_SUCCESS) - return error; - - name = str_ltrim(quot + 1, end); - } - - { - struct xml_token *token = args->tokens + (ntokens - 1); - token->size = (u16)(state->ntokens - ntokens); - } - - return state_set_pos(state, args, name); -} - -#define TAG_LEN(str) (sizeof(str) - 1) -#define TAG_MINSIZE 1 - -static enum xml_error parse_comment(struct xml *state, struct xml_args *args) -{ - static const char START_TAG[] = "<!--"; - static const char END_TAG[] = "-->"; - - const char *dash; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - if (end - start < (int)TAG_LEN(START_TAG)) - return XML_ERROR_BUFFERDRY; - - if (!str_starts_with(start, end, START_TAG)) - return XML_ERROR_INVALID; - - start += TAG_LEN(START_TAG); - dash = str_findstr(start, end, END_TAG); - if (dash == end) - return XML_ERROR_BUFFERDRY; - - state_push_token(state, args, XML_COMMENT, start, dash); - return state_set_pos(state, args, dash + TAG_LEN(END_TAG)); -} - -static enum xml_error parse_instruction(struct xml *state, struct xml_args *args) -{ - static const char START_TAG[] = "<?"; - static const char END_TAG[] = "?>"; - - enum xml_error error; - const char *quest, *space; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - assert(TAG_MINSIZE <= end - start); - - if (!str_starts_with(start, end, START_TAG)) - return XML_ERROR_INVALID; - - start += TAG_LEN(START_TAG); - space = str_find_notalnum(start, end); - if (space == end) - return XML_ERROR_BUFFERDRY; - - state_push_token(state, args, XML_INSTRUCTION, start, space); - - state_set_pos(state, args, space); - error = parse_attributes(state, args); - if (error != XML_SUCCESS) - return error; - - quest = buffer_from_offset(args, state->buffer_pos); - if (end - quest < (int)TAG_LEN(END_TAG)) - return XML_ERROR_BUFFERDRY; - - if (!str_starts_with(quest, end, END_TAG)) - return XML_ERROR_INVALID; - - return state_set_pos(state, args, quest + TAG_LEN(END_TAG)); -} - -static enum xml_error parse_doctype(struct xml *state, struct xml_args *args) -{ - static const char START_TAG[] = "<!DOCTYPE"; - static const char END_TAG[] = ">"; - - const char *bracket; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - if (end - start < (int)TAG_LEN(START_TAG)) - return XML_ERROR_BUFFERDRY; - - if (!str_starts_with(start, end, START_TAG)) - return XML_ERROR_BUFFERDRY; - - start += TAG_LEN(START_TAG); - bracket = str_findstr(start, end, END_TAG); - if (bracket == end) - return XML_ERROR_BUFFERDRY; - - state_push_token(state, args, XML_DOCTYPE, start, bracket); - return state_set_pos(state, args, bracket + TAG_LEN(END_TAG)); -} - -static enum xml_error parse_start(struct xml *state, struct xml_args *args) -{ - enum xml_error error; - const char *gt, *name, *space; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - assert(TAG_MINSIZE <= end - start); - - if (!(start[0] == '<' && is_alpha(start[1]))) - return XML_ERROR_INVALID; - - name = start + 1; - space = str_find_notalnum(name, end); - if (space == end) - return XML_ERROR_BUFFERDRY; - - state_push_token(state, args, XML_START_TAG, name, space); - - state_set_pos(state, args, space); - error = parse_attributes(state, args); - if (error != XML_SUCCESS) - return error; - - gt = buffer_from_offset(args, state->buffer_pos); - - if (gt != end && *gt == '/') { - state_push_token(state, args, XML_END_TAG, name, space); - gt++; - } - - if (gt == end) - return XML_ERROR_BUFFERDRY; - - if (*gt != '>') - return XML_ERROR_INVALID; - - return state_set_pos(state, args, gt + 1); -} - -static enum xml_error parse_end(struct xml *state, struct xml_args *args) -{ - const char *gt, *space; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - assert(TAG_MINSIZE <= end - start); - - if (!(str_starts_with(start, end, "</") && is_alpha(start[2]))) - return XML_ERROR_INVALID; - - start += 2; - gt = str_findchr(start, end, '>'); - if (gt == end) - return XML_ERROR_BUFFERDRY; - - space = str_find_notalnum(start, gt); - if (str_ltrim(space, gt) != gt) - return XML_ERROR_STRICT; - - state_push_token(state, args, XML_END_TAG, start, space); - return state_set_pos(state, args, gt + 1); -} - -static enum xml_error parse_cdata(struct xml *state, struct xml_args *args) -{ - static const char START_TAG[] = "<![CDATA["; - static const char END_TAG[] = "]]>"; - - const char *bracket; - const char *start = buffer_from_offset(args, state->buffer_pos); - const char *end = buffer_getend(args); - if (end - start < (int)TAG_LEN(START_TAG)) - return XML_ERROR_BUFFERDRY; - - if (!str_starts_with(start, end, START_TAG)) - return XML_ERROR_INVALID; - - start += TAG_LEN(START_TAG); - bracket = str_findstr(start, end, END_TAG); - if (bracket == end) - return XML_ERROR_BUFFERDRY; - - state_push_token(state, args, XML_CDATA, start, bracket); - return state_set_pos(state, args, bracket + TAG_LEN(END_TAG)); -} - -void xml_init(struct xml *state) -{ - state->buffer_pos = 0; - state->ntokens = 0; - state->tag_level = 0; -} - -#define ROOT_FOUND(state) (0 < (state)->tag_level) -#define ROOT_PARSED(state) ((state)->tag_level == 0) - -enum xml_error xml_parse(struct xml *state, const char *buffer, u32 buffer_length, - struct xml_token tokens[], u32 num_tokens) -{ - struct xml temp = *state; - const char *end = buffer + buffer_length; - - struct xml_args args; - args.buffer = buffer; - args.buffer_length = buffer_length; - args.tokens = tokens; - args.num_tokens = num_tokens; - - while (!ROOT_FOUND(&temp)) { - enum xml_error error; - const char *start = buffer_from_offset(&args, temp.buffer_pos); - const char *lt = str_ltrim(start, end); - state_set_pos(&temp, &args, lt); - state_commit(state, &temp); - - if (end - lt < TAG_MINSIZE) - return XML_ERROR_BUFFERDRY; - - if (*lt != '<') - return XML_ERROR_INVALID; - - switch (lt[1]) { - case '?': - error = parse_instruction(&temp, &args); - break; - case '!': - error = (lt[2] == '-') ? parse_comment(&temp, &args) : - parse_doctype(&temp, &args); - break; - default: - error = parse_start(&temp, &args); - break; - } - - if (error != XML_SUCCESS) - return error; - - state_commit(state, &temp); - } - - while (!ROOT_PARSED(&temp)) { - enum xml_error error; - const char *start = buffer_from_offset(&args, temp.buffer_pos); - const char *lt = str_findchr(start, end, '<'); - while (buffer_from_offset(&args, temp.buffer_pos) != lt) { - error = parse_characters(&temp, &args, lt); - if (error != XML_SUCCESS) - return error; - - state_commit(state, &temp); - } - - if (end - lt < TAG_MINSIZE) - return XML_ERROR_BUFFERDRY; - - switch (lt[1]) { - case '?': - error = parse_instruction(&temp, &args); - break; - case '/': - error = parse_end(&temp, &args); - break; - case '!': - error = (lt[2] == '-') ? parse_comment(&temp, &args) : - parse_cdata(&temp, &args); - break; - default: - error = parse_start(&temp, &args); - break; - } - - if (error != XML_SUCCESS) - return error; - - state_commit(state, &temp); - } - - return XML_SUCCESS; -} diff --git a/libs/libtxt/xml.h b/libs/libtxt/xml.h deleted file mode 100644 index 3f5c74d..0000000 --- a/libs/libtxt/xml.h +++ /dev/null @@ -1,51 +0,0 @@ -// Inspired by sxml (capmar) -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef XML_H -#define XML_H - -#include <def.h> - -enum xml_error { - XML_ERROR_INVALID = -1, - XML_SUCCESS = 0, - XML_ERROR_BUFFERDRY = 1, - XML_ERROR_TOKENSFULL = 2 -}; - -struct xml_token { - u16 type; - u16 size; - u32 start_pos; - u32 end_pos; -}; - -struct xml_args { - const char *buffer; - u32 buffer_length; - struct xml_token *tokens; - u32 num_tokens; -}; - -enum xml_type { - XML_START_TAG, - XML_END_TAG, - XML_CHARACTER, - XML_CDATA, - XML_INSTRUCTION, - XML_DOCTYPE, - XML_COMMENT -}; - -struct xml { - u32 buffer_pos; - u32 ntokens; - u32 tag_level; -}; - -enum xml_error xml_parse(struct xml *parser, const char *buffer, u32 buffer_length, - struct xml_token *tokens, u32 num_tokens) NONNULL; - -void xml_init(struct xml *parser) NONNULL; - -#endif diff --git a/res/test.c b/res/test.c deleted file mode 100644 index ead84da..0000000 --- a/res/test.c +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - printf("Hello, world!\n"); - return 0; -} @@ -270,6 +270,23 @@ make_sync() { mv tmp compile_commands.json } +make_lint() { + format=$({ find . -path ./cross -prune -false -o -iname *.h -o -iname *.c -exec clang-format-11 -n --Werror {} \;; } 2>&1) + if [ $(echo -n "$format" | head -c1 | wc -c) -ne 0 ]; then + echo "$format" + exit 1 + fi + + # TODO: Implement clang-tidy linting + # find . -path ./cross -prune -o -iname *.h -o -iname *.c | xargs clang-tidy-11 --checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling + + echo "No errors!" +} + +make_format() { + find . -path ./cross -prune -false -o -iname *.h -o -iname *.c -exec clang-format-11 -i {} \; +} + make_clean() { #rm -rf build/ $MAKE clean @@ -283,6 +300,10 @@ elif [ "${mode}" = "build" ]; then make_build elif [ "${mode}" = "clean" ]; then make_clean +elif [ "${mode}" = "lint" ]; then + make_lint +elif [ "${mode}" = "format" ]; then + make_format elif [ "${mode}" = "again" ]; then make_test elif [ "${mode}" = "disasm" ]; then @@ -313,6 +334,8 @@ else printf "\nDescription of options:\n" printf "cross\t\tBuilds the cross compiler\n" printf "clean\t\tRemoves the compiled files\n" + printf "lint\t\tLint the entire project using clang-tidy\n" + printf "format\t\tFormat the entire project using clang-format\n" printf "build\t\tBuilds the whole project (cross+clean)\n" printf "test\t\tRuns the Melvix unit tests with QEMU (cross+clean+build)\n" printf "debug\t\tEmulates Melvix with QEMU and debug options (cross+clean+build)\n" |