xaizek / tos (License: GPLv3 only) (since 2018-12-07)
This is an alternative version of sources presented as part of Write Your Own OS video tutorial by Viktor Engelmann.
<root> / src / kernel.cpp (e9b80b58573e5f9262c3dbe54f68fd11ccaf6064) (8,046B) (mode 100644) [raw]
#include <cstdint>

#include <memory>
#include <utility>

#include "drv/ATA.hpp"
#include "drv/drivers.hpp"
#include "drv/keyboard.hpp"
#include "drv/mouse.hpp"
#include "fs/mbr.hpp"
#include "hwcomm/PCI.hpp"
#include "hwcomm/interrupts.hpp"
#include "net/arp.hpp"
#include "net/etherframe.hpp"
#include "net/icmp.hpp"
#include "net/ipv4.hpp"
#include "net/tcp.hpp"
#include "net/udp.hpp"
#include "utils/struct.hpp"
#include "Console.hpp"
#include "Demo.hpp"
#include "GDT.hpp"
#include "assert.hpp"
#include "memorymanagement.hpp"
#include "multiboot.hpp"
#include "multitasking.hpp"
#include "print.hpp"
#include "syscalls.hpp"

struct PrintfUDPHandler : public net::UDPHandler
{
    virtual void handleUDPMessage(net::UDPSocket &/*socket*/,
                                  span<std::uint8_t> msg) override
    {
        char foo[] = " ";
        kprint("UDP: ");
        for (std::uint8_t c : msg) {
            foo[0] = c;
            kprint(foo);
        }
    }
};

static bool
startsWith(const char s[], const char prefix[])
{
    while (*s == *prefix && *prefix != '\0') {
        ++s;
        ++prefix;
    }
    return (*prefix == '\0');
}

struct PrintfTCPHandler : public net::TCPHandler
{
    virtual bool handleTCPMessage(net::TCPSocket &socket,
                                  span<std::uint8_t> msg) override
    {
        char foo[] = " ";
        kprint("TCP: ");
        for (std::uint8_t c : msg) {
            foo[0] = c;
            kprint(foo);
        }

        if (msg.size() > 9 &&
            startsWith(reinterpret_cast<const char *>(msg.data()),
                       "GET / HTTP")) {
            char response[] = "HTTP/1.1 200 OK\r\n"
                              "Server: MyOS\r\n"
                              "Content-Type: text/html\r\n"
                              "\r\n"
                              "<html>"
                                "<head>"
                                  "<title>Test OS</title>"
                                "</head>"
                                "<body>"
                                  "<b>Test Operating System</b>"
                                  "<br/>"
                                "</body>"
                              "</html>"
                              "\r\n";
            socket.send(as_bytes(response).before(1));
            socket.disconnect();
        }

        return true;
    }
};

struct NetworkStack
{
    NetworkStack(drv::EthernetDriver *net,
                 NetOrder<std::uint32_t> gatewayIP,
                 NetOrder<std::uint32_t> subnetMask)
        : etherframe(*net), arp(etherframe),
          ipv4(etherframe, arp, gatewayIP, subnetMask),
          icmp(ipv4), udp(ipv4), tcp(ipv4)
    {
        arp.broadcastMACAddress(gatewayIP);
        icmp.requestEchoReply(gatewayIP);
    }

    net::EtherFrameProvider etherframe;
    net::ARP arp;
    net::IPProvider ipv4;
    net::ICMP icmp;
    net::UDPProvider udp;
    net::TCPProvider tcp;

    PrintfUDPHandler udpHandler;
    PrintfTCPHandler tcpHandler;
};

extern "C" void stop();

static void heapDemo(MemoryManager &mm);
static void ataDemo();
static std::unique_ptr<NetworkStack> netDemo(TaskManager &taskManager,
                                             drv::DriverManager &drvManager);
static bool strEqual(const char s[], const char t[]);

static Demo demo;

extern "C" void *
memset(void *s, int c, std::size_t n)
{
    auto p = static_cast<std::uint8_t *>(s);
    while (n-- != 0U) {
        *p++ = c;
    }

    return s;
}

extern "C" void
callConstructors()
{
    using constructor = void (*)();
    extern constructor startCtors, endCtors;

    for (constructor *ctor = &startCtors; ctor != &endCtors; ++ctor) {
        (*ctor)();
    }
}

