[lib][uefi] Implement EFI_ERASE_BLOCK protocol

This commit is contained in:
Yi-Yo Chiang
2025-09-01 19:33:19 +08:00
committed by Kelvin Zhang
parent 91a76a9a03
commit fb9c37cbd6
3 changed files with 63 additions and 0 deletions

View File

@@ -259,6 +259,11 @@ EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
ts->get_properties = get_timestamp_properties;
*intf = reinterpret_cast<void *>(ts);
return EFI_STATUS_SUCCESS;
} else if (guid_eq(protocol, EFI_ERASE_BLOCK_PROTOCOL_GUID)) {
printf("%s(EFI_ERASE_BLOCK_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
"controller_handle=%p, attr=0x%x)\n",
__FUNCTION__, handle, agent_handle, controller_handle, attr);
return open_efi_erase_block_protocol(handle, intf);
}
printf("%s is unsupported 0x%x 0x%x 0x%x 0x%llx\n", __FUNCTION__,
protocol->data1, protocol->data2, protocol->data3,

View File

@@ -18,17 +18,20 @@
#include "uefi_platform.h"
#include <arch/arm64.h>
#include <lib/bio.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/erase_block_protocol.h>
#include <uefi/protocols/gbl_efi_image_loading_protocol.h>
#include <uefi/protocols/gbl_efi_os_configuration_protocol.h>
#include <uefi/types.h>
#include "defer.h"
#include "memory_protocols.h"
#define LOCAL_TRACE 0
@@ -181,6 +184,39 @@ template <typename T> T clamp(T n, T lower, T upper) {
return n;
}
struct EfiEraseBlockInterface {
EfiEraseBlockProtocol protocol;
bdev_t* dev;
};
EfiStatus erase_blocks(EfiEraseBlockProtocol* self, uint32_t media_id,
uint64_t lba, EfiEraseBlockToken* token, size_t size) {
LTRACEF("media_id=%d, lba=0x%llx, token=%p, size=0x%zx\n", media_id, lba,
token, size);
bdev_t* dev = reinterpret_cast<EfiEraseBlockInterface*>(self)->dev;
if (dev == NULL) {
LTRACEF("block dev is NULL\n");
return EFI_STATUS_NO_MEDIA;
}
if (token->event != nullptr) {
// TODO: Implement async IO
LTRACEF("async erase not supported, token->event=%p\n", token->event);
return EFI_STATUS_DEVICE_ERROR;
}
if (lba >= dev->block_count) {
LTRACEF("OOB erase lba=%llu block_count=%u\n", lba, dev->block_count);
return EFI_STATUS_INVALID_PARAMETER;
}
ssize_t ret = bio_erase(dev, lba * dev->block_size, size);
if (ret < 0) {
LTRACEF("bio_erase failed ret=%zd\n", ret);
return EFI_STATUS_DEVICE_ERROR;
}
return EFI_STATUS_SUCCESS;
}
} // namespace
__WEAK EfiStatus get_buffer(struct GblEfiImageLoadingProtocol *self,
@@ -204,3 +240,23 @@ __WEAK EfiStatus get_buffer(struct GblEfiImageLoadingProtocol *self,
Buffer->SizeBytes = buffer_size;
return EFI_STATUS_SUCCESS;
}
__WEAK
EfiStatus open_efi_erase_block_protocol(const EfiHandle handle, void** intf) {
auto* device_name = static_cast<const char*>(handle);
LTRACEF("handle=%p (%s)\n", handle, device_name);
auto* p = reinterpret_cast<EfiEraseBlockInterface*>(
uefi_malloc(sizeof(EfiEraseBlockInterface)));
if (p == nullptr) {
return EFI_STATUS_OUT_OF_RESOURCES;
}
memset(p, 0, sizeof(*p));
p->dev = bio_open(device_name);
p->protocol = {
.revision = EFI_ERASE_BLOCK_PROTOCOL_REVISION,
.erase_length_granularity = 1, // Erase block size == 1 filesystem block
.erase_blocks = erase_blocks,
};
*intf = p;
return EFI_STATUS_SUCCESS;
}

View File

@@ -75,4 +75,6 @@ void setup_heap();
// Caled by LK once after executing UEFI application to tear down the heap
void reset_heap();
EfiStatus open_efi_erase_block_protocol(const EfiHandle handle, void** intf);
#endif