iPXE
efi_disklog.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <assert.h>
28#include <errno.h>
29#include <string.h>
30#include <ipxe/console.h>
31#include <ipxe/disklog.h>
32#include <ipxe/init.h>
33#include <ipxe/umalloc.h>
34#include <ipxe/efi/efi.h>
37#include <config/console.h>
38
39/** @file
40 *
41 * EFI disk log console
42 *
43 */
44
45/* Set default console usage if applicable */
46#if ! ( defined ( CONSOLE_DISKLOG ) && CONSOLE_EXPLICIT ( CONSOLE_DISKLOG ) )
47#undef CONSOLE_DISKLOG
48#define CONSOLE_DISKLOG ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
49#endif
50
51/** EFI disk log console device handle */
53
54/** EFI disk log console block I/O protocol */
56
57/** EFI disk log console media ID */
59
60/** EFI disk log console */
61static struct disklog efi_disklog;
62
63struct console_driver efi_disklog_console __console_driver;
64
65/**
66 * Write current logical block
67 *
68 * @ret rc Return status code
69 */
70static int efi_disklog_write ( void ) {
72 struct disklog *disklog = &efi_disklog;
73 EFI_STATUS efirc;
74 int rc;
75
76 /* Write disk block */
77 if ( ( efirc = block->WriteBlocks ( block, efi_disklog_media_id,
79 disklog->buffer ) ) != 0 ) {
80 rc = -EEFI ( efirc );
81 DBGC ( disklog, "EFIDISKLOG %s could not write LBA %#llx: "
83 ( ( unsigned long long ) disklog->lba ),
84 strerror ( rc ) );
85 return rc;
86 }
87
88 return 0;
89}
90
91/** EFI disk log console operations */
93 .write = efi_disklog_write,
94};
95
96/**
97 * Write character to console
98 *
99 * @v character Character
100 */
101static void efi_disklog_putchar ( int character ) {
102
103 /* Write character */
104 disklog_putchar ( &efi_disklog, character );
105}
106
107/**
108 * Open EFI disk log partition
109 *
110 * @v handle Block device handle
111 * @ret rc Return status code
112 */
114 struct disklog *disklog = &efi_disklog;
118 void *buffer;
119 EFI_STATUS efirc;
120 int rc;
121
122 /* Record handle */
124
125 /* Open block I/O protocol for ephemeral usage */
127 &block ) ) != 0 ) {
128 DBGC ( disklog, "EFIDISKLOG %s could not open: %s\n",
130 goto err_open;
131 }
132 media = block->Media;
134 efi_disklog_media_id = media->MediaId;
135
136 /* Check this is a partition */
137 if ( ! media->LogicalPartition ) {
138 DBGC2 ( disklog, "EFIDISKLOG %s is not a partition\n",
140 rc = -ENOTTY;
141 goto err_not_partition;
142 }
143
144 /* Check partition type (if exposed by the platform) */
146 &part ) ) == 0 ) {
147 if ( ( part->Type != PARTITION_TYPE_MBR ) ||
149 DBGC ( disklog, "EFIDISKLOG %s is not a log "
150 "partition\n", efi_handle_name ( handle ) );
151 rc = -ENOTTY;
152 goto err_not_log;
153 }
154 } else {
155 DBGC2 ( disklog, "EFIDISKLOG %s has no partition info\n",
157 /* Continue anyway */
158 }
159
160 /* Allocate buffer */
161 buffer = umalloc ( media->BlockSize );
162 if ( ! buffer ) {
163 rc = -ENOMEM;
164 goto err_alloc;
165 }
166
167 /* Read partition signature */
168 if ( ( efirc = block->ReadBlocks ( block, efi_disklog_media_id, 0,
169 media->BlockSize, buffer ) ) != 0 ){
170 rc = -EEFI ( efirc );
171 DBGC ( disklog, "EFIDISKLOG %s could not read block 0: %s\n",
173 goto err_read;
174 }
175
176 /* Initialise disk log console */
177 disklog_init ( disklog, &efi_disklog_op, &efi_disklog_console, buffer,
178 media->BlockSize, 0, media->LastBlock );
179
180 /* Open disk log console */
181 if ( ( rc = disklog_open ( disklog ) ) != 0 ) {
182 DBGC ( disklog, "EFIDISKLOG %s could not initialise log: "
183 "%s\n", efi_handle_name ( handle ), strerror ( rc ) );
184 goto err_init;
185 }
186
187 /* Reopen handle for long-term use */
189 &block ) ) != 0 ) {
190 DBGC ( disklog, "EFIDISKLOG %s could not reopen: %s\n",
192 goto err_reopen;
193 }
194 if ( block != efi_disklog_block ) {
195 DBGC ( disklog, "EFIDISKLOG %s changed during reopening\n",
197 rc = -EPIPE;
198 goto err_reopen_mismatch;
199 }
200
201 DBGC ( disklog, "EFIDISKLOG using %s\n", efi_handle_name ( handle ) );
202 DBGC2 ( disklog, "EFIDISKLOG has %zd-byte LBA [%#x,%#llx]\n",
203 disklog->blksize, 0,
204 ( ( unsigned long long ) disklog->max_lba ) );
205 return 0;
206
207 err_reopen_mismatch:
209 err_reopen:
210 err_init:
211 err_read:
212 ufree ( buffer );
213 err_alloc:
214 err_not_log:
215 err_not_partition:
217 err_open:
219 return rc;
220}
221
222/**
223 * Initialise EFI disk log console
224 *
225 */
226static void efi_disklog_init ( void ) {
227 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
229 EFI_HANDLE *handles;
230 UINTN count;
231 unsigned int i;
232 EFI_STATUS efirc;
233 int rc;
234
235 /* Locate all block I/O protocol handles */
236 if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol, protocol,
237 NULL, &count,
238 &handles ) ) != 0 ) {
239 rc = -EEFI ( efirc );
240 DBGC ( &efi_disklog, "EFIDISKLOG could not locate block I/O: "
241 "%s\n", strerror ( rc ) );
242 goto err_locate;
243 }
244
245 /* Try each handle in turn */
246 for ( i = 0 ; i < count ; i++ ) {
247 if ( ( rc = efi_disklog_open ( handles[i] ) ) == 0 )
248 break;
249 }
250
251 bs->FreePool ( handles );
252 err_locate:
253 return;
254}
255
256/**
257 * EFI disk log console initialisation function
258 */
259struct init_fn efi_disklog_init_fn __init_fn ( INIT_CONSOLE ) = {
260 .name = "disklog",
261 .initialise = efi_disklog_init,
262};
263
264/**
265 * Shut down EFI disk log console
266 *
267 * @v booting System is shutting down for OS boot
268 */
269static void efi_disklog_shutdown ( int booting __unused ) {
270 struct disklog *disklog = &efi_disklog;
271
272 /* Do nothing if we have no EFI disk log console */
273 if ( ! efi_disklog_handle )
274 return;
275
276 /* Close EFI disk log console */
277 DBGC ( disklog, "EFIDISKLOG %s closed\n",
281 ufree ( disklog->buffer );
285}
286
287/** EFI disk log console shutdown function */
288struct startup_fn efi_disklog_startup_fn __startup_fn ( STARTUP_EARLY ) = {
289 .name = "disklog",
290 .shutdown = efi_disklog_shutdown,
291};
292
293/** EFI disk log console driver */
294struct console_driver efi_disklog_console __console_driver = {
295 .putchar = efi_disklog_putchar,
296 .disabled = CONSOLE_DISABLED,
297 .usage = CONSOLE_DISKLOG,
298};
299
300/* Request a log partition from genfsimg */
301IPXE_NOTE ( DISKLOG );
UINT64 UINTN
Unsigned value of native width.
unsigned int UINT32
4-byte unsigned value.
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
Block IO protocol as defined in the UEFI 2.0 specification.
struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL
Definition BlockIo.h:22
This file defines the EFI Partition Information Protocol.
#define PARTITION_TYPE_MBR
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
GUID EFI_GUID
128-bit buffer containing a unique identifier value.
@ ByProtocol
Retrieve the set of handles from the handle database that support a specified protocol.
Definition UefiSpec.h:1530
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
Assertions.
Console configuration.
int disklog_open(struct disklog *disklog)
Open disk log console.
Definition disklog.c:46
void disklog_putchar(struct disklog *disklog, int character)
Write character to disk log console.
Definition disklog.c:85
Disk log console.
#define DISKLOG_PARTITION_TYPE
Disk log partition type.
Definition disklog.h:84
static void disklog_init(struct disklog *disklog, struct disklog_operations *op, struct console_driver *console, void *buffer, size_t blksize, uint64_t lba, uint64_t max_lba)
Initialise disk log console.
Definition disklog.h:66
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition efi_debug.c:652
static EFI_HANDLE efi_disklog_handle
EFI disk log console device handle.
Definition efi_disklog.c:52
static int efi_disklog_write(void)
Write current logical block.
Definition efi_disklog.c:70
static struct disklog_operations efi_disklog_op
EFI disk log console operations.
Definition efi_disklog.c:92
static int efi_disklog_open(EFI_HANDLE handle)
Open EFI disk log partition.
static UINT32 efi_disklog_media_id
EFI disk log console media ID.
Definition efi_disklog.c:58
static void efi_disklog_putchar(int character)
Write character to console.
static void efi_disklog_shutdown(int booting __unused)
Shut down EFI disk log console.
static struct disklog efi_disklog
EFI disk log console.
Definition efi_disklog.c:61
static EFI_BLOCK_IO_PROTOCOL * efi_disklog_block
EFI disk log console block I/O protocol.
Definition efi_disklog.c:55
#define CONSOLE_DISKLOG
Definition efi_disklog.c:48
static void efi_disklog_init(void)
Initialise EFI disk log console.
EFI_GUID efi_block_io_protocol_guid
Block I/O protocol GUID.
Definition efi_guid.c:146
EFI_GUID efi_partition_info_protocol_guid
Partition information protocol GUID.
Definition efi_guid.c:314
void efi_close_by_driver(EFI_HANDLE handle, EFI_GUID *protocol)
Close protocol opened for persistent use by a driver.
Definition efi_open.c:279
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
#define INIT_CONSOLE
Console initialisation.
Definition init.h:31
static unsigned int count
Number of entries.
Definition dwmac.h:220
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER).
Definition netvsc.h:5
#define IPXE_NOTE(type)
Definition compiler.h:175
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define STARTUP_EARLY
Early startup.
Definition init.h:64
User interaction.
#define CONSOLE_DISABLED
Console is disabled for all uses.
Definition console.h:112
#define __console_driver
Mark a struct console_driver as being part of the console drivers table.
Definition console.h:134
EFI API.
#define efi_open_by_driver(handle, protocol, interface)
Open protocol for persistent use by a driver.
Definition efi.h:483
#define efi_open(handle, protocol, interface)
Open protocol for ephemeral use.
Definition efi.h:453
#define EFI_HANDLE
Definition efi.h:53
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:181
EFI_SYSTEM_TABLE * efi_systab
uint16_t handle
Handle.
Definition smbios.h:5
User memory allocation.
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition umalloc.h:57
static __always_inline void ufree(void *ptr)
Free external memory.
Definition umalloc.h:68
String functions.
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
#define __startup_fn(startup_order)
Declare a startup/shutdown function.
Definition init.h:53
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
uint16_t protocol
Protocol ID.
Definition stp.h:7
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
Block IO read only mode data and updated only via members of BlockIO.
Definition BlockIo.h:130
EFI Boot Services Table.
Definition UefiSpec.h:1930
EFI_FREE_POOL FreePool
Definition UefiSpec.h:1949
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer
Definition UefiSpec.h:2007
Partition Information Protocol structure.
MBR_PARTITION_RECORD Mbr
MBR data.
union EFI_PARTITION_INFO_PROTOCOL::@056321252157326256300375054226170121123346213234 Info
UINT8 OSIndicator
Definition Mbr.h:35
A console driver.
Definition console.h:56
Disk log operations.
Definition disklog.h:45
A disk log.
Definition disklog.h:25
uint8_t * buffer
Logical block data buffer.
Definition disklog.h:31
size_t blksize
Logical block size.
Definition disklog.h:33
uint64_t lba
Current logical block index.
Definition disklog.h:35
uint64_t max_lba
Maximum logical block index.
Definition disklog.h:37
An initialisation function.
Definition init.h:15
A startup/shutdown function.
Definition init.h:43
static char media[]
Definition sundance.c:85