Skip to content

Commit 959f763

Browse files
programmerlexiMintsuki
authored andcommitted
lib/bli: implement entry control
1 parent bc5d1e4 commit 959f763

File tree

3 files changed

+125
-36
lines changed

3 files changed

+125
-36
lines changed

common/lib/bli.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ void init_bli(void) {
9191

9292
uint64_t features = (1 << 0) | // Timeout control
9393
(1 << 1) | // Oneshot timeout control
94+
(1 << 2) | // Default entry control
95+
(1 << 3) | // Oneshot entry control
9496
(1 << 13); // menu-disabled support
9597
gRT->SetVariable(L"LoaderFeatures",
9698
&bli_vendor_guid,
@@ -160,4 +162,51 @@ bool bli_update_timeout(size_t *timeout, bool *skip_timeout) {
160162
return handle_timeout(L"LoaderConfigTimeout", false, timeout, skip_timeout);
161163
}
162164

165+
static bool handle_entry(wchar_t *variable, bool erase, char *path, size_t buf_size) {
166+
wchar_t wide_path[256];
167+
UINTN getvar_size = sizeof(wide_path) - 2;
168+
uint32_t attrs;
169+
if (gRT->GetVariable(variable,
170+
&bli_vendor_guid,
171+
&attrs,
172+
&getvar_size,
173+
wide_path) == 0 && getvar_size > 0) {
174+
if (erase) {
175+
gRT->SetVariable(variable, &bli_vendor_guid,
176+
attrs,
177+
0, NULL);
178+
}
179+
180+
size_t i;
181+
for (i = 0; i < buf_size-1 && i * 2 < getvar_size; i++) {
182+
path[i] = wide_path[i] & 0xff; // Assume 0x00 - 0x7f
183+
}
184+
path[i] = 0;
185+
186+
return true;
187+
}
188+
return false;
189+
}
190+
191+
bool bli_get_default_entry(char *path, size_t buf_size) {
192+
return handle_entry(L"LoaderEntryDefault", false, path, buf_size);
193+
}
194+
195+
bool bli_get_oneshot_entry(char *path, size_t buf_size) {
196+
return handle_entry(L"LoaderEntryOneShot", true, path, buf_size);
197+
}
198+
199+
void bli_set_selected_entry(const char *path) {
200+
wchar_t wide_path[256];
201+
size_t pos = 0;
202+
for (; pos < 256 && pos < strlen(path); pos++) {
203+
wide_path[pos] = path[pos];
204+
}
205+
gRT->SetVariable(L"LoaderEntrySelected",
206+
&bli_vendor_guid,
207+
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
208+
strlen(path)*2 + 1,
209+
wide_path);
210+
}
211+
163212
#endif

common/lib/bli.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ void init_bli(void);
77
void bli_on_boot(void);
88
bool bli_update_oneshot_timeout(size_t *timeout, bool *skip_timeout);
99
bool bli_update_timeout(size_t *timeout, bool *skip_timeout);
10+
void bli_set_selected_entry(const char *path);
11+
bool bli_get_default_entry(char *path, size_t buf_size);
12+
bool bli_get_oneshot_entry(char *path, size_t buf_size);
1013

1114
#endif
1215

common/menu.c

Lines changed: 73 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,56 +1125,92 @@ noreturn void _menu(bool first_run) {
11251125

11261126
size_t selected_entry = 0;
11271127

1128-
char *default_entry = config_get_value(NULL, 0, "DEFAULT_ENTRY");
1129-
if (default_entry != NULL) {
1130-
bool is_index = true;
1131-
for (const char *p = default_entry; *p != '\0'; p++) {
1132-
if (*p < '0' || *p > '9') {
1133-
is_index = false;
1134-
break;
1135-
}
1136-
}
1137-
if (is_index) {
1138-
selected_entry = strtoui(default_entry, NULL, 10);
1139-
if (selected_entry)
1140-
selected_entry--;
1141-
} else {
1142-
// Copy the path since find_entry_by_path calls config_get_value
1143-
// internally (via should_skip_entry), which clobbers the static buffer.
1144-
char default_entry_path[256];
1145-
size_t len = strlen(default_entry);
1146-
if (len >= sizeof(default_entry_path)) {
1147-
len = sizeof(default_entry_path) - 1;
1148-
}
1149-
memcpy(default_entry_path, default_entry, len);
1150-
default_entry_path[len] = '\0';
1128+
bool has_entry = false;
1129+
1130+
#if defined (UEFI)
1131+
{
1132+
char path[256];
1133+
if (bli_get_oneshot_entry(path, 256)) {
1134+
// Find the entry with this path, expand directories, and get its index.
11511135
struct menu_entry *found_entry = NULL;
11521136
size_t found_index = 0;
1153-
find_entry_by_path(default_entry_path, menu_tree, 0, &found_entry, &found_index, true);
1137+
find_entry_by_path(path, menu_tree, 0, &found_entry, &found_index, true);
11541138
if (found_entry != NULL) {
11551139
selected_entry = found_index;
1140+
has_entry = true;
1141+
}
1142+
}
1143+
}
1144+
#endif
1145+
1146+
if (!has_entry) {
1147+
char *default_entry = config_get_value(NULL, 0, "DEFAULT_ENTRY");
1148+
if (default_entry != NULL) {
1149+
bool is_index = true;
1150+
for (const char *p = default_entry; *p != '\0'; p++) {
1151+
if (*p < '0' || *p > '9') {
1152+
is_index = false;
1153+
break;
1154+
}
1155+
}
1156+
if (is_index) {
1157+
selected_entry = strtoui(default_entry, NULL, 10);
1158+
if (selected_entry)
1159+
selected_entry--;
1160+
} else {
1161+
// Copy the path since find_entry_by_path calls config_get_value
1162+
// internally (via should_skip_entry), which clobbers the static buffer.
1163+
char default_entry_path[256];
1164+
size_t len = strlen(default_entry);
1165+
if (len >= sizeof(default_entry_path)) {
1166+
len = sizeof(default_entry_path) - 1;
1167+
}
1168+
memcpy(default_entry_path, default_entry, len);
1169+
default_entry_path[len] = '\0';
1170+
struct menu_entry *found_entry = NULL;
1171+
size_t found_index = 0;
1172+
find_entry_by_path(default_entry_path, menu_tree, 0, &found_entry, &found_index, true);
1173+
if (found_entry != NULL) {
1174+
selected_entry = found_index;
1175+
}
11561176
}
11571177
}
11581178
}
11591179

11601180
#if defined (UEFI)
1161-
char *remember_last = config_get_value(NULL, 0, "REMEMBER_LAST_ENTRY");
1162-
if (remember_last != NULL && strcasecmp(remember_last, "yes") == 0) {
1163-
char last_entry_path[256];
1164-
UINTN getvar_size = sizeof(last_entry_path);
1165-
if (gRT->GetVariable(L"LimineLastBootedEntry",
1166-
&limine_efi_vendor_guid,
1167-
NULL,
1168-
&getvar_size,
1169-
last_entry_path) == 0 && getvar_size > 0) {
1170-
// Ensure NUL termination
1171-
last_entry_path[getvar_size < sizeof(last_entry_path) ? getvar_size : sizeof(last_entry_path) - 1] = '\0';
1181+
if (!has_entry) {
1182+
char *remember_last = config_get_value(NULL, 0, "REMEMBER_LAST_ENTRY");
1183+
if (remember_last != NULL && strcasecmp(remember_last, "yes") == 0) {
1184+
char last_entry_path[256];
1185+
UINTN getvar_size = sizeof(last_entry_path);
1186+
if (gRT->GetVariable(L"LimineLastBootedEntry",
1187+
&limine_efi_vendor_guid,
1188+
NULL,
1189+
&getvar_size,
1190+
last_entry_path) == 0 && getvar_size > 0) {
1191+
// Ensure NUL termination
1192+
last_entry_path[getvar_size < sizeof(last_entry_path) ? getvar_size : sizeof(last_entry_path) - 1] = '\0';
1193+
// Find the entry with this path, expand directories, and get its index.
1194+
struct menu_entry *found_entry = NULL;
1195+
size_t found_index = 0;
1196+
find_entry_by_path(last_entry_path, menu_tree, 0, &found_entry, &found_index, true);
1197+
if (found_entry != NULL) {
1198+
selected_entry = found_index;
1199+
has_entry = true;
1200+
}
1201+
}
1202+
}
1203+
}
1204+
if (!has_entry) {
1205+
char path[256];
1206+
if (bli_get_default_entry(path, 256)) {
11721207
// Find the entry with this path, expand directories, and get its index.
11731208
struct menu_entry *found_entry = NULL;
11741209
size_t found_index = 0;
1175-
find_entry_by_path(last_entry_path, menu_tree, 0, &found_entry, &found_index, true);
1210+
find_entry_by_path(path, menu_tree, 0, &found_entry, &found_index, true);
11761211
if (found_entry != NULL) {
11771212
selected_entry = found_index;
1213+
has_entry = true;
11781214
}
11791215
}
11801216
}
@@ -1469,6 +1505,7 @@ noreturn void _menu(bool first_run) {
14691505
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
14701506
strlen(entry_path) + 1,
14711507
entry_path);
1508+
bli_set_selected_entry(entry_path);
14721509
#endif
14731510

14741511
boot(selected_menu_entry->body);

0 commit comments

Comments
 (0)