logind,systemctl: add reboot to EFI firmware support
This commit is contained in:
parent
3d1137ac2b
commit
5bdf22430e
|
@ -526,6 +526,18 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--firmware-setup</option></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>When used with the <command>reboot</command> command,
|
||||||
|
indicate to the system's firmware to boot into setup
|
||||||
|
mode. Note that this is currently only supported on some EFI
|
||||||
|
systems and only if the system was booted in EFI
|
||||||
|
mode.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--plain</option></term>
|
<term><option>--plain</option></term>
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ _systemctl () {
|
||||||
local -A OPTS=(
|
local -A OPTS=(
|
||||||
[STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
|
[STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
|
||||||
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
|
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
|
||||||
--quiet -q --privileged -P --system --user --version --runtime --recursive -r'
|
--quiet -q --privileged -P --system --user --version --runtime --recursive -r --firmware-setup'
|
||||||
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root'
|
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -384,5 +384,6 @@ _arguments -s \
|
||||||
{-P,--privileged}'[Acquire privileges before execution]' \
|
{-P,--privileged}'[Acquire privileges before execution]' \
|
||||||
{-n+,--lines=}'[Journal entries to show]:number of entries' \
|
{-n+,--lines=}'[Journal entries to show]:number of entries' \
|
||||||
{-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \
|
{-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \
|
||||||
|
'--firmware-setup[Tell the firmware to show the setup menu on next boot]' \
|
||||||
'--plain[When used with list-dependencies, print output as a list]' \
|
'--plain[When used with list-dependencies, print output as a list]' \
|
||||||
'*::systemctl command:_systemctl_command'
|
'*::systemctl command:_systemctl_command'
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "udev-util.h"
|
#include "udev-util.h"
|
||||||
#include "selinux-util.h"
|
#include "selinux-util.h"
|
||||||
|
#include "efivars.h"
|
||||||
#include "logind.h"
|
#include "logind.h"
|
||||||
|
|
||||||
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
|
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
|
||||||
|
@ -1850,6 +1851,104 @@ static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *u
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int property_get_reboot_to_firmware_setup(
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *path,
|
||||||
|
const char *interface,
|
||||||
|
const char *property,
|
||||||
|
sd_bus_message *reply,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(reply);
|
||||||
|
assert(userdata);
|
||||||
|
|
||||||
|
r = efi_get_reboot_to_firmware();
|
||||||
|
if (r < 0 && r != -EOPNOTSUPP)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return sd_bus_message_append(reply, "b", r > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int method_set_reboot_to_firmware_setup(
|
||||||
|
sd_bus *bus,
|
||||||
|
sd_bus_message *message,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
|
||||||
|
int b, r;
|
||||||
|
int interactive;
|
||||||
|
Manager *m = userdata;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(message);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "bb", &b, &interactive);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = bus_verify_polkit_async(message,
|
||||||
|
CAP_SYS_ADMIN,
|
||||||
|
"org.freedesktop.login1.set-reboot-to-firmware-setup",
|
||||||
|
interactive,
|
||||||
|
UID_INVALID,
|
||||||
|
&m->polkit_registry,
|
||||||
|
error);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||||
|
|
||||||
|
r = efi_set_reboot_to_firmware(b);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int method_can_reboot_to_firmware_setup(
|
||||||
|
sd_bus *bus,
|
||||||
|
sd_bus_message *message,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
bool challenge;
|
||||||
|
const char *result;
|
||||||
|
Manager *m = userdata;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(message);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
r = efi_reboot_to_firmware_supported();
|
||||||
|
if (r == -EOPNOTSUPP)
|
||||||
|
return sd_bus_reply_method_return(message, "s", "na");
|
||||||
|
else if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = bus_test_polkit(message,
|
||||||
|
CAP_SYS_ADMIN,
|
||||||
|
"org.freedesktop.login1.set-reboot-to-firmware-setup",
|
||||||
|
UID_INVALID,
|
||||||
|
&challenge,
|
||||||
|
error);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (r > 0)
|
||||||
|
result = "yes";
|
||||||
|
else if (challenge)
|
||||||
|
result = "challenge";
|
||||||
|
else
|
||||||
|
result = "no";
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, "s", result);
|
||||||
|
}
|
||||||
|
|
||||||
static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
|
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
|
||||||
const char *who, *why, *what, *mode;
|
const char *who, *why, *what, *mode;
|
||||||
|
@ -1970,6 +2069,7 @@ const sd_bus_vtable manager_vtable[] = {
|
||||||
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
|
@ -2023,6 +2123,8 @@ const sd_bus_vtable manager_vtable[] = {
|
||||||
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("SetRebootToFirmwareSetup", "bb", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
|
||||||
SD_BUS_SIGNAL("SessionNew", "so", 0),
|
SD_BUS_SIGNAL("SessionNew", "so", 0),
|
||||||
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
|
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
|
||||||
|
|
|
@ -128,6 +128,14 @@
|
||||||
send_interface="org.freedesktop.login1.Manager"
|
send_interface="org.freedesktop.login1.Manager"
|
||||||
send_member="CanHybridSleep"/>
|
send_member="CanHybridSleep"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.login1"
|
||||||
|
send_interface="org.freedesktop.login1.Manager"
|
||||||
|
send_member="CanRebootToFirmwareSetup"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.login1"
|
||||||
|
send_interface="org.freedesktop.login1.Manager"
|
||||||
|
send_member="SetRebootToFirmwareSetup"/>
|
||||||
|
|
||||||
<allow send_destination="org.freedesktop.login1"
|
<allow send_destination="org.freedesktop.login1"
|
||||||
send_interface="org.freedesktop.login1.Manager"
|
send_interface="org.freedesktop.login1.Manager"
|
||||||
send_member="AttachDevice"/>
|
send_member="AttachDevice"/>
|
||||||
|
|
|
@ -290,4 +290,14 @@
|
||||||
</defaults>
|
</defaults>
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
|
<action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
|
||||||
|
<_description>Allow indication to the firmware to boot to setup interface</_description>
|
||||||
|
<_message>Authentication is required to indicate to the firmware to boot to setup interface.</_message>
|
||||||
|
<defaults>
|
||||||
|
<allow_any>auth_admin_keep</allow_any>
|
||||||
|
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||||
|
<allow_active>auth_admin_keep</allow_active>
|
||||||
|
</defaults>
|
||||||
|
</action>
|
||||||
|
|
||||||
</policyconfig>
|
</policyconfig>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "virt.h"
|
||||||
#include "efivars.h"
|
#include "efivars.h"
|
||||||
|
|
||||||
#ifdef ENABLE_EFI
|
#ifdef ENABLE_EFI
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
|
#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
|
||||||
#define END_DEVICE_PATH_TYPE 0x7f
|
#define END_DEVICE_PATH_TYPE 0x7f
|
||||||
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
|
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
|
||||||
|
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
|
||||||
|
|
||||||
struct boot_option {
|
struct boot_option {
|
||||||
uint32_t attr;
|
uint32_t attr;
|
||||||
|
@ -93,6 +95,76 @@ int is_efi_secure_boot_setup_mode(void) {
|
||||||
return read_flag("SetupMode");
|
return read_flag("SetupMode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int efi_reboot_to_firmware_supported(void) {
|
||||||
|
int r;
|
||||||
|
size_t s;
|
||||||
|
uint64_t b;
|
||||||
|
_cleanup_free_ void *v = NULL;
|
||||||
|
|
||||||
|
if (!is_efi_boot() || detect_container(NULL) > 0)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
else if (s != sizeof(uint64_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
b = *(uint64_t *)v;
|
||||||
|
b &= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||||
|
return b > 0 ? 0 : -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_os_indications(uint64_t *os_indication) {
|
||||||
|
int r;
|
||||||
|
size_t s;
|
||||||
|
_cleanup_free_ void *v = NULL;
|
||||||
|
|
||||||
|
r = efi_reboot_to_firmware_supported();
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
else if (s != sizeof(uint64_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*os_indication = *(uint64_t *)v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int efi_get_reboot_to_firmware(void) {
|
||||||
|
int r;
|
||||||
|
uint64_t b;
|
||||||
|
|
||||||
|
r = get_os_indications(&b);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efi_set_reboot_to_firmware(bool value) {
|
||||||
|
int r;
|
||||||
|
uint64_t b, b_new;
|
||||||
|
|
||||||
|
r = get_os_indications(&b);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||||
|
else
|
||||||
|
b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||||
|
|
||||||
|
/* Avoid writing to efi vars store if we can due to firmware bugs. */
|
||||||
|
if (b != b_new)
|
||||||
|
return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int efi_get_variable(
|
int efi_get_variable(
|
||||||
sd_id128_t vendor,
|
sd_id128_t vendor,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
bool is_efi_boot(void);
|
bool is_efi_boot(void);
|
||||||
int is_efi_secure_boot(void);
|
int is_efi_secure_boot(void);
|
||||||
int is_efi_secure_boot_setup_mode(void);
|
int is_efi_secure_boot_setup_mode(void);
|
||||||
|
int efi_reboot_to_firmware_supported(void);
|
||||||
|
int efi_get_reboot_to_firmware(void);
|
||||||
|
int efi_set_reboot_to_firmware(bool value);
|
||||||
|
|
||||||
int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size);
|
int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size);
|
||||||
int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size);
|
int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size);
|
||||||
|
|
|
@ -68,6 +68,7 @@
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "dropin.h"
|
#include "dropin.h"
|
||||||
|
#include "efivars.h"
|
||||||
|
|
||||||
static char **arg_types = NULL;
|
static char **arg_types = NULL;
|
||||||
static char **arg_states = NULL;
|
static char **arg_states = NULL;
|
||||||
|
@ -132,6 +133,7 @@ static char *arg_host = NULL;
|
||||||
static unsigned arg_lines = 10;
|
static unsigned arg_lines = 10;
|
||||||
static OutputMode arg_output = OUTPUT_SHORT;
|
static OutputMode arg_output = OUTPUT_SHORT;
|
||||||
static bool arg_plain = false;
|
static bool arg_plain = false;
|
||||||
|
static bool arg_firmware_setup = false;
|
||||||
|
|
||||||
static bool original_stdout_is_tty;
|
static bool original_stdout_is_tty;
|
||||||
|
|
||||||
|
@ -2928,6 +2930,12 @@ static int start_special(sd_bus *bus, char **args) {
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg_firmware_setup) {
|
||||||
|
r = efi_set_reboot_to_firmware(true);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %m");
|
||||||
|
}
|
||||||
|
|
||||||
if (a == ACTION_REBOOT && args[1]) {
|
if (a == ACTION_REBOOT && args[1]) {
|
||||||
r = update_reboot_param_file(args[1]);
|
r = update_reboot_param_file(args[1]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -5971,6 +5979,7 @@ static void systemctl_help(void) {
|
||||||
" -o --output=STRING Change journal output mode (short, short-iso,\n"
|
" -o --output=STRING Change journal output mode (short, short-iso,\n"
|
||||||
" short-precise, short-monotonic, verbose,\n"
|
" short-precise, short-monotonic, verbose,\n"
|
||||||
" export, json, json-pretty, json-sse, cat)\n"
|
" export, json, json-pretty, json-sse, cat)\n"
|
||||||
|
" --firmware-setup Tell the firmware to show the setup menu on next boot\n"
|
||||||
" --plain Print unit dependencies as a list instead of a tree\n\n"
|
" --plain Print unit dependencies as a list instead of a tree\n\n"
|
||||||
"Unit Commands:\n"
|
"Unit Commands:\n"
|
||||||
" list-units [PATTERN...] List loaded units\n"
|
" list-units [PATTERN...] List loaded units\n"
|
||||||
|
@ -6150,6 +6159,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||||
ARG_STATE,
|
ARG_STATE,
|
||||||
ARG_JOB_MODE,
|
ARG_JOB_MODE,
|
||||||
ARG_PRESET_MODE,
|
ARG_PRESET_MODE,
|
||||||
|
ARG_FIRMWARE_SETUP,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
|
@ -6192,6 +6202,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||||
{ "state", required_argument, NULL, ARG_STATE },
|
{ "state", required_argument, NULL, ARG_STATE },
|
||||||
{ "recursive", no_argument, NULL, 'r' },
|
{ "recursive", no_argument, NULL, 'r' },
|
||||||
{ "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
|
{ "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
|
||||||
|
{ "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6432,6 +6443,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||||
arg_plain = true;
|
arg_plain = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_FIRMWARE_SETUP:
|
||||||
|
arg_firmware_setup = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case ARG_STATE: {
|
case ARG_STATE: {
|
||||||
const char *word, *state;
|
const char *word, *state;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
Loading…
Reference in a new issue