github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/svc/svc_nintendoswitch.go (about) 1 // +build nintendoswitch 2 3 // Named wrappers to Runtime SVC 4 package svc 5 6 import ( 7 "device/arm64" 8 "fmt" 9 "github.com/racerxdl/gonx/nx/nxerrors" 10 "github.com/racerxdl/gonx/nx/nxtypes" 11 "time" 12 "unsafe" 13 ) 14 15 // SvcGetInfo Retrieves information about the system, or a certain kernel object. 16 // svc 0x29 17 //go:inline 18 func GetInfo(output *uint64, id0 uint32, handle nxtypes.Handle, id1 uint64) uint64 { 19 return uint64(arm64.SVCall4(0x29, output, id0, handle, id1)) 20 } 21 22 // SendSyncRequest Sends an IPC synchronization request to a session. 23 // svc 0x21 24 //go:inline 25 func SendSyncRequest(session uint64) uint64 { 26 return uint64(arm64.SVCall1(0x21, session)) 27 } 28 29 // CloseHandle Closes a handle, decrementing the reference count of the corresponding kernel object. 30 // This might result in the kernel freeing the object. 31 // svc 0x16. 32 //go:inline 33 func CloseHandle(session nxtypes.Handle) uint64 { 34 return uint64(arm64.SVCall1(0x16, uint64(session))) 35 } 36 37 // ConnectToNamedPort Connects to a registered named port. 38 // Expects byte to be a null terminated string 39 // svc 0x1F 40 //go:inline 41 func ConnectToNamedPort(session *nxtypes.Handle, name *byte) uint64 { 42 res := arm64.AsmFull(` 43 str {session}, [sp, #-16]! 44 mov x1, {name} 45 svc 0x1F 46 mov {}, x0 47 ldr x2, [sp], #16 48 str w1, [x2] 49 `, map[string]interface{}{ 50 "name": uintptr(unsafe.Pointer(name)), 51 "session": uintptr(unsafe.Pointer(session)), 52 }) 53 54 return uint64(res) 55 } 56 57 // CreateTransferMemory Creates a block of transfer memory. 58 // svc 0x15 59 //go:inline 60 func CreateTransferMemory(handle *nxtypes.Handle, addr uintptr, size uintptr, perm uint32) uint64 { 61 // X1 => Addr 62 // X2 => Size 63 // W3 => Memory Perms 64 // Output Result W0 65 // Output TransferMemoryhandle W1 66 res := arm64.AsmFull(` 67 mov x1, {addr} 68 mov x2, {size} 69 mov x3, {perms} 70 str {handle}, [sp, #-16]! 71 svc 0x15 72 ldr x2, [sp], #16 73 str w1, [x2] 74 `, map[string]interface{}{ 75 "addr": addr, 76 "size": size, 77 "perms": perm, 78 "handle": uintptr(unsafe.Pointer(handle)), 79 }) 80 return uint64(res) 81 } 82 83 // SetMemoryAttribute Sets memory attributes 84 // svc 0x03 85 //go:inline 86 func SetMemoryAttribute(addr uintptr, size uintptr, mask, value uint32) uint64 { 87 return uint64(arm64.SVCall4(0x03, addr, size, mask, value)) 88 } 89 90 // WaitSynchronization Waits the specified handles to be finished or the specified timeout 91 // Returns the Handle Index and error if timeout 92 // svc 0x18 93 //go:inline 94 func WaitSynchronization(handles []nxtypes.Handle, timeout time.Duration) (uint32, error) { 95 if len(handles) > 0x40 { 96 // HOS Kernel Limit 97 return 0, nxerrors.TooManyHandles 98 } 99 index := ^uint32(0) 100 // 101 r := arm64.AsmFull(` 102 str {index}, [sp, #-16]! 103 mov x1, {handleptr} 104 mov x2, {handlesnum} 105 mov x3, {timeout} 106 svc 0x18 107 mov {}, x0 108 ldr x2, [sp], #16 109 str w1, [x2] 110 `, map[string]interface{}{ 111 "handleptr": uintptr(unsafe.Pointer(&handles[0])), 112 "handlesnum": len(handles), 113 "timeout": uint64(timeout), 114 "index": uintptr(unsafe.Pointer(&index)), 115 }) 116 117 if r != nxtypes.ResultOK { 118 return uint32(index), nxerrors.Timeout 119 } 120 121 return uint32(index), nil 122 } 123 124 // WaitSynchronization Waits a single handle to be finished with the specified timeout 125 // Calls WaitSynchronization 126 //go:inline 127 func WaitSynchronizationSingle(handle nxtypes.Handle, timeout time.Duration) error { 128 _, err := WaitSynchronization([]nxtypes.Handle{handle}, timeout) 129 return err 130 } 131 132 // Break calls to a SVC Break 133 func Break(breakReason, v0, info uint64) uint64 { 134 return uint64(arm64.SVCall3(0x26, breakReason, v0, info)) 135 } 136 137 // GetTLS returns a pointer to thread local storage 138 func GetTLS() *TLS { 139 tlsPtr := arm64.AsmFull(`mrs {}, tpidrro_el0`, nil) 140 return (*TLS)(unsafe.Pointer(tlsPtr)) 141 } 142 143 func GetIPCBuffer() *[64]uint32 { 144 return &GetTLS().IPCBuffer 145 } 146 147 func ClearIPCBuffer() { 148 buff := GetIPCBuffer() 149 for i := 0; i < 64; i++ { 150 buff[i] = 0 151 } 152 } 153 154 func DumpIPCBuffer() { 155 buff := GetIPCBuffer() 156 println("TLS IPC Buffer Dump:") 157 for i := 0; i < 64; i++ { 158 if i%4 == 0 { 159 fmt.Printf("\n%04x: ", i*4) 160 } 161 fmt.Printf("%08x ", buff[i]) 162 } 163 println("") 164 }