Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
openbios.h
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2021 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29#include <stdint.h>
30
31// https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html
32struct BuildId {
33 uint32_t namesz;
34 uint32_t descsz;
35 uint32_t type;
36 uint8_t strings[];
37};
38
39static inline int isOpenBiosPresent() {
40 uintptr_t* a0table = (uintptr_t*)0x200;
41 return (a0table[11] & 3) == 1;
42}
43
44/* Calls OpenBIOS API entry `index` with two arguments. The call itself is
45 in the asm so that nothing the compiler schedules between setting t1 and
46 the jump can reuse t1; it clobbers what a normal call does. */
47static inline uintptr_t openBiosCall(uint32_t index, uintptr_t arg0, uintptr_t arg1) {
48 uintptr_t* a0table = (uintptr_t*)0x200;
49 uintptr_t fn = a0table[11] ^ 1;
50 register uintptr_t a0 asm("a0") = arg0;
51 register uintptr_t a1 asm("a1") = arg1;
52 register uintptr_t t1 asm("t1") = index;
53 register uintptr_t v0 asm("v0");
54 __asm__ volatile("jalr %4\n\tnop\n"
55 : "=r"(v0), "+r"(a0), "+r"(a1), "+r"(t1)
56 : "r"(fn)
57 : "$1", "v1", "a2", "a3", "t0", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "ra", "hi", "lo",
58 "memory");
59 return v0;
60}
61
62static inline uint32_t getOpenBiosApiVersion() {
63 if (!isOpenBiosPresent()) return 0;
64 return openBiosCall(0x00, 0, 0);
65}
66
67static inline struct BuildId* getOpenBiosBuildId() {
68 if (!isOpenBiosPresent()) return 0;
69 return (struct BuildId*)openBiosCall(0x01, 0, 0);
70}
71
72/* OpenBIOS API 1. Each wrapper answers "no" (0, or nonzero for
73 installOpenBiosExceptionSlot) on a retail BIOS and on OpenBIOS builds
74 older than API 1, without calling anything. */
75
76/* Nonzero if this OpenBIOS was built with the debug monitor in it
77 (MONITOR=1): that monitor owns the exception path and its link from
78 boot, and answers `break 4, 1` with HELLO. */
79static inline int getOpenBiosMonitor() {
80 if (getOpenBiosApiVersion() < 1) return 0;
81 return (int)openBiosCall(0x02, 0, 0);
82}
83
84/* Puts a call to `fn` (`lui at / ori at, at / jalr at / nop`) into the
85 kernel exception handler's patch slot `slot` (1..4) and flushes the
86 i-cache, only if that slot is still four nops. `fn` runs with only at,
87 v0, v1 and ra saved into the register frame k0 points at, and must
88 return with k0 intact. Returns 0 when installed; nonzero, with nothing
89 written, for a slot out of range or already taken. */
90static inline int installOpenBiosExceptionSlot(int slot, void (*fn)(void)) {
91 if (getOpenBiosApiVersion() < 1) return -1;
92 return (int)openBiosCall(0x03, (uintptr_t)slot, (uintptr_t)fn);
93}
94
95/* A RAM range (KSEG0 address and size in bytes) that OpenBIOS guarantees
96 it never uses, for resident code loaded under it. Returns 0 and a size
97 of 0 when there is none to be had. */
98static inline void* getOpenBiosCodeCave(uint32_t* size) {
99 if (getOpenBiosApiVersion() < 1) {
100 if (size) *size = 0;
101 return 0;
102 }
103 return (void*)openBiosCall(0x04, (uintptr_t)size, 0);
104}
static int size
Definition string.h:149
__asm__(" .section .text.monitorSlotEntry, \"ax\", @progbits\n" " .align 2\n" " .global monitorSlotEntry\n" " .type monitorSlotEntry, @function\n" " .set push\n" " .set noreorder\n" " .set noat\n" "monitorSlotEntry:\n" " mfc0 $v0, $13\n" " nop\n" " andi $v0, $v0, 0x7c\n" " beqz $v0, 1f\n" " srl $v0, $v0, 2\n" " li $v1, " MON_STR(MON_SLOT_EXCMASK) "\n" " srlv $v1, $v1, $v0\n" " andi $v1, $v1, 1\n" " bnez $v1, 2f\n" " nop\n" " jr $ra\n" " nop\n" "1:\n" MON_SLOT_RX_TEST " jr $ra\n" " nop\n" "2:\n" " sw $a0, 0x10($k0)\n" " sw $a1, 0x14($k0)\n" " sw $a2, 0x18($k0)\n" " sw $a3, 0x1c($k0)\n" " mfc0 $a0, $12\n" " nop\n" " sw $a0, 0x8c($k0)\n" " mfc0 $a1, $13\n" " nop\n" " sw $a1, 0x90($k0)\n" " sw $k1, 0x6c($k0)\n" " sw $s0, 0x40($k0)\n" " sw $s1, 0x44($k0)\n" " sw $s2, 0x48($k0)\n" " sw $s3, 0x4c($k0)\n" " sw $s4, 0x50($k0)\n" " sw $s5, 0x54($k0)\n" " sw $s6, 0x58($k0)\n" " sw $s7, 0x5c($k0)\n" " sw $t0, 0x20($k0)\n" " sw $t1, 0x24($k0)\n" " sw $t2, 0x28($k0)\n" " sw $t3, 0x2c($k0)\n" " sw $t4, 0x30($k0)\n" " sw $t5, 0x34($k0)\n" " sw $t6, 0x38($k0)\n" " sw $t7, 0x3c($k0)\n" " sw $t8, 0x60($k0)\n" " sw $t9, 0x64($k0)\n" " sw $gp, 0x70($k0)\n" " sw $sp, 0x74($k0)\n" " sw $fp, 0x78($k0)\n" " mfhi $a0\n" " nop\n" " sw $a0, 0x84($k0)\n" " mflo $a0\n" " nop\n" " sw $a0, 0x88($k0)\n" " move $s0, $ra\n" " la $sp, monitorSlotStack + " MON_STR(MONITOR_SLOT_STACK_WORDS) " * 4 - 16\n" " jal monitorSlotDispatch\n" " nop\n" " lw $k0, 0x108($zero)\n" " move $ra, $s0\n" " lw $k0, 0($k0)\n" " nop\n" " addiu $k0, $k0, 8\n" " lw $a0, 0x84($k0)\n" " lw $a1, 0x88($k0)\n" " mthi $a0\n" " mtlo $a1\n" " lw $a0, 0x10($k0)\n" " lw $a1, 0x14($k0)\n" " lw $a2, 0x18($k0)\n" " lw $a3, 0x1c($k0)\n" " lw $t0, 0x20($k0)\n" " lw $t1, 0x24($k0)\n" " lw $t2, 0x28($k0)\n" " lw $t3, 0x2c($k0)\n" " lw $t4, 0x30($k0)\n" " lw $t5, 0x34($k0)\n" " lw $t6, 0x38($k0)\n" " lw $t7, 0x3c($k0)\n" " lw $t8, 0x60($k0)\n" " lw $t9, 0x64($k0)\n" " lw $s0, 0x40($k0)\n" " lw $sp, 0x74($k0)\n" " jr $ra\n" " nop\n" " .set pop\n" " .size monitorSlotEntry, . - monitorSlotEntry\n" " .previous\n")
Definition openbios.h:32
uint32_t type
Definition openbios.h:35
uint32_t namesz
Definition openbios.h:33
uint32_t descsz
Definition openbios.h:34
uint8_t strings[]
Definition openbios.h:36