• Home
  • About
    • Organization Structure
    • Organizing Committee
    • Privacy Policy
  • Membership
    • Apply for Membership
    • Membership Info
    • Our Members
  • Summits
    • 2024 Summit
    • 2022 Summit
    • 2020 Summit
    • 2019 Summit
    • 2018 Summit
  • Resources
    • About seL4®
    • seL4® Foundation
    • TCCoE Repository
    • Existing Platforms and Capabilities
  • Training
  • Contact
⟵ Exercise-7
table of contents
Exercise-9 ⟶

seL4 Level-1 Tutorials - Exercise #8: I/O Keyboard

Objectives
  • Initialize keyboard driver.
  • Pass I/O port capabilities of the driver to a child process.
  • Customize the I/O operations in the child process.
  • Capture input in the child process and send it to the main process.
Background
The seL4 platform support libraries already define a keyboard device driver – capturing input from the keyboard is similar to how we initialized the timer in an earlier exercise. Once I/O operations are set up, it is rather straightforward. All of this is true when operating within the rootserver, which contains bootinfo and sets up allocators with ease.
In order to talk to I/O devices, I/O ports must be established as capabilities. The default behavior for the keyboard driver is to instantiate a capability when a write/read command is requested to/from an I/O port. This requires an initialized allocation environment. Unfortunately, the child process does not have the same information as the rootserver, and setting up allocation in the child process is a lengthy and complicated procedure.
Fortunately, we do not have to strictly follow the driver’s method of allocating capabilities for every read/write request. We can actually override that behavior with a customized one. For a keyboard driver, we already know there are only two I/O ports we need to talk to. Therefore, we can instantiate two capabilities in the rootserver, and pass them to the child process instead. Then, we can customize a cookie and override the read/write requests in the child process in such a way that they do not need any allocation, and just directly use the capabilities received from the rootserver.
Therefore, the alternative implementation allows us to completely initialize the keyboard driver using the rootserver process, and then pass the capabilities needed to communicate with the driver to the child process. The child process is completely blind to any allocation mechanisms, and it only knows how to communicate with the keyboard and capture its input.
Steps
1. Initialize build environment:
$ cd /home/$USER/sel4-files $ container # if using our environment setup $ cd level-1-tutorials $ ./init-build exercise-8 x86 $ cd application/build/exercose-8-x86 $ ninja # RUN THE FOLLOWING IN A SEPERATE TERMINAL OUTSIDE OF 'container' $ ./simulate -g '-vga std' # use Ctrl + A ⟶ X to quit qemu # use Ctrl + Alt + G to release mouse from qemu
The output should be:
2. Manual initialization of I/O port capabilities (TODO #1 and TODO #2 in main.c). We determined that the control port is 0x64 and the data port is 0x60 for the keyboard device. Accordingly, we will manually allocate those capabilities for TODO #1:
simple_get_IOPort_cap(simple_t *simple, int start_port, int end_port, seL4_CPtr cnode_root, seL4_CPtr index, seL4_Word depth) - simple: pointer to initialized simple - start_port: the start or IO port range - end_port: the end of IO port range - cnode_root: cspace to place the capability (hint ctrl_path.cptr) - index: where to place capability within root_cnode (ctrl_path.capPtr) - depth: depth of each capability bits (seL4_WordBits) - RETURNS: error code (0 on success)
Recompile and Simulate. The output should be:
3. Set the control and data port capabilities in the child process (TODO #3 in process.c). The capabilities are already passed to the child process when it is spawned. And the child process already gets a reference to the first passed capability it received. From Exercise-5, we know the first capability is the endpoint capability used for communication. Accordingly, the control and data capabilities come after it. To access them, we can just increment the counter by one and it should work just fine:
((seL4_CPtr)CAPS) + 1; // second capability minted by Main process to this process ((seL4_CPtr)CAPS) + 2; // third capability minted by Main process to this process
Recompile and Simulate. The output should be:
4. Customize the cookie (TODO #4 in process.c). We have created a custom cookie that only contains two capabilities: control and data port capabilities (port_control and port_data, respectively). The task is to set those capabilities properly in the keyboard_get_io_port_ops function (in process.c).
cookie->port_control cookie->port_data
Recompile and Simulate. The output should be:
5. Customize the I/O operations (TODO #5 in process.c). The last part is to let the driver framework understand how to communicate with the keyboard. And it needs to know this information before attempting to communicate with the keyboard. Accordingly, we need to set the in and out functions to our custom functions (defined in process.c), and also set the cookie to our custom cookie. The functions we defined already use the custom cookie format, so they will understand the cookie without issues.
ops->io_port_in_fn ops->io_port_out_fn ops->cookie
Recompile and Simulate. The output should be:
6. Once everything is set up, the keyboard is only set to capture input in the child process (must select Qemu window to capture your input) and pass it to the main process. However, it does not send them character-by-character. Rather, it waits for either a newline character or for the total number of typed characters to exceed 30 before it sends message to the main thread. The main thread will then display the message it received.
Note: read the function init_cdev in process.c: this function uses the I/O operations structure to initialize communication with the keyboard. If the I/O operations structure is invalid, the whole procedure fails. This is why we customized it with our cookie, and with the new execution logic, it has no problem verifying that everything works as intended.
Learned APIs & Structures
  • simple_get_IOPort_cap
  • ps_io_ops_t
  • ps_io_port_ops_t
  • ps_chardevice_t
⟵ Exercise-7
table of contents
Exercise-9 ⟶
seL4 is a trademark of LF Projects, LLC. Trusted Computing Center of Excellence™ is a tradename of The Computing Center of Excellence, Inc. Copyright © 2022 The Computing Center of Excellence, Inc.

We use cookies to enable essential functionality on our website, and analyze website traffic. By clicking Accept you consent to our use of cookies. Read about how we use cookies.

Your Cookie Settings

We use cookies to enable essential functionality on our website, and analyze website traffic. Read about how we use cookies.

Cookie Categories
Essential

These cookies are strictly necessary to provide you with services available through our websites. You cannot refuse these cookies without impacting how our websites function. You can block or delete them by changing your browser settings, as described under the heading "Managing cookies" in the Privacy and Cookies Policy.

Analytics

These cookies collect information that is used in aggregate form to help us understand how our websites are being used or how effective our marketing campaigns are.