extern "C" void
kernelEntry(multiboot_info *multibootInfo, unsigned int /*multibootMagic*/)
{
    kprint("Hello, OSless World!\n");

    std::uint32_t memupper = multibootInfo->mem_upper;
    extern void *kernelEnd;
    auto top = reinterpret_cast<std::uint8_t *>(memupper*1024 + 1*1024*1024);
    auto bottom = reinterpret_cast<std::uint8_t *>(&kernelEnd);
    MemoryManager memoryManager(bottom, top - bottom);
    kprint("heap start: 0x", &kernelEnd, "\n");
    heapDemo(memoryManager);

    GlobalDescriptorTable gdt;
    hwcomm::InterruptManager interrupts(gdt);
    SyscallHandler syscalls(0x80);

    kprint("Initializing Hardware, Stage 1\n");

    drv::DriverManager drvManager;

    drv::KeyboardDriver keyboard(demo);
    drvManager.addDriver(keyboard);

    drv::MouseDriver mouse(demo);
    drvManager.addDriver(mouse);

    hwcomm::PCIController pciController;
    pciController.selectDrivers(drvManager, interrupts);

    kprint("Initializing Hardware, Stage 2\n");
    drvManager.activateAll();

    ataDemo();

    TaskManager taskManager(gdt);

    kprint("Initializing Hardware, Stage 3\n");
    interrupts.activate();

    std::unique_ptr<NetworkStack> networkStack = netDemo(taskManager,
                                                         drvManager);

    taskManager.addTask(std::unique_ptr<Task>(new Task([]() {
        demo.run();
    })));

    stop();
}

static void
heapDemo(MemoryManager &mm)
{
    void *allocated = mm.malloc(1024);
    kprint("allocated: 0x", allocated, "\n");
    mm.free(allocated);
    allocated = mm.malloc(1024);
    kprint("allocated: 0x", allocated, "\n");
    mm.free(allocated);
}

static void
ataDemo()
{
    kprint("\nS-ATA primary master: ");
    drv::ATA ata0m(true, 0x1f0);
    ata0m.identify();

    kprint("\nS-ATA primary slave: ");
    drv::ATA ata0s(false, 0x1f0);
    ata0s.identify();

    kprint("\nS-ATA secondary master: ");
    drv::ATA ata1m(true, 0x170);
    ata1m.identify();

    kprint("\nS-ATA secondary slave: ");
    drv::ATA ata1s(false, 0x170);
    ata1s.identify();

    kprint("\n");

    fs::MBR::readPartitions(ata0m);

    // third: 0x1E8
    // fourth: 0x168
}

static std::unique_ptr<NetworkStack>
netDemo(TaskManager &taskManager, drv::DriverManager &drvManager)
{
    auto ourIP = toNetOrder<std::uint32_t>(0x0a00020f);  // 10.0.2.15
    auto gatewayIP = toNetOrder<std::uint32_t>(0x0a000202); // 10.0.2.2
    auto subnetMask = toNetOrder<std::uint32_t>(0xffffff00); // 255.255.255.0

    for (drv::Driver *drv : drvManager) {
        if (strEqual(drv->getName(), "rtl8139") ||
            strEqual(drv->getName(), "amd_am79c973")) {
            auto net = static_cast<drv::EthernetDriver *>(drv);
            net->setIPAddress(ourIP);

            kprint("MAC: ", net->getMAC().BE, "\n");

            auto networkStack = new NetworkStack(net, gatewayIP, subnetMask);

            taskManager.addTask(std::unique_ptr<Task>(new Task([=]() {
                net::UDPSocket &udpServer = networkStack->udp.listen(1234);
                networkStack->udp.bind(udpServer, &networkStack->udpHandler);

                net::UDPSocket &udpClient =
                    networkStack->udp.connect(gatewayIP, 1235);
                networkStack->udp.bind(udpClient, &networkStack->udpHandler);
                const std::uint8_t data[] = { 'H', 'e', 'l', 'l', 'o', '!' };
                udpClient.send(data);
            })));

            taskManager.addTask(std::unique_ptr<Task>(new Task([=]() {
                net::TCPSocket &tcpServer = networkStack->tcp.listen(1234);
                networkStack->tcp.bind(tcpServer, &networkStack->tcpHandler);

                net::TCPSocket &tcpClient =
                    networkStack->tcp.connect(gatewayIP, 1235);
                networkStack->tcp.bind(tcpClient, &networkStack->tcpHandler);
                const std::uint8_t data[] = { 'H', 'e', 'l', 'l', 'o', '!' };
                tcpClient.send(data);
            })));

            return std::unique_ptr<NetworkStack>(networkStack);
        }
    }

    return {};
}

static bool
strEqual(const char s[], const char t[])
{
    while (*s == *t && *s != '\0') {
        ++s;
        ++t;
    }
    return (*s == '\0');
}

extern "C" void
__cxa_pure_virtual()
{
    kassert(false, "Pure virtual function called!\n");
}
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master