| /* | |
| * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>. | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public License as | |
| * published by the Free Software Foundation; either version 2 of the | |
| * License, or any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, but | |
| * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| * 02110-1301, USA. | |
| * | |
| * You can also choose to distribute this program under the terms of | |
| * the Unmodified Binary Distribution Licence (as given in the file | |
| * COPYING.UBDL), provided that you have satisfied its requirements. | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <assert.h> | |
| #include <errno.h> | |
| #include <string.h> | |
| #include <ipxe/disklog.h> | |
| /** @file | |
| * | |
| * Disk log console | |
| * | |
| */ | |
| /** | |
| * Open disk log console | |
| * | |
| * @v disklog Disk log | |
| * @ret rc Return status code | |
| * | |
| * The data buffer must already contain the initial logical block. | |
| */ | |
| int disklog_open ( struct disklog *disklog ) { | |
| struct disklog_header *hdr = | |
| ( ( struct disklog_header * ) disklog->buffer ); | |
| /* Sanity checks */ | |
| assert ( disklog->console != NULL ); | |
| assert ( disklog->buffer != NULL ); | |
| assert ( disklog->blksize > 0 ); | |
| assert ( ( disklog->blksize & ( disklog->blksize - 1 ) ) == 0 ); | |
| assert ( disklog->lba <= disklog->max_lba ); | |
| assert ( disklog->op != NULL ); | |
| assert ( disklog->op->write != NULL ); | |
| /* Check magic signature */ | |
| if ( ( disklog->blksize < sizeof ( *hdr ) ) || | |
| ( memcmp ( hdr->magic, DISKLOG_MAGIC, | |
| sizeof ( hdr->magic ) ) != 0 ) ) { | |
| DBGC ( disklog, "DISKLOG has bad magic signature\n" ); | |
| return -EINVAL; | |
| } | |
| /* Initialise buffer */ | |
| disklog->offset = sizeof ( *hdr ); | |
| disklog->unwritten = 0; | |
| memset ( ( disklog->buffer + sizeof ( *hdr ) ), 0, | |
| ( disklog->blksize - sizeof ( *hdr ) ) ); | |
| /* Enable console */ | |
| disklog->console->disabled = 0; | |
| return 0; | |
| } | |
| /** | |
| * Write character to disk log console | |
| * | |
| * @v disklog Disk log | |
| * @v character Character | |
| */ | |
| void disklog_putchar ( struct disklog *disklog, int character ) { | |
| static int busy; | |
| int rc; | |
| /* Ignore if we are already mid-logging */ | |
| if ( busy ) | |
| return; | |
| busy = 1; | |
| /* Sanity checks */ | |
| assert ( disklog->offset < disklog->blksize ); | |
| /* Write character to buffer */ | |
| disklog->buffer[disklog->offset++] = character; | |
| disklog->unwritten++; | |
| /* Write sector to disk, if applicable */ | |
| if ( ( disklog->offset == disklog->blksize ) || | |
| ( disklog->unwritten == DISKLOG_MAX_UNWRITTEN ) || | |
| ( character == '\n' ) ) { | |
| /* Write sector to disk */ | |
| if ( ( rc = disklog->op->write() ) != 0 ) { | |
| DBGC ( disklog, "DISKLOG could not write: %s\n", | |
| strerror ( rc ) ); | |
| /* Ignore and continue; there's nothing we can do */ | |
| } | |
| /* Reset count of unwritten characters */ | |
| disklog->unwritten = 0; | |
| } | |
| /* Move to next sector, if applicable */ | |
| if ( disklog->offset == disklog->blksize ) { | |
| /* Disable console if we have run out of space */ | |
| if ( disklog->lba >= disklog->max_lba ) | |
| disklog->console->disabled = 1; | |
| /* Clear log buffer */ | |
| memset ( disklog->buffer, 0, disklog->blksize ); | |
| disklog->offset = 0; | |
| /* Move to next sector */ | |
| disklog->lba++; | |
| } | |
| /* Clear busy flag */ | |
| busy = 0; | |
| } |