1
1
mirror of https://github.com/NixOS/mobile-nixos.git synced 2024-12-16 20:21:32 +03:00

Merge pull request #245 from samueldr-wip/feature/stage-1-recovery-acknowledge

stage-1: Acknowledge recovery boot mode
This commit is contained in:
Samuel Dionne-Riel 2020-11-22 16:59:57 -05:00 committed by GitHub
commit 8f1cf6fca9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 56 deletions

View File

@ -49,6 +49,7 @@ module Tasks
# Update the current progress
count = @tasks.length.to_f
Progress.update({progress: (100 * (1 - (todo.length / count))).ceil})
Progress.update({recovery: Hal::Recovery.wants_recovery?})
todo.each do |task|
if task._try_run_task then

View File

@ -82,7 +82,7 @@ class Tasks::SwitchRoot < SingletonTask
# May pause the boot to allow the user to select a generation.
def selected_generation()
if user_wants_selection()
if Hal::Recovery.wants_recovery?
generate_selection()
# FIXME: In the future, boot GUIs will be launched async, before this
# task is ran.
@ -102,50 +102,8 @@ class Tasks::SwitchRoot < SingletonTask
end
end
def boot_as_recovery_wants_recovery()
# "Boot as recovery" systems do not have a discrete recovery partition.
# For those systems, when `[s_]kip_initramfs` is in the kernel cmdline, we
# know the intent is to boot the normal system.
# Is a "boot as recovery" device, and Is `[s_]kip_initramfs` missing?
Configuration["device"]["boot_as_recovery"] and
!File.read("/proc/cmdline").split(/\s+/).grep(/[s_]kip_initramfs/).any?
end
def is_recovery()
# Check in /etc/boot/config for `is_recovery`, it's assumed to be set, and
# true, for recovery.img.
Configuration["is_recovery"] or
boot_as_recovery_wants_recovery
end
def is_boot_interrupted()
keys = [
# Keys used for "mobile" use-cases
:KEY_VOLUMEUP,
:KEY_VOLUMEDOWN,
# Keys used for "computer" use-cases
:KEY_LEFTCTRL,
:KEY_RIGHTCTRL,
:KEY_LEFTSHIFT,
:KEY_RIGHTSHIFT,
:KEY_ESC,
]
Evdev.keys_held(keys)
end
# Checks if the user wants to select a generation.
def user_wants_selection()
[
# Booted a recovery partition.
is_recovery,
# Or signaling the boot selection menu should be shown.
is_boot_interrupted,
].any?
end
def run()
if user_wants_selection
if Hal::Recovery.wants_recovery?
Tasks::Splash.instance.quit("Continuing to recovery menu")
else
Tasks::Splash.instance.quit("Continuing to stage-2")

51
boot/lib/hal/recovery.rb Normal file
View File

@ -0,0 +1,51 @@
module Hal
module Recovery
extend self
KEYS = [
# Keys used for "mobile" use-cases
:KEY_VOLUMEUP,
:KEY_VOLUMEDOWN,
# Keys used for "computer" use-cases
:KEY_LEFTCTRL,
:KEY_RIGHTCTRL,
:KEY_LEFTSHIFT,
:KEY_RIGHTSHIFT,
:KEY_ESC,
]
def firmware_wants_recovery?()
# "Boot as recovery" systems do not have a discrete recovery partition.
# For those systems, when `[s_]kip_initramfs` is in the kernel cmdline, we
# know the intent is to boot the normal system.
# Is a "boot as recovery" device, and Is `[s_]kip_initramfs` missing?
if Configuration["device"]["boot_as_recovery"] then
if File.exists?("/proc/cmdline") then
!File.read("/proc/cmdline").split(/\s+/).grep(/[s_]kip_initramfs/).any?
end
end
end
# Is this boot image a recovery image, or booted into recovery mode by the
# device firmware?
def is_recovery?()
# Check in /etc/boot/config for `is_recovery`, it's assumed to be set, and
# true, for recovery builds.
Configuration["is_recovery"] or firmware_wants_recovery?
end
# Is the normal boot flow interrupted by a key input?
def boot_interrupted?()
Evdev.keys_held(KEYS)
end
def wants_recovery?
[
# Booted a recovery partition.
is_recovery?,
# Or signaling the boot selection menu should be shown.
boot_interrupted?,
].any?
end
end
end

View File

@ -26,6 +26,7 @@ class UI
add_logo
add_progress_bar
add_label
add_recovery
add_textarea
add_keyboard
@ -99,6 +100,34 @@ class UI
end
end
def add_recovery()
@recovery_container = LVGL::LVContainer.new(@page)
@recovery_container.set_hidden(true)
@recovery_container.set_width(@page.get_width)
@recovery_container.get_style(LVGL::CONT_STYLE::MAIN).dup.tap do |style|
@recovery_container.set_style(LVGL::CONT_STYLE::MAIN, style)
style.body_main_color = 0xFF000000
style.body_grad_color = 0xFF000000
style.body_border_width = 0
end
recovery_label = LVGL::LVLabel.new(@recovery_container)
recovery_label.get_style(LVGL::LABEL_STYLE::MAIN).dup.tap do |style|
recovery_label.set_style(LVGL::LABEL_STYLE::MAIN, style)
style.text_color = 0xFFFFFFFF
end
recovery_label.set_long_mode(LVGL::LABEL_LONG::BREAK)
recovery_label.set_align(LVGL::LABEL_ALIGN::CENTER)
recovery_label.set_width(@recovery_container.get_width() * 0.9)
recovery_label.set_text("Booting to recovery menu")
recovery_label.set_x(@recovery_container.get_width()/2 - recovery_label.get_width()/2)
recovery_label.set_y(@unit)
@recovery_container.set_height(recovery_label.get_height() + 2*@unit)
@recovery_container.set_pos(0, @page.get_height() - @recovery_container.get_height())
end
# Used to handle fade-in/fade-out
# This is because opacity handles multiple overlaid objects wrong.
def add_cover()
@ -167,6 +196,10 @@ class UI
end
end
def show_recovery_notice(val = true)
@recovery_container.set_hidden(!val)
end
def offset_page(delta)
LVGL::LVAnim.new().tap do |anim|
anim.set_exec_cb(@page, :lv_obj_set_y)

View File

@ -42,6 +42,19 @@ LVGUI.main_loop do
p msg
end
# Update the UI...
# First updating the current progress
ui.set_progress(msg["progress"])
ui.show_recovery_notice(msg["recovery"])
# Update the label as needed.
if msg["label"]
ui.set_label(msg["label"])
else
ui.set_label("")
end
# We might have a special command; handle it.
if msg["command"] then
command = msg["command"]
@ -68,18 +81,6 @@ LVGUI.main_loop do
$stderr.puts "[splash] Unexpected command #{command.to_json}..."
end
end
# Update the UI...
# First updating the current progress
ui.set_progress(msg["progress"])
# And updating the label as needed.
if msg["label"]
ui.set_label(msg["label"])
else
ui.set_label("")
end
end
end