mirror of
https://github.com/ipxe/ipxe
synced 2025-12-09 10:50:28 +03:00
[riscv] Support older SBI implementations
Fall back to attempting the legacy SBI console and shutdown calls if the standard calls fail. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -73,7 +73,7 @@ sbi_ecall_0 ( int eid, int fid ) {
|
||||
*
|
||||
* @v eid Extension ID
|
||||
* @v fid Function ID
|
||||
* @v param0 Parameter 0
|
||||
* @v p0 Parameter 0
|
||||
* @ret ret Return value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) struct sbi_return
|
||||
@@ -98,8 +98,8 @@ sbi_ecall_1 ( int eid, int fid, unsigned long p0 ) {
|
||||
*
|
||||
* @v eid Extension ID
|
||||
* @v fid Function ID
|
||||
* @v param0 Parameter 0
|
||||
* @v param1 Parameter 1
|
||||
* @v p0 Parameter 0
|
||||
* @v p1 Parameter 1
|
||||
* @ret ret Return value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) struct sbi_return
|
||||
@@ -124,9 +124,9 @@ sbi_ecall_2 ( int eid, int fid, unsigned long p0, unsigned long p1 ) {
|
||||
*
|
||||
* @v eid Extension ID
|
||||
* @v fid Function ID
|
||||
* @v param0 Parameter 0
|
||||
* @v param1 Parameter 1
|
||||
* @v param2 Parameter 2
|
||||
* @v p0 Parameter 0
|
||||
* @v p1 Parameter 1
|
||||
* @v p2 Parameter 2
|
||||
* @ret ret Return value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) struct sbi_return
|
||||
@@ -148,9 +148,51 @@ sbi_ecall_3 ( int eid, int fid, unsigned long p0, unsigned long p1,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call supervisor with no parameters
|
||||
*
|
||||
* @v fid Legacy function ID
|
||||
* @ret ret Return value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) long
|
||||
sbi_legacy_ecall_0 ( int fid ) {
|
||||
register unsigned long a7 asm ( "a7" ) = ( ( long ) fid );
|
||||
register unsigned long a0 asm ( "a0" );
|
||||
|
||||
__asm__ __volatile__ ( "ecall"
|
||||
: "=r" ( a0 )
|
||||
: "r" ( a7 )
|
||||
: "memory" );
|
||||
return a0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call supervisor with one parameter
|
||||
*
|
||||
* @v fid Legacy function ID
|
||||
* @v p0 Parameter 0
|
||||
* @ret ret Return value
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) long
|
||||
sbi_legacy_ecall_1 ( int fid, unsigned long p0 ) {
|
||||
register unsigned long a7 asm ( "a7" ) = ( ( long ) fid );
|
||||
register unsigned long a0 asm ( "a0" ) = p0;
|
||||
|
||||
__asm__ __volatile__ ( "ecall"
|
||||
: "+r" ( a0 )
|
||||
: "r" ( a7 )
|
||||
: "memory" );
|
||||
return a0;
|
||||
}
|
||||
|
||||
/** Convert an SBI error code to an iPXE status code */
|
||||
#define ESBI( error ) EPLATFORM ( EINFO_EPLATFORM, error )
|
||||
|
||||
/** Legacy extensions */
|
||||
#define SBI_LEGACY_PUTCHAR 0x01 /**< Console Put Character */
|
||||
#define SBI_LEGACY_GETCHAR 0x02 /**< Console Get Character */
|
||||
#define SBI_LEGACY_SHUTDOWN 0x08 /**< System Shutdown */
|
||||
|
||||
/** System reset extension */
|
||||
#define SBI_SRST SBI_EID ( 'S', 'R', 'S', 'T' )
|
||||
#define SBI_SRST_SYSTEM_RESET 0x00 /**< Reset system */
|
||||
|
||||
@@ -50,9 +50,15 @@ static unsigned char sbi_console_input;
|
||||
* @v character Character to be printed
|
||||
*/
|
||||
static void sbi_putchar ( int character ) {
|
||||
struct sbi_return ret;
|
||||
|
||||
/* Write byte to console */
|
||||
sbi_ecall_1 ( SBI_DBCN, SBI_DBCN_WRITE_BYTE, character );
|
||||
ret = sbi_ecall_1 ( SBI_DBCN, SBI_DBCN_WRITE_BYTE, character );
|
||||
if ( ! ret.error )
|
||||
return;
|
||||
|
||||
/* Debug extension not supported: try legacy method */
|
||||
sbi_legacy_ecall_1 ( SBI_LEGACY_PUTCHAR, character );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,6 +88,7 @@ static int sbi_getchar ( void ) {
|
||||
*/
|
||||
static int sbi_iskey ( void ) {
|
||||
struct sbi_return ret;
|
||||
long key;
|
||||
|
||||
/* Do nothing if we already have a buffered character */
|
||||
if ( sbi_console_input )
|
||||
@@ -91,11 +98,18 @@ static int sbi_iskey ( void ) {
|
||||
ret = sbi_ecall_3 ( SBI_DBCN, SBI_DBCN_READ,
|
||||
sizeof ( sbi_console_input ),
|
||||
virt_to_phys ( &sbi_console_input ), 0 );
|
||||
if ( ret.error )
|
||||
return 0;
|
||||
if ( ! ret.error )
|
||||
return ret.value;
|
||||
|
||||
/* Return number of characters read and buffered */
|
||||
return ret.value;
|
||||
/* Debug extension not supported: try legacy method */
|
||||
key = sbi_legacy_ecall_0 ( SBI_LEGACY_GETCHAR );
|
||||
if ( key > 0 ) {
|
||||
sbi_console_input = key;
|
||||
return key;
|
||||
}
|
||||
|
||||
/* No character available */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** SBI console */
|
||||
|
||||
@@ -53,6 +53,10 @@ static void sbi_reboot ( int flags ) {
|
||||
rc = -ESBI ( ret.error );
|
||||
DBGC ( SBI_SRST, "SBI %s reset failed: %s\n",
|
||||
( warm ? "warm" : "cold" ), strerror ( rc ) );
|
||||
|
||||
/* Try a legacy shutdown */
|
||||
sbi_legacy_ecall_0 ( SBI_LEGACY_SHUTDOWN );
|
||||
DBGC ( SBI_SRST, "SBI legacy shutdown failed\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,6 +75,11 @@ static int sbi_poweroff ( void ) {
|
||||
/* Any return is an error */
|
||||
rc = -ESBI ( ret.error );
|
||||
DBGC ( SBI_SRST, "SBI shutdown failed: %s\n", strerror ( rc ) );
|
||||
|
||||
/* Try a legacy shutdown */
|
||||
sbi_legacy_ecall_0 ( SBI_LEGACY_SHUTDOWN );
|
||||
DBGC ( SBI_SRST, "SBI legacy shutdown failed\n" );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,9 @@ prefix_virt:
|
||||
#define SBI_DBCN ( ( 'D' << 24 ) | ( 'B' << 16 ) | ( 'C' << 8 ) | 'N' )
|
||||
#define SBI_DBCN_WRITE_BYTE 0x02
|
||||
|
||||
/* SBI legacy console putchar */
|
||||
#define SBI_LEGACY_PUTCHAR 0x01
|
||||
|
||||
.section ".prefix.print_message", "ax", @progbits
|
||||
.globl print_message
|
||||
print_message:
|
||||
@@ -108,6 +111,10 @@ print_message_alt:
|
||||
li a7, SBI_DBCN
|
||||
li a6, SBI_DBCN_WRITE_BYTE
|
||||
ecall
|
||||
beqz a0, 1b
|
||||
lbu a0, -1(t1)
|
||||
li a7, SBI_LEGACY_PUTCHAR
|
||||
ecall
|
||||
j 1b
|
||||
2:
|
||||
/* Restore registers and return (via alternate link register) */
|
||||
@@ -154,6 +161,17 @@ progress_\@:
|
||||
* Returns: none
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert a single nibble to an ASCII character
|
||||
*/
|
||||
.macro nibble_to_ascii reg
|
||||
addi \reg, \reg, -10
|
||||
bltz \reg, dec_\@
|
||||
addi \reg, \reg, ( 'a' - ( '0' + 10 ) )
|
||||
dec_\@: addi \reg, \reg, ( '0' + 10 )
|
||||
.endm
|
||||
|
||||
.section ".prefix.print_hex_value", "ax", @progbits
|
||||
.globl print_hex_value
|
||||
print_hex_value:
|
||||
@@ -183,14 +201,16 @@ print_hex_value_alt:
|
||||
|
||||
1: /* Print each digit in turn */
|
||||
srli a0, t1, ( __riscv_xlen - 4 )
|
||||
addi a0, a0, -10
|
||||
bltz a0, 2f
|
||||
addi a0, a0, ( 'a' - ( '0' + 10 ) )
|
||||
2: addi a0, a0, ( '0' + 10 )
|
||||
nibble_to_ascii a0
|
||||
li a7, SBI_DBCN
|
||||
li a6, SBI_DBCN_WRITE_BYTE
|
||||
ecall
|
||||
slli t1, t1, 4
|
||||
beqz a0, 2f
|
||||
srli a0, t1, ( __riscv_xlen - 4 )
|
||||
nibble_to_ascii a0
|
||||
li a7, SBI_LEGACY_PUTCHAR
|
||||
ecall
|
||||
2: slli t1, t1, 4
|
||||
addi t2, t2, -4
|
||||
bgtz t2, 1b
|
||||
|
||||
@@ -1121,6 +1141,9 @@ install:
|
||||
#define SBI_SRST_SYSTEM_RESET 0x00
|
||||
#define SBI_RESET_COLD 0x00000001
|
||||
|
||||
/* SBI legacy shutdown */
|
||||
#define SBI_LEGACY_SHUTDOWN 0x08
|
||||
|
||||
.section ".prefix.reset_system", "ax", @progbits
|
||||
.globl reset_system
|
||||
reset_system:
|
||||
@@ -1133,9 +1156,14 @@ reset_system:
|
||||
li a0, SBI_RESET_COLD
|
||||
mv a1, zero
|
||||
ecall
|
||||
progress "(reset failed)\n"
|
||||
|
||||
/* Attempt legacy shutdown */
|
||||
li a7, SBI_LEGACY_SHUTDOWN
|
||||
ecall
|
||||
progress "(legacy shutdown failed)\n"
|
||||
|
||||
/* If reset failed, lock the system */
|
||||
progress "(reset failed)\n"
|
||||
1: wfi
|
||||
j 1b
|
||||
.size reset_system, . - reset_system
|
||||
|
||||
Reference in New Issue
Block a user