Blog

  • Site Working Better Now

    Will try to return to code!

  • I’m NOT A Web Designer

    (If you can’t tell!)

    I’m aware of some minor problems with the site like menus not looking good on mobile and missing contact forms, I’ll try to fix these eventually but will be prioritising other things.

    In the long term hopefully I’ll be able to hire someone to maintain the site but for now I have a lot of things to balance and will probably have to accept a few annoyances with site maintenance to avoid losing too much time tweaking CSS.

    If you check back in a month or so I should have the site more prepared, in the meantime I’ll try to post more updates, write some better introduction pages and ready some actual code releases. Your patience is appreciated!

  • Technical Things In Progress

    Aside from coming up with ideas for “release engineering” there are a few parts of the OS which are currently under heavy development and may or may not be ready in time for the first proper releases:

    PLIC & Driver Kit

    The system currently only supports some ad-hoc hardware drivers for testing, but does support loading Device Tree Blob files so can be extended to support real hardware drivers with a bit more work:

    • PLIC & interrupt handling code needs to be extended or rewritten to allow dynamic configuration from the DTB
    • Management of modules & drivers is not fully fleshed out yet, but is likely to work similarly to other systems (e.g. “device files” are still used currently with limited functionality but could be streamlined into a more modern configuration)
    • Alternative filesystems, advanced disk management and partitioning support will probably be delayed until after some releases or released with limited functionality (prioritising enhancements to the core filesystem instead to ensure it remains stable)
    • Framebuffer graphics can easily be added for some (emulator) targets but will likely be more problematic on real hardware
    • No work has commenced on any support for device hub technologies such as PCI & USB, support for legacy device hubs will probably be limited for a little while in favour of drivers for smaller individual devices & GPIO

    Full Self-Hosting

    The system is already quite stable when built with the custom compiler, but more work is needed especially on the assembler/linker and at the build system end in order for the OS to be able to fully recompile itself.

    In the meantime most development is done from Linux, which is a reasonable compromise and is the same way most other operating systems are developed, but the system is fairly close to being self-hosted and this is expected to go very smoothly once the new linker rewrite is finished.

    Networking Support

    I’ve been looking into a few different options to provide networking support, none of these options are perfect so the final system may come with a couple of alternatives but these probably won’t be ready in initial releases:

    • Writing a new TCP/IP stack – this is likely to be viable for small demos but is unlikely to result in a competitive system in the short term
    • Porting an existing TCP/IP stack – this is likely to be much more practical but will probably be limited to some typical “embedded networking” feature set and perhaps a bit clunky to set up for end users
    • Developing new protocols – this will likely result in a much better demonstration systems and perhaps will be more useful for fully integrated products (especially for HPC & robotics) but won’t integrate nicely with legacy tech
    • Running full networking using virtualised/emulated systems – this will probably be a good compromise for full featured networking in the mid term but won’t solve short or long term integration problems

    For the time being, some legacy internet APIs including kqueue/kevent functions are already exposed in the C library but aren’t implemented in the OS, allowing some networked programs to be built or prototyped using legacy APIs but they won’t run on the new kernel yet.

    Documentation & End User Utilities

    Documentation is currently limited and no man (manual page) program is included. This will be addressed as individual components stabilise, in the meantime you will need to check instructions printed by the individual programs or written in the source code.

    Some other utilities needed by users but not critical for development will also have been overlooked at this stage, but more programs can easily be ported later.

  • How My Audit Process Works

    During the build process for the kernel, a program just scans code for markings “NEW CODE” or “OLD CODE” in each file and prints a report. Obviously this simple method can be adapted to check for more complicated audit requirements e.g. checking that each file has been reviewed within a certain timeframe (the current process just checks which files have been written anew versus which are old code).

    Totals are rounded so will usually add up to just under 100%. This is only a simple tool and can be extended later for more thorough audit statistics!

    But this is a really powerful tool. You ever written an OS kernel? I’ve written most of one, but I did it the easy way: One piece at a time.

    // Copyright (c) 2025, Rainbow (Zak) Yani Star Fenton
    // This "audit" program is licensed under the Mulan PSL v2. You can use this
    // software according to the terms and conditions of the Mulan PSL v2.
    // You may obtain a copy of Mulan PSL v2 at:
    // http://license.coscl.org.cn/MulanPSL2
    // THIS SOFTWARE IS PROVIDED ON AN “AS IS” BASIS, WITHOUT warranties of
    // any kind, either express or implied, including but not limited to
    // non-infringement, merchantability or fit for a particular purpose.
    // See the Mulan PSL v2 for more details.
    
    #include <stdlib.h>
    #include <stddef.h>
    #include <stdio.h>
    
    #define AUDIT_TYPE_OLD      1
    #define AUDIT_TYPE_NEW      2
    #define AUDIT_TYPE_UNMARKED 3
    
    typedef struct audit_info audit_info_t;
    typedef struct audit_filelist audit_filelist_t;
    struct audit_filelist {
      const char* name;
      audit_filelist_t* next;
      int type;
      int lines;
    };
    struct audit_info {
      int filecount;
      int linecount;
      audit_filelist_t* oldcode;
      audit_filelist_t* newcode;
      audit_filelist_t* unmarkedcode;
    };
    
    int audit_filelist_countfiles(audit_filelist_t* l) {
      int total = 0;
      while (l) {
        total++;
        l = l->next;
      }
      return total;
    }
    
    int audit_filelist_countlines(audit_filelist_t* l) {
      int total = 0;
      while (l) {
        total += l->lines;
        l = l->next;
      }
      return total;
    }
    
    int usage(int argc, char** argv, const char* error) {
      FILE* out = error ? stderr : stdout;
      fprintf(out, "ABOUT:\n");
      fprintf(out, "This is a simple code audit tool to note occurrences like OLD CODE & NEW CODE\n");
      fprintf(out, "The main purpose of this tool is to help gradually remove old/third-party code from a codebase,\n");
      fprintf(out, "but it could be extended later e.g. for checking each file has been manually audited at a recent date.\n");
      fprintf(out, "This tool isn't specific to a particular programming language and can be used for config files too.\n");
      fprintf(out, "\nUSAGE:\n");
      fprintf(out, "\t%s [source files...]\n", argv[0]);
      if (error) {
        fprintf(out, "ERROR: %s\n", error);
        return -1;
      } else {
        return 0;
      }
    }
    
    int audit_check(const char* line, const char* check) {
      char c;
      while ((c = *line++) != 0) {
        if (c == check[0]) {
          const char* search = check+1;
          while (*search && *search == *line) {
            line++;
            search++;
          }
          if (!*search) {
            return 1; // Found!
          }
        }
      }
      return 0; // Not found
    }
    
    void audit_line(audit_info_t* info, audit_filelist_t* file, const char* line) {
      if (audit_check(line, "OLD CODE")) {
        file->type = AUDIT_TYPE_OLD;
      } else if (file->type == AUDIT_TYPE_UNMARKED && audit_check(line, "NEW CODE")) {
        file->type = AUDIT_TYPE_NEW;
      }
      file->lines++;
    }
    
    char linebuf[1000];
    
    int audit_run(audit_info_t* info, const char* filename) {
      FILE* f = fopen(filename, "r");
      if (!f) {
        return -1;
      }
      audit_filelist_t* filelist = malloc(sizeof(audit_filelist_t));
      if (!filelist) {
        fprintf(stderr, "ERROR: Failed to allocate memory\n");
        fclose(f);
        return -1;
      }
      filelist->name = strdup(filename);
      filelist->type = AUDIT_TYPE_UNMARKED;
      filelist->lines = 0;
      filelist->next = NULL;
      
      while (fgets(linebuf, 1000, f)) {
        audit_line(info, filelist, linebuf);
      }
      
      switch (filelist->type) {
        case AUDIT_TYPE_NEW:
          filelist->next = info->newcode;
          info->newcode = filelist;
          break;
        case AUDIT_TYPE_OLD:
          filelist->next = info->oldcode;
          info->oldcode = filelist;
          break;
        default:
          filelist->next = info->unmarkedcode;
          info->unmarkedcode = filelist;
          break;
      }
      info->linecount += filelist->lines;
      
      fclose(f);
      return 0;
    }
    
    void audit_subreport(audit_info_t* info, const char* startline, audit_filelist_t* files, FILE* out, int extrastats) {
      int nfiles = audit_filelist_countfiles(files);
      int nlines = audit_filelist_countlines(files);
      int fpercent = (int) (((double) nfiles) / ((double) (info->filecount)) * 100);
      int lpercent = (int) (((double) nlines) / ((double) (info->linecount)) * 100);
      fprintf(out, "%s %d FILES (%d%%)\t%d LINES (%d%%)\n", startline, nfiles, fpercent, nlines, lpercent);
      if (!files) {
        return;
      }
      //fprintf(out, "%s IN ", startline);
      audit_filelist_t* smallest = files;
      audit_filelist_t* largest = files;
      while (files) {
        //fprintf(out, " %s", files->name);
        if (files->lines < smallest->lines) {
          smallest = files;
        } else if (files->lines > largest->lines) {
          largest = files;
        }
        files = files->next;
      }
      //fprintf(out, "\n");
      if (extrastats) {
        fprintf(out, "%s SMALLEST %s (%d lines) LARGEST %s (%d lines)\n", startline, smallest->name, smallest->lines, largest->name, largest->lines);
      }
    }
    
    void audit_report(audit_info_t* info, FILE* out) {
      fprintf(out, "THIS IS AN AUTOGENERATED REPORT\n");
      fprintf(out, "This report was created by the 'audit' program\n");
      fprintf(out, "TOTAL %d FILES %d LINES\n", info->filecount, info->linecount);
      audit_subreport(info, "NEW CODE:     ", info->newcode, out, 0);
      audit_subreport(info, "OLD CODE:     ", info->oldcode, out, 1);
      audit_subreport(info, "UNMARKED CODE:", info->unmarkedcode, out, 1);
    }
    
    int main(int argc, char** argv) {
      audit_info_t info;
      info.filecount = 0;
      info.oldcode = NULL;
      info.newcode = NULL;
      info.unmarkedcode = NULL;
      
      for (int i = 1; i < argc; i++) {
        if (audit_run(&info, argv[i]) != 0) {
          fprintf(stderr, "ERROR: Failed to process file '%s'\n", argv[i]);
          return -1;
        }
        info.filecount++;
      }
      
      if (info.filecount < 1) {
        return usage(argc, argv, "Expecting list of source files\n");
      } else {
        audit_report(&info, stdout);
        return 0;
      }
    }
    
  • New Logo

    I messed up my original logo and domain but I’m back!

  • Current Status (tech stuff)

    In short: The build system is a mess.

    Anyone who’s worked on operating systems probably knows that the biggest challenge isn’t implementing any particular feature, it’s “release engineering” or actually getting the features that are already implemented shipped in a somewhat working & documented state with the correct versions of each component (not having everything out-of-sync).

    Individual features aside, I’m kind of half way through the release engineering, I already made some one off releases on my old site via Git just so I could prepare myself but I’ve decided I want to hopefully finish a few features then get my package manager & build system all fired up. Worst case scenario is I’ll just have to release it all as a big work-in-progress blob instead of separate documented components.

    So other than needing some work on version control in my package manager I’ve still got to make some final decisions on things like licensing and whether to provide all the code as open source (or just provide it to paying clients) which I’m open to feedback on.

  • New Site Launch

    This site is being put up as part of a casually-timed business launch while I complete my software, and is mostly intended for advertising or feedback purposes for now.

    Some site features may not work or may not render correctly yet and product downloads will be prepared in small stages, so be sure to check back for updates later!