drivers/firmware/efi/earlycon.c

Source file repositories/reference/linux-study-clean/drivers/firmware/efi/earlycon.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/efi/earlycon.c
Extension
.c
Size
6226 bytes
Lines
276
Domain
Driver Families
Bucket
drivers/firmware
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!src) {
			efi_earlycon_unmap(dst, len);
			return;
		}

		memmove(dst, src, maxlen);

		efi_earlycon_unmap(src, len);
		efi_earlycon_unmap(dst, len);
	}
}

static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h,
				    const struct screen_info *si)
{
	const u32 color_black = 0x00000000;
	const u32 color_white = 0x00ffffff;
	const u8 *src;
	int m, n, bytes;
	u8 x;

	bytes = BITS_TO_BYTES(font->width);
	src = font->data + c * font->height * bytes + h * bytes;

	for (m = 0; m < font->width; m++) {
		n = m % 8;
		x = *(src + m / 8);
		if ((x >> (7 - n)) & 1)
			*dst = color_white;
		else
			*dst = color_black;
		dst++;
	}
}

static void
efi_earlycon_write(struct console *con, const char *str, unsigned int num)
{
	const struct screen_info *si = &sysfb_primary_display.screen;
	u32 cur_efi_x = efi_x;
	unsigned int len;
	const char *s;
	void *dst;

	len = si->lfb_linelength;

	while (num) {
		unsigned int linemax = (si->lfb_width - efi_x) / font->width;
		unsigned int h, count;

		count = strnchrnul(str, num, '\n') - str;
		if (count > linemax)
			count = linemax;

		for (h = 0; h < font->height; h++) {
			unsigned int n, x;

			dst = efi_earlycon_map((efi_y + h) * len, len);
			if (!dst)
				return;

			s = str;
			n = count;
			x = efi_x;

			while (n-- > 0) {
				efi_earlycon_write_char(dst + x * 4, *s, h, si);
				x += font->width;
				s++;
			}

			efi_earlycon_unmap(dst, len);
		}

		num -= count;
		efi_x += count * font->width;
		str += count;

		if (num > 0 && *s == '\n') {
			cur_efi_x = efi_x;
			efi_x = 0;
			efi_y += font->height;
			str++;
			num--;
		}

		if (efi_x + font->width > si->lfb_width) {
			cur_efi_x = efi_x;
			efi_x = 0;
			efi_y += font->height;

Annotation

Implementation Notes