Skip to content
Draft
1 change: 1 addition & 0 deletions api/core/v1alpha2/vmcondition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ const (
ReasonPodTerminating RunningReason = "PodTerminating"
ReasonPodNotFound RunningReason = "PodNotFound"
ReasonPodConditionMissing RunningReason = "PodConditionMissing"
ReasonBootFailed RunningReason = "BootFailed"
ReasonGuestNotRunning RunningReason = "GuestNotRunning"
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
index d9f61757cf..d2a0e5f6a1 100644
--- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -2020,6 +2020,14 @@ PlatformBootManagerUnableToBoot (
EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
UINTN Index;

+ {
+ STATIC CONST CHAR8 Msg[] = "No bootable device.\r\n";
+ UINTN i;
+ for (i = 0; i < sizeof (Msg) - 1; i++) {
+ IoWrite8 (0x403, (UINT8)Msg[i]);
+ }
+ }
+
if (FeaturePcdGet (PcdBootRestrictToFirmware)) {
AsciiPrint (
"%a: No bootable option was found.\n",
diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
index 9bacf9d8c7..ea78559516 100644
--- a/ShellPkg/Application/Shell/Shell.c
+++ b/ShellPkg/Application/Shell/Shell.c
@@ -359,6 +359,14 @@ UefiMain (
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn;
SPLIT_LIST *Split;

+ {
+ STATIC CONST CHAR8 Msg[] = "No bootable device.\r\n";
+ UINTN i;
+ for (i = 0; i < sizeof (Msg) - 1; i++) {
+ IoWrite8 (0x403, (UINT8)Msg[i]);
+ }
+ }
+
if (PcdGet8 (PcdShellSupportLevel) > 3) {
return (EFI_UNSUPPORTED);
}
diff --git a/ShellPkg/Application/Shell/Shell.h b/ShellPkg/Application/Shell/Shell.h
index 89b4ac6b02..cd82e6f608 100644
--- a/ShellPkg/Application/Shell/Shell.h
+++ b/ShellPkg/Application/Shell/Shell.h
@@ -42,6 +42,7 @@
#include <Library/HandleParsingLib.h>
#include <Library/FileHandleLib.h>
#include <Library/UefiHiiServicesLib.h>
+#include <Library/IoLib.h>

#include "ShellParametersProtocol.h"
#include "ShellProtocol.h"
diff --git a/ShellPkg/Application/Shell/Shell.inf b/ShellPkg/Application/Shell/Shell.inf
index f1e41de133..88b033bc35 100644
--- a/ShellPkg/Application/Shell/Shell.inf
+++ b/ShellPkg/Application/Shell/Shell.inf
@@ -66,6 +66,7 @@
SortLib
HandleParsingLib
UefiHiiServicesLib
+ IoLib

[Guids]
gShellVariableGuid ## SOMETIMES_CONSUMES ## GUID
2 changes: 2 additions & 0 deletions images/edk2/patches/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# 001-isa-debug-port-no-bootable-device-message.patch
If an EFI “No bootable device” error occurs, or the system drops into the EFI shell, output “No bootable device.” to the debug device at address 0x403.
16 changes: 16 additions & 0 deletions images/edk2/werf.inc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ git:
stageDependencies:
install:
- '*.json'
- add: {{ .ModuleDir }}/images/{{ .ImageName }}/patches
to: /src/patches
includePaths:
- '*.patch'
stageDependencies:
install:
- '*.patch'
- add: {{ .ModuleDir }}/images/{{ .ImageName }}/uefi-revocation-list
to: /src/FIRMWARE
includePaths:
Expand All @@ -68,6 +75,8 @@ shell:
- |
cd /src

echo "kek231"

echo "Git clone Edk2 repository..."
git clone \
--depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} \
Expand All @@ -90,6 +99,13 @@ shell:
submodule update --init --recursive --depth=1
fi

echo "Applying patches..."
for p in /src/patches/*.patch; do
[ -f "$p" ] || continue
echo "Applying $p"
git apply "$p"
Comment on lines +105 to +106
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
echo "Applying $p"
git apply "$p"
echo -n "Apply ${p} ... "
git apply --ignore-space-change --ignore-whitespace ${p} && echo OK || (echo FAIL ; exit 1)

For consistency with other images.

done

---

image: {{ .ModuleNamePrefix }}{{ .ImageName }}
Expand Down
132 changes: 132 additions & 0 deletions images/qemu/patches/002-no-bootable-qmp.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index fdb04fe..0cf2325 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -26,6 +26,7 @@

#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qapi/qapi-events-control.h"
#include "qemu/module.h"
#include "chardev/char-fe.h"
#include "hw/isa/isa.h"
@@ -34,6 +35,7 @@
#include "qom/object.h"

#define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
+#define DEBUGCON_NO_BOOTABLE_DEVICE "No bootable device."
OBJECT_DECLARE_SIMPLE_TYPE(ISADebugconState, ISA_DEBUGCON_DEVICE)

//#define DEBUG_DEBUGCON
@@ -42,6 +44,9 @@ typedef struct DebugconState {
MemoryRegion io;
CharBackend chr;
uint32_t readback;
+ bool watch_no_bootable_device;
+ char match_buf[sizeof(DEBUGCON_NO_BOOTABLE_DEVICE) - 1];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems there is no need to decrease size for buf length, sizeof is OK.

+ size_t match_len;
} DebugconState;

struct ISADebugconState {
@@ -51,6 +56,27 @@ struct ISADebugconState {
DebugconState state;
};

+static void debugcon_maybe_emit_no_bootable_device(DebugconState *s,
+ unsigned char ch)
+{
+ if (!s->watch_no_bootable_device) {
+ return;
+ }
+
+ if (s->match_len < sizeof(s->match_buf)) {
+ s->match_buf[s->match_len++] = ch;
+ } else {
+ memmove(s->match_buf, s->match_buf + 1, sizeof(s->match_buf) - 1);
+ s->match_buf[sizeof(s->match_buf) - 1] = ch;
+ }
+
+ if (s->match_len == sizeof(s->match_buf) &&
+ memcmp(s->match_buf, DEBUGCON_NO_BOOTABLE_DEVICE,
+ sizeof(s->match_buf)) == 0) {
+ qapi_event_send_no_bootable_device();
+ }
+}
+
static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
@@ -64,6 +90,7 @@ static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
+ debugcon_maybe_emit_no_bootable_device(s, ch);
}


@@ -118,6 +145,8 @@ static Property debugcon_isa_properties[] = {
DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9),
DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
DEFINE_PROP_UINT32("readback", ISADebugconState, state.readback, 0xe9),
+ DEFINE_PROP_BOOL("watch-no-bootable", ISADebugconState,
+ state.watch_no_bootable_device, false),
DEFINE_PROP_END_OF_LIST(),
};

diff --git a/qapi/control.json b/qapi/control.json
index 336386f..e1e727e 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -209,3 +209,13 @@
'*pretty': 'bool',
'chardev': 'str'
} }
+
+##
+# @NO_BOOTABLE_DEVICE:
+#
+# Emitted when `isa-debugcon` with enabled no-bootable watching
+# receives the string "No bootable device.".
+#
+# Since: 0.14
+##
+{ 'event': 'NO_BOOTABLE_DEVICE' }
diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c
index 22957fa..9b4840e 100644
--- a/tests/qtest/qmp-test.c
+++ b/tests/qtest/qmp-test.c
@@ -337,6 +337,25 @@ static void test_qmp_missing_any_arg(void)
qtest_quit(qts);
}

+static void test_qmp_no_bootable_device_event(void)
+{
+ static const char trigger[] = "No bootable device.";
+ QTestState *qts;
+ size_t i;
+
+ qts = qtest_initf("-nodefaults -machine q35 "
+ "-chardev null,id=debugcon "
+ "-device isa-debugcon,iobase=0x402,chardev=debugcon,"
+ "watch-no-bootable=on");
+
+ for (i = 0; i < sizeof(trigger) - 1; i++) {
+ qtest_outb(qts, 0x402, trigger[i]);
+ }
+
+ qtest_qmp_eventwait(qts, "NO_BOOTABLE_DEVICE");
+ qtest_quit(qts);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -348,6 +367,8 @@ int main(int argc, char *argv[])
#endif
qtest_add_func("qmp/preconfig", test_qmp_preconfig);
qtest_add_func("qmp/missing-any-arg", test_qmp_missing_any_arg);
+ qtest_add_func("qmp/no-bootable-device-event",
+ test_qmp_no_bootable_device_event);

return g_test_run();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/scripts/layoutrom.py b/scripts/layoutrom.py
index 6616721..4f655dc 100755
--- a/scripts/layoutrom.py
+++ b/scripts/layoutrom.py
@@ -564,7 +564,7 @@ def parseObjDump(file, fileid):

if state == 'section':
try:
- idx, name, size, vma, lma, fileoff, align = line.split()
+ idx, name, size, vma, lma, fileoff, align, *_flags = line.split()
if align[:3] != '2**':
continue
section = Section()
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
diff --git a/src/boot.c b/src/boot.c
index 1effd80..ec5992f 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -21,6 +21,7 @@
#include "string.h" // memset
#include "util.h" // irqtimer_calc
#include "tcgbios.h" // tpm_*
+#include "x86.h" // outb

/****************************************************************
* Helper search functions
@@ -960,12 +961,23 @@ boot_rom(u32 vector)
}

// Unable to find bootable device - warn user and eventually retry.
+static void
+write_port_403(const char *s)
+{
+ if (!CONFIG_DEBUG_IO || !runningOnQEMU())
+ return;
+
+ for (; *s; s++)
+ outb(*s, 0x403);
+}
+
static void
boot_fail(void)
{
- if (BootRetryTime == (u32)-1)
+ if (BootRetryTime == (u32)-1) {
printf("No bootable device.\n");
- else
+ write_port_403("No bootable device.\n");
+ } else
printf("No bootable device. Retrying in %d seconds.\n"
, BootRetryTime/1000);
// Wait for 'BootRetryTime' milliseconds and then reboot.
11 changes: 11 additions & 0 deletions images/qemu/patches/seabios/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Patches

## 001-alt-skip-flags-when-parse-objdump-section.patch

This patch makes `scripts/layoutrom.py` tolerate extra flags in `objdump`
section output.

## 002-0x403-debug-port-no-bootable-device-message.patch

If SeaBIOS cannot find a bootable device on QEMU, this patch also outputs
`No bootable device.` to the debug device at address `0x403`.
12 changes: 11 additions & 1 deletion images/qemu/werf.inc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ shell:

fi

echo "Apply SeaBIOS patches"
for p in /patches/seabios/*.patch ; do
[ -f "$p" ] || continue
git -C roms/seabios apply --check --ignore-space-change --ignore-whitespace "$p" >/dev/null 2>&1 || (echo "FAIL" ; exit 1)
echo -n "Apply ${p} to roms/seabios ... "
git -C roms/seabios apply --ignore-space-change --ignore-whitespace "$p" && echo OK || (echo FAIL ; exit 1)
done

---
{{- $name := print $.ImageName "-dependencies" -}}
{{- define "$name" -}}
Expand Down Expand Up @@ -201,6 +209,9 @@ shell:

cd /{{ $gitRepoName }}-{{ $version }}

echo "Building patched SeaBIOS..."
make -C roms bios V=1 PYTHON=python3 HOSTCC=gcc -j$(nproc)

for p in /patches/*.patch ; do
echo -n "Apply ${p} ... "
git apply --ignore-space-change --ignore-whitespace ${p} && echo OK || (echo FAIL ; exit 1)
Expand Down Expand Up @@ -346,7 +357,6 @@ shell:

{{- $_ := set $ "ProjectName" (list $.ImageName "qemu" | join "/") }}
{{- include "image-build.build" (set $ "BuildCommand" `make -j$(nproc)`) | nindent 6 }}

setup:
- |
/install-qemu.sh --version-num "{{ $version }}" \
Expand Down
3 changes: 2 additions & 1 deletion images/virt-artifact/werf.inc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ shell:
install:
- |
echo "Git clone {{ $gitRepoName }} repository..."
git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt
echo "kek231dddd"
git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch v1.6.2-virtualization-no-bootable /src/kubevirt

rm -rf /src/kubevirt/.git

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.Virtual
if kvvmi != nil && vm.Status.Phase != v1alpha2.MachineStopped {
vm.Status.Node = kvvmi.Status.NodeName

for _, c := range kvvmi.Status.Conditions {
if string(c.Type) == "BootFailed" {
cb.Reason(vmcondition.ReasonBootFailed).Status(metav1.ConditionFalse).Message(c.Reason)
conditions.SetCondition(cb, &vm.Status.Conditions)
return nil
}
}

if vm.Status.Phase == v1alpha2.MachineRunning {
cb.Reason(vmcondition.ReasonVirtualMachineRunning).Status(metav1.ConditionTrue)
conditions.SetCondition(cb, &vm.Status.Conditions)
Expand Down
Loading