]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Support older SBI implementations
authorMichael Brown <mcb30@ipxe.org>
Sun, 25 May 2025 08:28:11 +0000 (09:28 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sun, 25 May 2025 09:43:39 +0000 (10:43 +0100)
Fall back to attempting the legacy SBI console and shutdown calls if
the standard calls fail.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/riscv/include/ipxe/sbi.h
src/arch/riscv/interface/sbi/sbi_console.c
src/arch/riscv/interface/sbi/sbi_reboot.c
src/arch/riscv/prefix/libprefix.S

index 44685cc87a6d6dd4cc3530e712dfc3936d078ac9..aaab3a3555bc7086c03d36ca162ee16cc7df0161 100644 (file)
@@ -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 */
index 93cdf0798170972a377401414930ea4bc15018fe..c993ebc0ab9b37f960cf37e792a1eb580c7a2275 100644 (file)
@@ -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;
-
-       /* Return number of characters read and buffered */
-       return ret.value;
+       if ( ! ret.error )
+               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 */
index 3529c9d38f044836f23fa53e4cac1c364e6cd151..b1c742ec73c8fd2baf9da3a9e2d79b922d587633 100644 (file)
@@ -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;
 }
 
index a101ba1cd6be746bdba7a8891949a2681b803680..5bfc6b3be9dcf6bdbd92c4f6587d9aee2291f69a 100644 (file)
@@ -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