162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * printf.c: Internal prom library printf facility. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 662306a36Sopenharmony_ci * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 762306a36Sopenharmony_ci * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com) 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * We used to warn all over the code: DO NOT USE prom_printf(), 1062306a36Sopenharmony_ci * and yet people do. Anton's banking code was outputting banks 1162306a36Sopenharmony_ci * with prom_printf for most of the 2.4 lifetime. Since an effective 1262306a36Sopenharmony_ci * stick is not available, we deployed a carrot: an early printk 1362306a36Sopenharmony_ci * through PROM by means of -p boot option. This ought to fix it. 1462306a36Sopenharmony_ci * USE printk; if you need, deploy -p. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/compiler.h> 1962306a36Sopenharmony_ci#include <linux/spinlock.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <asm/openprom.h> 2262306a36Sopenharmony_ci#include <asm/oplib.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define CONSOLE_WRITE_BUF_SIZE 1024 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic char ppbuf[1024]; 2762306a36Sopenharmony_cistatic char console_write_buf[CONSOLE_WRITE_BUF_SIZE]; 2862306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(console_write_lock); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid notrace prom_write(const char *buf, unsigned int n) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci unsigned int dest_len; 3362306a36Sopenharmony_ci unsigned long flags; 3462306a36Sopenharmony_ci char *dest; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci dest = console_write_buf; 3762306a36Sopenharmony_ci raw_spin_lock_irqsave(&console_write_lock, flags); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci dest_len = 0; 4062306a36Sopenharmony_ci while (n-- != 0) { 4162306a36Sopenharmony_ci char ch = *buf++; 4262306a36Sopenharmony_ci if (ch == '\n') { 4362306a36Sopenharmony_ci *dest++ = '\r'; 4462306a36Sopenharmony_ci dest_len++; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci *dest++ = ch; 4762306a36Sopenharmony_ci dest_len++; 4862306a36Sopenharmony_ci if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) { 4962306a36Sopenharmony_ci prom_console_write_buf(console_write_buf, dest_len); 5062306a36Sopenharmony_ci dest = console_write_buf; 5162306a36Sopenharmony_ci dest_len = 0; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci if (dest_len) 5562306a36Sopenharmony_ci prom_console_write_buf(console_write_buf, dest_len); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&console_write_lock, flags); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_civoid notrace prom_printf(const char *fmt, ...) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci va_list args; 6362306a36Sopenharmony_ci int i; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci va_start(args, fmt); 6662306a36Sopenharmony_ci i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); 6762306a36Sopenharmony_ci va_end(args); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci prom_write(ppbuf, i); 7062306a36Sopenharmony_ci} 71