Kernel Implementation: Printing Functions

The starting kernel code you are provided will includes logic to find a terminal_write function, which allows you to print characters to the screen after your kernel boots. We are going to need to print different types of values like individual characters, strings, integers, and pointers.

Please implement the following printing functions in your kernel:

void kprint_c(char c)
Print a single character to the terminal
void kprint_s(const char* str)
Print a string to the terminal
void kprint_d(uint64_t value)
Print an unsigned 64-bit integer value to the terminal in decimal notation (no leading zeros please!)
void kprint_x(uint64_t value)
Print an unsigned 64-bit integer value to the terminal in lowercase hexadecimal notation (no leading zeros or “0x” please!)
void kprint_p(void* ptr)
Print the value of a pointer to the terminal in lowercase hexadecimal with the prefix “0x”

As you work on your implementations, keep in mind that we do not have access to malloc and free functions (we haven’t written them yet). That means any space you need to print values will have to be of some known size that you can reserve in a local array.

You may have noticed that these functions match the printf flags for printing these types. You might find it useful to try printing values with the corresponding printf flag to see how your printing code should behave.

Implementation of kprintf

As a follow-up to this assigment, we implemented a simple kprintf function in class. To deal with variadic arguments you will need to include stdarg.h.

void kprintf(const char* format, ...) {
  // Start processing variadic arguments
  va_list args;
  va_start(args, format);

  // Loop until we reach the end of the format string
  size_t index = 0;
  while (format[index] != '\0') {
    // Is the current charater a '%'?
    if (format[index] == '%') {
      // Yes, print the argument
      index++;
      switch(format[index]) {
        case '%':
          kprint_c('%');
          break;
        case 'c':
          kprint_c(va_arg(args, int));
          break;
        case 's':
          kprint_s(va_arg(args, char*));
          break;
        case 'd':
          kprint_d(va_arg(args, uint64_t));
          break;
        case 'x':
          kprint_x(va_arg(args, int64_t));
          break;
        case 'p':
          kprint_p(va_arg(args, void*));
          break;
        default:
          kprint_s("<not supported>");
      }
    } else {
      // No, just a normal character. Print it.
      kprint_c(format[index]);
    }
    index++;
  }

  // Finish handling variadic arguments
  va_end(args);
}