Search code examples
ckernelosdev

ps/2 configuration byte system flag is not set


When I read the ps/2 configuration byte, the system flag is not set even though it should be?

Here's how I read it:

    char buffer;
    asm volatile("inb $0x64, %%al; mov %%al, %0" : "=r" (buffer) : : "rax");
    asm ("movb $0x20, %al; outb %al, $0x64");
    asm volatile("inb $0x60, %%al; mov %%al, %0" : "=r" (buffer) :: "rax");

And the value of the buffer is: 01100001

The 2nd bit is the system flag and it is clearly not set (unless ps/2 is big endian?)

OSDEV wiki literally says that if the system flag is not set, your OS shouldnt be running enter image description here

Edit: adding that the code was run under QEMU, as comments are not always permanent.


Solution

  • It turns out that the answer to your question is that the system flag isn't set in the configuration byte because QEMU doesn't ever set it.

    Reading the byte under QEMU returns 0x61/01100001 (bit 2, the system flag, is not set). However, running the same code under VirtualBox, which appears to perform (or at least simulate) POST, the value is 0x45/01000101 (bit 5 is cleared to indicate a second PS/2 port).

    The relevant code is in the QEMU source tree in hw/input/pckbd.c. It's a little hard to align with the OSDev Wiki, because the naming and descriptions aren't always consistent - in particular, the first and second PS/2 ports are specifically referred to as 'keyboard' and 'mouse'. (If my memory is correct here, the keyboard always had to be on the first port, because the mouse used extra pin signals the keyboard didn't).

    What OSDev calls the Controller Configuration Byte, QEMU calls the Controller Mode Register, and is stored in a byte called mode. The flags are indicated by a series of #define values:

    /* Controller Mode Register Bits */
    #define KBD_MODE_KBD_INT        0x01    /* Keyboard data generate IRQ1 */
    #define KBD_MODE_MOUSE_INT      0x02    /* Mouse data generate IRQ12 */
    #define KBD_MODE_SYS            0x04    /* The system flag (?) */
    #define KBD_MODE_NO_KEYLOCK     0x08    /* The keylock doesn't affect the keyboard if set */
    #define KBD_MODE_DISABLE_KBD    0x10    /* Disable keyboard interface */
    #define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
    #define KBD_MODE_KCC            0x40    /* Scan code conversion to PC format */
    #define KBD_MODE_RFU            0x80
    

    There's definitely some inconsistency with OSDev, including bit 3, which OSDev states "Should be zero", but QEMU seems to indicate that it can be set:

    #define KBD_MODE_NO_KEYLOCK     0x08    /* The keylock doesn't affect the keyboard if set */
    

    except that KBD_MODE_NO_KEYLOCK isn't used anywhere.

    The particular #define that refers to the system flag:

    #define KBD_MODE_SYS            0x04    /* The system flag (?) */
    

    is never used either, and isn't part of the default initialized value of mode. Based on the comment, they don't even seem to know what it is.