Trình khách IRC tích hợp trong bo mạch chủ
(axleos.com)- UEFIRC là một trình khách IRC đồ họa chạy trong môi trường tiền khởi động UEFI của firmware bo mạch chủ trước khi hệ điều hành khởi chạy, cho thấy ngay cả trong môi trường dành cho bootloader vẫn có thể triển khai giao diện và tính năng mạng gần giống một ứng dụng thông thường
- Việc triển khai tận dụng driver NIC và ngăn xếp TCP mà UEFI cung cấp cho khởi động qua mạng, và backend mạng
vmnetcho QEMU giúp việc phát triển trở nên khả thi - Điểm khó nhất là xử lý giao thức TCP của UEFI trong Rust, nơi trạng thái toàn cục, callback tái nhập, buffer scatter-gather, cùng event, token, handle và protocol đan xen phức tạp
- GUI là phiên bản được mang sang UEFI của bộ công cụ GUI Rust và trình kết xuất TrueType của axle, đồng thời libgui cũng được cải tiến để hỗ trợ nhập chuột, thanh cuộn và kết xuất văn bản trong khung nhìn cuộn
- Kết quả cuối cùng gần với một dự án đùa công phu hơn là một trình khách IRC thực dụng, nhưng nó vẫn là công cụ để than phiền về ngăn xếp TCP/IP của UEFI ngay từ bên trong UEFI qua IRC
UEFIRC làm gì
- UEFIRC là một trình khách IRC đồ họa chạy trên UEFI
- Nó được viết bằng Rust và sử dụng bộ công cụ GUI cùng trình kết xuất TrueType được tạo cho không gian người dùng của axle
- Có thể kết nối tới máy chủ IRC, trò chuyện và đọc tin nhắn
- Trong quá trình phát triển, backend mạng
vmnetcho QEMU đã được sử dụng
UEFI như một sân khấu thực thi
- Bootloader của hệ điều hành được nạp với sự trợ giúp của firmware lưu trong ROM của bo mạch chủ
- BIOS trước đây có nhiều hạn chế, và tiêu chuẩn UEFI được tạo ra để thay thế
- BIOS yêu cầu bootloader khởi đầu ở chế độ 16-bit
- Cũng có yêu cầu bộ nạp giai đoạn đầu phải nằm trong 512 byte
- UEFI đặt bootloader vào môi trường 64-bit ngay từ đầu và cung cấp API cho những việc như chuyển độ phân giải hiển thị VESA, cấp phát bộ nhớ và truy cập hệ thống tệp EFI
- Đây là một bước tiến lớn so với BIOS, nhưng cũng bị đánh giá là thiết kế quá mức
Tái sử dụng tính năng khởi động qua mạng cho IRC
- Một số bootloader có thể nạp hệ điều hành qua mạng thay vì từ thiết bị khối cục bộ
- Để hỗ trợ trường hợp sử dụng này, firmware UEFI phải bao gồm ngăn xếp mạng
- Driver NIC
- Triển khai TCP
- API để các ứng dụng chạy trong môi trường tiền khởi động truy cập ngăn xếp này
- Vì bootloader không nhất thiết chỉ để nạp hệ điều hành, nên trong cùng môi trường đó cũng có thể chạy một trình khách IRC
Khó khăn khi xử lý UEFI TCP trong Rust
- Phần khó nhất của dự án là triển khai trình khách giao thức TCP của UEFI bằng Rust
- Giao thức TCP của UEFI đòi hỏi các vòng đời dữ liệu và tương tác rất khó biểu đạt trong Rust
- Trạng thái toàn cục
- Callback tái nhập
- Buffer scatter-gather
- Event, token, handle, protocol
- Mã Rust đã được kiểm thử nhiều ngày để loại bỏ rò rỉ bộ nhớ và lỗi use-after-free trong buffer nhận TCP
Sự rối rắm của NOTIFY_SIGNAL và NOTIFY_WAIT
- Chỉ nhìn tên thì rất khó đoán được cách hoạt động của API event trong UEFI
- Nếu chỉ định
NOTIFY_SIGNAL, callback sẽ được gọi khi event xảy ra, và việc dùngwait()sẽ là lỗi - Nếu chỉ định
NOTIFY_WAITrồi gọiwait(), UEFI có thể gọi callback nhiều lần trước khi event xảy ra, và khi event xảy ra thìwait()mới được giải phóng - Hai chế độ này tạo ra ý nghĩa hoàn toàn khác nhau ngay cả với cùng một callback
NOTIFY_SIGNAL: event đã xảy ra, đây là lúc làm bước tiếp theoNOTIFY_WAIT: event vẫn chưa xảy ra, đây là lúc thúc đẩy tiến trình tiếp tục
- Cuối cùng, để đệm bất đồng bộ dữ liệu gói nhận được, tác giả dùng vòng lặp
NOTIFY_WAITcùng một bộ hẹn giờ timeout ngắn
Hỗ trợ chuột và con trỏ
- Chuột không phải là thứ bắt buộc với trình khách IRC, nhưng nó khiến ứng dụng có cảm giác tương tác hơn
- Dùng Simple Pointer Protocol của UEFI để đọc chuyển động chuột và đầu vào nút bấm, rồi đưa phản hồi vị trí con trỏ vào GUI
- Simple Pointer Protocol không hỗ trợ bánh xe cuộn
- Trong UEFIRC, phải dùng phím mũi tên hoặc kéo thanh cuộn bằng con trỏ
- Vì firmware UEFI OVMF tiêu chuẩn không cung cấp được event chuột, tác giả đã build firmware UEFI tùy biến có kèm các driver và protocol cần thiết như
UsbMouseDxe - Để có thể thử UEFIRC trong QEMU, firmware UEFI đó cũng được đăng lên phần phát hành
Tỉ lệ hóa chuyển động chuột
- Driver chuột báo cáo độ thay đổi vị trí chứ không phải vị trí tuyệt đối
- Việc chỉ cộng tuyến tính
delta_x,delta_ynhư nguyên bản tạo cảm giác chậm chạp - Các hệ điều hành dùng cách tỉ lệ hóa gần hơn với việc vừa cho phép di chuyển nhanh vừa điều chỉnh tinh
- Trong cách triển khai ví dụ, độ lớn di chuyển con trỏ được nhân với giá trị áp dụng
log2()lên tổng trị tuyệt đối của lượng dịch chuyển - Con trỏ di chuyển tuyến tính dễ khiến toàn bộ môi trường có cảm giác chậm và phản hồi kém
Mô hình hóa tin nhắn IRC
- Việc mô hình hóa tin nhắn IRC tương đối đơn giản và dễ chịu
- IRC dùng định dạng dòng dựa trên văn bản, nên khá dễ parse
- Tuy nhiên, do nhiều thập kỷ mở rộng, vẫn tồn tại gánh nặng là chỉ một phần được tiêu chuẩn hóa
Dùng libgui trong UEFI
- Bộ công cụ GUI Rust của axle trước đó đã được chuẩn bị khá nhiều để có thể dùng ngoài ngữ cảnh axle, nên việc chạy nó trong UEFI không quá khó
- Công việc cốt lõi là cung cấp một triển khai
AwmWindowcó thể dùng bên trong UEFI - Sau đó có thể tận dụng nguyên vẹn nhiều tính năng của libgui
- Quản lý event
- Kết xuất phông chữ
- Ghép lớp
- Trang trí khung nhìn
- Các thành phần phức tạp như khung nhìn cuộn
Thanh cuộn và kết xuất văn bản trong khung nhìn cuộn
- libgui viết bằng C của axle đã có tính năng thanh cuộn, nhưng bản Rust vẫn còn thiếu một số phần
- Vì phần tương tác chính của UEFIRC diễn ra trong một khung nhìn cuộn đầy văn bản, nên tính năng thanh cuộn đã được triển khai lại trong libgui Rust
- Khung nhìn cuộn có chi phí kết xuất pixel lớn hơn khung nhìn kích thước cố định
- Với khung nhìn cố định, chỉ cần nghĩ tới buffer RGB kích thước
width * height - Khung nhìn cuộn phải xử lý một canvas có thể mở rộng vô hạn
- Với khung nhìn cố định, chỉ cần nghĩ tới buffer RGB kích thước
- Bộ công cụ GUI Rust của axle xử lý khung nhìn cuộn theo kiểu dựa trên tile
- Mỗi tile là một buffer pixel hình vuông rộng vài trăm pixel
- Chỉ cấp phát các tile cần thiết cho vùng mà nội dung thực sự được kết xuất
- Tính toán các tile hiển thị được rồi ghép chúng thành hình ảnh cuối cùng
- Nếu trình kết xuất TrueType gọi
putpixel()cho từng pixel của glyph, khung nhìn cuộn sẽ không biết trước toàn bộ vùng cần kết xuất, dẫn tới kém hiệu quả - Để giải quyết, polygon stack được bổ sung vào các đơn vị vẽ cơ bản như đường thẳng, hình tròn và hình chữ nhật
- Khung nhìn cuộn có thể biết trước rằng một polygon lớn sắp được vẽ và cấp phát sẵn các tile cần thiết
- Tác giả không thật sự thích việc dùng tô đa giác tùy ý như primitive cơ bản, nhưng trên thực tế nó hoạt động tốt
libgui được cải thiện trong quá trình làm UEFIRC
- Mỗi khi tạo một ứng dụng đồ họa mới, những ràng buộc và bất tiện nhỏ trong bộ công cụ GUI, IPC, giao diện driver và tính năng kernel lại lộ ra
- Trong quá trình phát triển UEFIRC, nhiều chỉnh sửa đã được đưa vào libgui
- Cung cấp event nhả chuột trái
- Hỗ trợ thay đổi kích thước động cho Label
- Label kết xuất phông TrueType thay cho phông bitmap cũ
- Button kết xuất phông TrueType thay cho phông bitmap cũ
- Trình kết xuất TrueType cung cấp nhiều thông tin layout hơn khi kết xuất glyph
- Trình phân tích TrueType mô hình hóa và phơi bày nhiều font metric hơn
- Sửa các lỗi tinh vi về layout và khoảng cách trong trình kết xuất TrueType
- TextInputView hỗ trợ callback đầu vào phím do người dùng cung cấp
Kết quả hoàn toàn không cần thiết
- Bản thân trình khách IRC là một dự án đùa công phu nên không thực sự hữu ích trong sử dụng thực tế
- Nhưng khi bực mình với ngăn xếp TCP/IP của UEFI, nó có thể dùng như một công cụ để than phiền về điều đó
- Cuối cùng, tác giả đã vào kênh IRC phát triển UEFI
#edk2từ bên trong UEFI và để lại lời chào
1 bình luận
Ý kiến trên Hacker News
Tác giả làm một client IRC đồ họa chạy chỉ trong môi trường trước khi khởi động UEFI cho vui, và còn nhét vào những tính năng quá đà như phông chữ TrueType, con trỏ, trang trí GUI
Ban đầu đây là dự án để làm thứ gì đó nhanh và nhẹ sau khi đã mệt với việc tự viết bộ thu GPS từ đầu, nhưng như mọi khi, nó mất nhiều thời gian hơn dự kiến rất nhiều
Trong bài, tác giả cũng dành khá nhiều thời gian cho phần trực quan hóa cách mô hình hóa scroll view và render vào viewport tĩnh; hy vọng mọi người xem thấy thú vị
Lúc đầu, với ý tưởng “cố nhét thứ không nên có vào UEFI”, tác giả nghĩ đến một client Twitter, nhưng đã có người làm khá tốt bằng giao thức HTTP của UEFI rồi nên quyết định tránh HTTP
Vì vậy tác giả chọn IRC, thứ chạy trên TCP và cũng mang cảm giác mạng xã hội hoàn toàn không hợp với môi trường trước khi khởi động
Tất nhiên là nói đùa. Ít nhiều là vậy
Là người theo chủ nghĩa tối giản nên tôi không cần GUI hay chuột, và UEFI dường như cũng đã nhiều hơn mức tôi cần
Client Twitter được nhắc tới ở đây: https://github.com/arata-nvm/mitnal
Trông có vẻ có thể là một cách khá ổn, và có lẽ an toàn, để tự động khôi phục các hệ thống từ xa khi bản cài đặt hỏng hoàn toàn và không thể boot bình thường
Rất hay. Nó cũng cho thấy rằng bên dưới hệ thống mà hầu hết mọi người nghĩ tới có một lớp phần mềm phức tạp và mạnh mẽ hơn ta tưởng
Người ta thường hiểu nhầm rằng hệ điều hành là “tầng thấp nhất” của stack phần mềm, nhưng thực ra còn có mã dạng firmware mới là thứ thật sự sở hữu hệ thống
Đôi khi nó làm xong việc rồi biến mất, đôi khi nó ở lại trong suốt thời gian hệ thống bật, tới mức ngay cả hệ điều hành cũng cảm thấy nó trong suốt
Có thái độ cho rằng “nó chỉ là mã cấp thấp để điều khiển thiết bị, ở đó chẳng có chuyện gì nghiêm trọng xảy ra”, nhưng nếu bên dưới đó còn nhét được cả client IRC thì hoàn toàn có thể tưởng tượng ra những việc ác ý khác
“Tại sao?” ư, rốt cuộc “tại sao” là câu hỏi kiểu gì vậy? Tôi đến HN để thấy tinh thần này
“Một nhận thức đáng sợ nhất ập đến với tôi. Việc tôi làm chẳng có lý do nào cả. Tôi biết vì sao mình làm. Tôi làm vì nghĩ nó sẽ vui. Nhưng họ sẽ hỏi ‘rốt cuộc tại sao anh lại làm chuyện này’, và nếu tôi không có một lý do đủ nghe được thì có lẽ họ sẽ tống tôi vào bệnh viện tâm thần.” — Boyd Rice
Không cần tự đánh giá thấp mình. Ở đây có một dự án client chỉ huy và kiểm soát botnet
UI hơi buồn cười
Thật sự rất tuyệt. Tôi không biết UEFI API lại dễ tiếp cận và được tài liệu hóa tốt như vậy
Tôi tò mò vòng lặp phát triển diễn ra thế nào. Chắc là chạy trong VM, nhưng mỗi lần chạy client có phải “boot” lại không
Script chạy chính sẽ tạo lại hệ thống tệp EFI chứa bản build mới của UEFIRC, rồi chuyển nó cho QEMU
Tuy nhiên khi làm GUI, phần overhead này trở nên khá phiền, nên tác giả đã cấu hình để app có thể build cho cả UEFI thuần lẫn môi trường host chạy trên Mac
Khi đổi build flag, GUI toolkit sẽ vẽ trực tiếp lên framebuffer do UEFI cung cấp, hoặc kết nối với hệ thống cửa sổ của Mac để gửi nhận sự kiện
Overhead của cách tiếp cận hai target này cũng thấy được ở entry point: https://github.com/codyd51/uefirc/blob/main/src/main.rs
Phần phân tích cú pháp tin nhắn IRC không cần trang trí gì thêm nên được phát triển bằng một bộ unit test chạy trực tiếp trên Mac, một số nằm ở đây: https://github.com/codyd51/uefirc/blob/main/src/irc/response...
Một ngày nào đó tôi muốn hoàn tất việc viết hệ điều hành cho con bot IRC của mình, vốn vẫn còn đang chạy
Có lẽ đây là điều vô dụng nhất để nói, nhưng di chuyển chuột phi tuyến tính, tức tăng tốc chuột, là thiết lập đầu tiên tôi tắt khi boot một hệ điều hành mới. Kỳ lạ là nó thực sự làm tay tôi đau
Ví dụ trên Mac có linearmouse miễn phí, còn trên Windows thì chỉ cần tắt tăng tốc. Trên Linux thì dĩ nhiên là dễ
Khi dùng tăng tốc chuột, rất khó học cảm giác ánh xạ giữa quãng đường chuột di chuyển và quãng đường trên màn hình; về lâu dài tôi cho rằng dùng không tăng tốc hiệu quả hơn
Tôi học cách này từ game thủ, và tôi nghĩ game thủ vẫn có lý do chính đáng để làm vậy
Dù là cách nào thì cảm giác rồi cũng quen thôi. Giống như bàn đạp ga của ô tô thường cũng không ánh xạ trực tiếp với tốc độ
Nếu hỏi “tại sao?”, thì vì khi UEFI lần đầu được giới thiệu, những ứng dụng cấp thấp kiểu này từng được hứa hẹn
Bên tạo ra UEFI thậm chí từng mơ sẽ thay thế cả những hệ điều hành mini chỉ để vào internet dựa trên Linux mà một số nhà cung cấp cho truy cập bằng cách nhấn phím nhất định trong lúc boot. Tôi không nhớ tên
Tôi đã xem một video trên YouTube nói khá sâu về nó; tôi nhớ ban đầu đó là một bản Linux rút gọn hoặc hệ điều hành tùy biến khác, sau đó chuyển sang ứng dụng UEFI, rồi cuối cùng hết thịnh hành
Bài viết hay. Nó làm tôi nhớ tới trò đùa Cá tháng Tư của bootloader barebox 2 năm trước. Tính năng là nếu mọi mục tiêu boot khác đều thất bại thì sẽ kết nối tới #barebox[1]
Trọng tâm bên đó là thêm hỗ trợ TCP vào barebox, chứ không có các thành phần GUI đẹp như ở đây
Giao diện chỉ là dòng lệnh, và nếu build barebox làm EFI payload thì có thể vẽ lên EFI GOP
[1]: https://lore.barebox.org/barebox/20220401145902.GF4351@telli...
Tôi lập tức nhớ đến video gần đây của Cathode Ray Dude. Video nói về QuickLook, “client email” của HP, thực ra là plugin Outlook, và đây cũng là một sản phẩm đã được triển khai rồi bán ra theo kiểu này: https://www.youtube.com/watch?v=ssob-7sGVWs
Video còn có những việc kỳ lạ hơn mà HP từng làm. Tuy nhiên dự án này làm được cả phần khó mà QuickLook đã tránh, đó là networking
Phần trực quan hóa trong bài viết hay và ấn tượng đến bất ngờ