Skip to content

Commit

Permalink
Add HiiKeyboardLayout crate to support UEFI HII Keyboard Layouts (#342)
Browse files Browse the repository at this point in the history
## Description

This crate provides a rust wrapper around UEFI HII Keyboard Layout
structures. The relevant structures defined in the UEFI spec are not
well-suited for direct definition in rust; so this crate defines
analogous rust structures and provides serialization/deserialization
support for converting the rust structures into byte buffers and vice
versa. This crate uses the `scroll` crate
(https://github.com/m4b/scroll) to facilitate
serialization/deserialization of the Hii structures.

## Examples and Usage
Retrieving a default (en-US) layout, writing it to a buffer, and then
reading the buffer back into a rust structure:

```
 use hii_keyboard_layout::{get_default_keyboard_pkg, HiiKeyboardPkg};
 use scroll::{Pread, Pwrite};
 let mut buffer = [0u8; 4096];

 let package = get_default_keyboard_pkg();
 buffer.pwrite(&package, 0).unwrap();

 let package2: HiiKeyboardPkg = buffer.pread(0).unwrap();
 assert_eq!(package, package2);
```

- [x] Impacts functionality?
  - Introduces a new crate providing support for HII layouts.
- [ ] Impacts security?
- [ ] Breaking change?
- [x] Includes tests?
  - Includes standard rust unit tests. 
- [x] Includes documentation?
  - Includes standard rust documentation.

## How This Was Tested

Verified by included unit tests.

## Integration Instructions
This crate requires the "scroll," "num-traits" and "num-drive" crates,
so platforms intending to use it will need to add these as dependencies
in their workspace Cargo.toml files. This PR does this for the workspace
Cargo.toml that is at the root of mu_plus.

Sample:
``` 
scroll = { version = "0.11", default-features = false, features = ["derive"]}
num-traits = { version = "0.2", default-features = false}
num-derive = { version = "0.4", default-features = false}
  • Loading branch information
joschock authored Oct 31, 2023
1 parent 16d600a commit 0033f8e
Show file tree
Hide file tree
Showing 7 changed files with 1,063 additions and 1 deletion.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Add packages that generate binaries here
members = [
"HidPkg/Crates/HidIo",
"HidPkg/Crates/HiiKeyboardLayout",
"HidPkg/UefiHidDxe",
"MsCorePkg/HelloWorldRustDxe"
]
Expand All @@ -18,4 +19,7 @@ hidparser = {git = "https://github.com/microsoft/mu_rust_hid.git", branch = "mai
r-efi = "4.3.0"
rustversion = "1.0.14"
spin = "0.9.8"
memoffset = "0.9.0"
memoffset = "0.9.0"
scroll = { version = "0.11", default-features = false, features = ["derive"]}
num-traits = { version = "0.2", default-features = false}
num-derive = { version = "0.4", default-features = false}
15 changes: 15 additions & 0 deletions HidPkg/Crates/HiiKeyboardLayout/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "HiiKeyboardLayout"
version = "0.1.0"
edition = "2021"


[lib]
name = "hii_keyboard_layout"
path = "src/lib.rs"

[dependencies]
r-efi = {workspace=true}
scroll = {workspace=true}
num-traits = {workspace=true}
num-derive = {workspace=true}
Binary file not shown.
130 changes: 130 additions & 0 deletions HidPkg/Crates/HiiKeyboardLayout/resources/test/KeyboardLayout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
USB_KEYBOARD_LAYOUT_PACK_BIN mUsbKeyboardLayoutBin = {
sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN), // Binary size

//
// EFI_HII_PACKAGE_HEADER
//
{
sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32),
EFI_HII_PACKAGE_KEYBOARD_LAYOUT
},
1, // LayoutCount
sizeof (USB_KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32) - sizeof (EFI_HII_PACKAGE_HEADER) - sizeof (UINT16), // LayoutLength
USB_KEYBOARD_LAYOUT_KEY_GUID, // KeyGuid
sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (USB_KEYBOARD_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset
USB_KEYBOARD_KEY_COUNT, // DescriptorCount
{
//
// EFI_KEY_DESCRIPTOR (total number is USB_KEYBOARD_KEY_COUNT)
//
{ EfiKeyC1, 'a', 'A', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB5, 'b', 'B', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB3, 'c', 'C', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC3, 'd', 'D', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD3, 'e', 'E', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC4, 'f', 'F', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC5, 'g', 'G', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC6, 'h', 'H', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD8, 'i', 'I', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC7, 'j', 'J', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC8, 'k', 'K', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC9, 'l', 'L', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB7, 'm', 'M', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB6, 'n', 'N', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD9, 'o', 'O', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD10, 'p', 'P', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD1, 'q', 'Q', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD4, 'r', 'R', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyC2, 's', 'S', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD5, 't', 'T', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD7, 'u', 'U', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB4, 'v', 'V', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD2, 'w', 'W', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB2, 'x', 'X', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyD6, 'y', 'Y', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyB1, 'z', 'Z', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK },
{ EfiKeyE1, '1', '!', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE2, '2', '@', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE3, '3', '#', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE4, '4', '$', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE5, '5', '%', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE6, '6', '^', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE7, '7', '&', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE8, '8', '*', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE9, '9', '(', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE10, '0', ')', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyEsc, 0x1b, 0x1b, 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyBackSpace, 0x08, 0x08, 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyTab, 0x09, 0x09, 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeySpaceBar, ' ', ' ', 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyE11, '-', '_', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE12, '=', '+', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyD11, '[', '{', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyD12, ']', '}', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyD13, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyC12, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyC10, ';', ':', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyC11, '\'', '"', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyE0, '`', '~', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyB8, ',', '<', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyB9, '.', '>', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyB10, '/', '?', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT },
{ EfiKeyCapsLock, 0x00, 0x00, 0, 0, EFI_CAPS_LOCK_MODIFIER, 0 },
{ EfiKeyF1, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ONE_MODIFIER, 0 },
{ EfiKeyF2, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWO_MODIFIER, 0 },
{ EfiKeyF3, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_THREE_MODIFIER, 0 },
{ EfiKeyF4, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FOUR_MODIFIER, 0 },
{ EfiKeyF5, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FIVE_MODIFIER, 0 },
{ EfiKeyF6, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SIX_MODIFIER, 0 },
{ EfiKeyF7, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SEVEN_MODIFIER, 0 },
{ EfiKeyF8, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_EIGHT_MODIFIER, 0 },
{ EfiKeyF9, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_NINE_MODIFIER, 0 },
{ EfiKeyF10, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TEN_MODIFIER, 0 },
{ EfiKeyF11, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ELEVEN_MODIFIER, 0 },
{ EfiKeyF12, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWELVE_MODIFIER, 0 },
{ EfiKeyPrint, 0x00, 0x00, 0, 0, EFI_PRINT_MODIFIER, 0 },
{ EfiKeySLck, 0x00, 0x00, 0, 0, EFI_SCROLL_LOCK_MODIFIER, 0 },
{ EfiKeyPause, 0x00, 0x00, 0, 0, EFI_PAUSE_MODIFIER, 0 },
{ EfiKeyIns, 0x00, 0x00, 0, 0, EFI_INSERT_MODIFIER, 0 },
{ EfiKeyHome, 0x00, 0x00, 0, 0, EFI_HOME_MODIFIER, 0 },
{ EfiKeyPgUp, 0x00, 0x00, 0, 0, EFI_PAGE_UP_MODIFIER, 0 },
{ EfiKeyDel, 0x00, 0x00, 0, 0, EFI_DELETE_MODIFIER, 0 },
{ EfiKeyEnd, 0x00, 0x00, 0, 0, EFI_END_MODIFIER, 0 },
{ EfiKeyPgDn, 0x00, 0x00, 0, 0, EFI_PAGE_DOWN_MODIFIER, 0 },
{ EfiKeyRightArrow, 0x00, 0x00, 0, 0, EFI_RIGHT_ARROW_MODIFIER, 0 },
{ EfiKeyLeftArrow, 0x00, 0x00, 0, 0, EFI_LEFT_ARROW_MODIFIER, 0 },
{ EfiKeyDownArrow, 0x00, 0x00, 0, 0, EFI_DOWN_ARROW_MODIFIER, 0 },
{ EfiKeyUpArrow, 0x00, 0x00, 0, 0, EFI_UP_ARROW_MODIFIER, 0 },
{ EfiKeyNLck, 0x00, 0x00, 0, 0, EFI_NUM_LOCK_MODIFIER, 0 },
{ EfiKeySlash, '/', '/', 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyAsterisk, '*', '*', 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyMinus, '-', '-', 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyPlus, '+', '+', 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0 },
{ EfiKeyOne, '1', '1', 0, 0, EFI_END_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyTwo, '2', '2', 0, 0, EFI_DOWN_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyThree, '3', '3', 0, 0, EFI_PAGE_DOWN_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyFour, '4', '4', 0, 0, EFI_LEFT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyFive, '5', '5', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeySix, '6', '6', 0, 0, EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeySeven, '7', '7', 0, 0, EFI_HOME_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyEight, '8', '8', 0, 0, EFI_UP_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyNine, '9', '9', 0, 0, EFI_PAGE_UP_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyZero, '0', '0', 0, 0, EFI_INSERT_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyPeriod, '.', '.', 0, 0, EFI_DELETE_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK },
{ EfiKeyA4, 0x00, 0x00, 0, 0, EFI_MENU_MODIFIER, 0 },
{ EfiKeyLCtrl, 0, 0, 0, 0, EFI_LEFT_CONTROL_MODIFIER, 0 },
{ EfiKeyLShift, 0, 0, 0, 0, EFI_LEFT_SHIFT_MODIFIER, 0 },
{ EfiKeyLAlt, 0, 0, 0, 0, EFI_LEFT_ALT_MODIFIER, 0 },
{ EfiKeyA0, 0, 0, 0, 0, EFI_LEFT_LOGO_MODIFIER, 0 },
{ EfiKeyRCtrl, 0, 0, 0, 0, EFI_RIGHT_CONTROL_MODIFIER, 0 },
{ EfiKeyRShift, 0, 0, 0, 0, EFI_RIGHT_SHIFT_MODIFIER, 0 },
{ EfiKeyA2, 0, 0, 0, 0, EFI_RIGHT_ALT_MODIFIER, 0 },
{ EfiKeyA3, 0, 0, 0, 0, EFI_RIGHT_LOGO_MODIFIER, 0 },
},
1, // DescriptionCount
{ 'e', 'n', '-', 'U', 'S' }, // RFC4646 language code
' ', // Space
{ 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '\0' }, // DescriptionString[]
};
Binary file not shown.
Loading

0 comments on commit 0033f8e

Please sign in to comment.