[lib][uefi] Default implementation of BootService.SetWatchdogTimer()

The platform_watchdog_ methods are optional features that the target
platform can choose to implement.
If they are implemented, then BootService.SetWatchdogTimer() would call
them to setup the hardware watchdog.
If they are not implemented (for example presubmit targets), then
BootService.SetWatchdogTimer() would test the WEAK symbol against a NULL
pointer and error out.

To use BootService.SetWatchdogTimer(), platforms can choose to either
implement platform_watchdog_init and platform_watchdog_set_enabled, or
override the entire BootService.SetWatchdogTimer() method.
This commit is contained in:
Yi-Yo Chiang
2025-08-08 15:20:04 +08:00
committed by Kelvin Zhang
parent 7b26b7cf3a
commit e38bf65034
5 changed files with 62 additions and 3 deletions

View File

@@ -393,4 +393,5 @@ void setup_boot_service_table(EfiBootService *service) {
service->stall = stall;
service->raise_tpl = raise_tpl;
service->restore_tpl = restore_tpl;
service->set_watchdog_timer = set_watchdog_timer;
}

View File

@@ -2,10 +2,14 @@ LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
MODULE_INCLUDES += $(LOCAL_DIR)/local/include
MODULE_DEFINES=MSPACES=1
MODULE_INCLUDES += \
lib/watchdog/include \
MODULE_DEPS += \
lib/libcpp \
MODULE_SRCS += \
$(LOCAL_DIR)/uefi.cpp \
$(LOCAL_DIR)/relocation.cpp \

View File

@@ -18,7 +18,10 @@
#include "uefi_platform.h"
#include <arch/arm64.h>
#include <lib/watchdog.h>
#include <libfdt.h>
#include <lk/err.h>
#include <lk/trace.h>
#include <stdio.h>
#include <stdlib.h>
#include <uefi/protocols/gbl_efi_image_loading_protocol.h>
@@ -27,6 +30,8 @@
#include "defer.h"
#define LOCAL_TRACE 0
__WEAK EFI_STATUS efi_dt_fixup(struct EfiDtFixupProtocol *self, void *fdt,
size_t *buffer_size, uint32_t flags) {
auto offset = fdt_subnode_offset(fdt, 0, "chosen");
@@ -111,6 +116,46 @@ __WEAK EfiStatus get_timestamp_properties(EfiTimestampProperties *properties) {
return SUCCESS;
}
__BEGIN_CDECLS
// Redeclaring these as WEAK has two effects:
// 1. Since we are also including lib/watchdog.h, the compiler would ensure
// that the declarations had matching prototypes.
// 2. If the platform did not provide these methods, then these symbols would
// resolve to NULL, and can be checked at runtime.
extern __WEAK status_t platform_watchdog_init(
lk_time_t target_timeout, lk_time_t* recommended_pet_period);
extern __WEAK void platform_watchdog_set_enabled(bool enabled);
__END_CDECLS
__WEAK EfiStatus set_watchdog_timer(size_t timeout, uint64_t watchdog_code,
size_t data_size, char16_t* watchdog_data) {
if (platform_watchdog_init == nullptr || platform_watchdog_set_enabled == nullptr) {
TRACEF(
"unimplemented: platform_watchdog_init = %p "
"platform_watchdog_set_enabled = %p\n",
platform_watchdog_init, platform_watchdog_set_enabled);
return UNSUPPORTED;
}
if (timeout != 0) {
lk_time_t ignored = 0;
status_t ret = platform_watchdog_init(timeout * 1000, &ignored);
LTRACEF("platform_watchdog_init() ret=%d\n", ret);
if (ret == ERR_INVALID_ARGS) {
return INVALID_PARAMETER;
} else if (ret != NO_ERROR) {
return UNSUPPORTED;
}
platform_watchdog_set_enabled(true);
LTRACEF("enabled hw watchdog\n");
} else {
platform_watchdog_set_enabled(false);
LTRACEF("disabled hw watchdog\n");
}
return SUCCESS;
}
namespace {
const char *GetImageType(const char16_t *ImageType) {

View File

@@ -47,6 +47,10 @@ uint64_t get_timestamp();
EfiStatus get_timestamp_properties(EfiTimestampProperties *properties);
// timeout unit is in seconds.
EfiStatus set_watchdog_timer(size_t timeout, uint64_t watchdog_code,
size_t data_size, char16_t* watchdog_data);
// alloc_page/free_pages is implemented in memory_protocols.cpp
void *alloc_page(void *addr, size_t size, size_t align_log2 = PAGE_SIZE_SHIFT);
@@ -71,4 +75,4 @@ void setup_heap();
// Caled by LK once after executing UEFI application to tear down the heap
void reset_heap();
#endif
#endif

View File

@@ -7,6 +7,7 @@
*/
#pragma once
#include <lk/compiler.h>
#include <stdbool.h>
#include <stdint.h>
#include <kernel/thread.h>
@@ -14,6 +15,8 @@
#define WATCHDOG_MAGIC 'wdog'
__BEGIN_CDECLS
typedef struct watchdog {
uint32_t magic;
const char *name;
@@ -64,3 +67,5 @@ extern void platform_watchdog_pet(void);
status_t watchdog_hw_init(lk_time_t timeout);
void watchdog_hw_set_enabled(bool enabled);
__END_CDECLS