mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-04 18:42:15 +02:00
Compare commits
No commits in common. "94cfa2be1c1cd567f99d387c46643ee9c8efc79a" and "cb6f366a2a21e15945e3523909e784500e1e8191" have entirely different histories.
94cfa2be1c
...
cb6f366a2a
@ -69,11 +69,10 @@ typedef enum {
|
|||||||
|
|
||||||
/// Memory attribute bitmasks.
|
/// Memory attribute bitmasks.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MemAttr_IsBorrowed=BIT(0), ///< Is borrowed memory.
|
MemAttr_IsBorrowed=BIT(0), ///< Is borrowed memory.
|
||||||
MemAttr_IsIpcMapped=BIT(1), ///< Is IPC mapped (when IpcRefCount > 0).
|
MemAttr_IsIpcMapped=BIT(1), ///< Is IPC mapped (when IpcRefCount > 0).
|
||||||
MemAttr_IsDeviceMapped=BIT(2), ///< Is device mapped (when DeviceRefCount > 0).
|
MemAttr_IsDeviceMapped=BIT(2), ///< Is device mapped (when DeviceRefCount > 0).
|
||||||
MemAttr_IsUncached=BIT(3), ///< Is uncached.
|
MemAttr_IsUncached=BIT(3), ///< Is uncached.
|
||||||
MemAttr_IsPermissionLocked=BIT(4), ///< Is permission locked.
|
|
||||||
} MemoryAttribute;
|
} MemoryAttribute;
|
||||||
|
|
||||||
/// Memory permission bitmasks.
|
/// Memory permission bitmasks.
|
||||||
|
@ -30,8 +30,3 @@ Service* capsdcGetServiceSession(void);
|
|||||||
* @param[in] out_image_size Output image buffer size, should be at least large enough for RGBA8 width x height.
|
* @param[in] out_image_size Output image buffer size, should be at least large enough for RGBA8 width x height.
|
||||||
*/
|
*/
|
||||||
Result capsdcDecodeJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_image, size_t out_image_size);
|
Result capsdcDecodeJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_image, size_t out_image_size);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Shrinks a jpeg's dimensions by 2.
|
|
||||||
*/
|
|
||||||
Result capsdcShrinkJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_jpeg, size_t out_jpeg_size, u64 *out_result_size);
|
|
||||||
|
@ -405,8 +405,6 @@ Result fsOpenSdCardDetectionEventNotifier(FsEventNotifier* out);
|
|||||||
|
|
||||||
Result fsIsSignedSystemPartitionOnSdCardValid(bool *out);
|
Result fsIsSignedSystemPartitionOnSdCardValid(bool *out);
|
||||||
|
|
||||||
Result fsGetProgramId(u64* out, const char *path, FsContentAttributes attr); ///< [17.0.0+]
|
|
||||||
|
|
||||||
/// Retrieves the rights id corresponding to the content path. Only available on [2.0.0-15.0.1].
|
/// Retrieves the rights id corresponding to the content path. Only available on [2.0.0-15.0.1].
|
||||||
Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id);
|
Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id);
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ Result gpioPadSetInterruptMode(GpioPadSession *p, GpioInterruptMode mode);
|
|||||||
Result gpioPadGetInterruptMode(GpioPadSession *p, GpioInterruptMode *out);
|
Result gpioPadGetInterruptMode(GpioPadSession *p, GpioInterruptMode *out);
|
||||||
Result gpioPadSetInterruptEnable(GpioPadSession *p, bool en);
|
Result gpioPadSetInterruptEnable(GpioPadSession *p, bool en);
|
||||||
Result gpioPadGetInterruptEnable(GpioPadSession *p, bool *out);
|
Result gpioPadGetInterruptEnable(GpioPadSession *p, bool *out);
|
||||||
Result gpioPadGetInterruptStatus(GpioPadSession *p, GpioInterruptStatus *out); ///< [1.0.0-16.1.0]
|
Result gpioPadGetInterruptStatus(GpioPadSession *p, GpioInterruptStatus *out);
|
||||||
Result gpioPadClearInterruptStatus(GpioPadSession *p); ///< [1.0.0-16.1.0]
|
Result gpioPadClearInterruptStatus(GpioPadSession *p);
|
||||||
Result gpioPadSetValue(GpioPadSession *p, GpioValue val);
|
Result gpioPadSetValue(GpioPadSession *p, GpioValue val);
|
||||||
Result gpioPadGetValue(GpioPadSession *p, GpioValue *out);
|
Result gpioPadGetValue(GpioPadSession *p, GpioValue *out);
|
||||||
Result gpioPadBindInterrupt(GpioPadSession *p, Event *out);
|
Result gpioPadBindInterrupt(GpioPadSession *p, Event *out);
|
||||||
|
@ -83,7 +83,6 @@ Result ncmContentStorageRepairInvalidFileAttribute(NcmContentStorage* cs); ///<
|
|||||||
Result ncmContentStorageGetRightsIdFromPlaceHolderIdWithCache(NcmContentStorage* cs, NcmRightsId* out_rights_id, const NcmPlaceHolderId* placeholder_id, const NcmContentId* cache_content_id, FsContentAttributes attr); ///< [8.0.0+]
|
Result ncmContentStorageGetRightsIdFromPlaceHolderIdWithCache(NcmContentStorage* cs, NcmRightsId* out_rights_id, const NcmPlaceHolderId* placeholder_id, const NcmContentId* cache_content_id, FsContentAttributes attr); ///< [8.0.0+]
|
||||||
Result ncmContentStorageRegisterPath(NcmContentStorage* cs, const NcmContentId* content_id, const char *path); ///< [13.0.0+]
|
Result ncmContentStorageRegisterPath(NcmContentStorage* cs, const NcmContentId* content_id, const char *path); ///< [13.0.0+]
|
||||||
Result ncmContentStorageClearRegisteredPath(NcmContentStorage* cs); ///< [13.0.0+]
|
Result ncmContentStorageClearRegisteredPath(NcmContentStorage* cs); ///< [13.0.0+]
|
||||||
Result ncmContentStorageGetProgramId(NcmContentStorage* cs, u64* out, const NcmContentId* content_id, FsContentAttributes attr); ///< [17.0.0+]
|
|
||||||
|
|
||||||
void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db);
|
void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db);
|
||||||
Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, const void* data, u64 data_size);
|
Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, const void* data, u64 data_size);
|
||||||
@ -107,4 +106,3 @@ Result ncmContentMetaDatabaseListContentMetaInfo(NcmContentMetaDatabase* db, s32
|
|||||||
Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u8* out);
|
Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u8* out);
|
||||||
Result ncmContentMetaDatabaseGetRequiredApplicationVersion(NcmContentMetaDatabase* db, u32* out_version, const NcmContentMetaKey* key); ///< [2.0.0+]
|
Result ncmContentMetaDatabaseGetRequiredApplicationVersion(NcmContentMetaDatabase* db, u32* out_version, const NcmContentMetaKey* key); ///< [2.0.0+]
|
||||||
Result ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(NcmContentMetaDatabase* db, NcmContentId* out_content_id, const NcmContentMetaKey* key, NcmContentType type, u8 id_offset); ///< [5.0.0+]
|
Result ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(NcmContentMetaDatabase* db, NcmContentId* out_content_id, const NcmContentMetaKey* key, NcmContentType type, u8 id_offset); ///< [5.0.0+]
|
||||||
Result ncmContentMetaDatabaseGetPlatform(NcmContentMetaDatabase* db, u8* out, const NcmContentMetaKey* key); ///< [17.0.0+]
|
|
||||||
|
@ -60,11 +60,6 @@ typedef enum {
|
|||||||
NcmContentInstallType_Unknown = 7, ///< Unknown
|
NcmContentInstallType_Unknown = 7, ///< Unknown
|
||||||
} NcmContentInstallType;
|
} NcmContentInstallType;
|
||||||
|
|
||||||
/// ContentMetaPlatform
|
|
||||||
typedef enum {
|
|
||||||
NcmContentMetaPlatform_Nx = 0, ///< Nx
|
|
||||||
} NcmContentMetaPlatform;
|
|
||||||
|
|
||||||
/// ContentId
|
/// ContentId
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 c[0x10]; ///< Id
|
u8 c[0x10]; ///< Id
|
||||||
|
@ -771,18 +771,6 @@ Result nsIsAnyApplicationEntityInstalled(u64 application_id, bool *out);
|
|||||||
*/
|
*/
|
||||||
Result nsCleanupUnavailableAddOnContents(u64 application_id, AccountUid uid);
|
Result nsCleanupUnavailableAddOnContents(u64 application_id, AccountUid uid);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief EstimateSizeToMove
|
|
||||||
* @note Only available on [10.0.0+].
|
|
||||||
* @param[in] storage_ids Array of u8 \ref NcmStorageId.
|
|
||||||
* @param[in] count Size of the storage_ids array in entries.
|
|
||||||
* @param[in] storage_id storage_id \ref NcmStorageId
|
|
||||||
* @param[in] flags Flags
|
|
||||||
* @param[in] application_id ApplicationId.
|
|
||||||
* @param[out] Out Output value.
|
|
||||||
*/
|
|
||||||
Result nsEstimateSizeToMove(u8 *storage_ids, s32 count, NcmStorageId storage_id, u32 flags, u64 application_id, s64 *out);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief FormatSdCard
|
* @brief FormatSdCard
|
||||||
* @note Only available on [2.0.0+].
|
* @note Only available on [2.0.0+].
|
||||||
|
@ -14,15 +14,6 @@ typedef enum {
|
|||||||
TsLocation_External = 1, ///< TMP451 External: SoC
|
TsLocation_External = 1, ///< TMP451 External: SoC
|
||||||
} TsLocation;
|
} TsLocation;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TsDeviceCode_LocationInternal = 0x41000001u,
|
|
||||||
TsDeviceCode_LocationExternal = 0x41000002u,
|
|
||||||
} TsDeviceCode;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Service s;
|
|
||||||
} TsSession;
|
|
||||||
|
|
||||||
/// Initialize ts.
|
/// Initialize ts.
|
||||||
Result tsInitialize(void);
|
Result tsInitialize(void);
|
||||||
|
|
||||||
@ -54,7 +45,3 @@ Result tsGetTemperature(TsLocation location, s32 *temperature);
|
|||||||
*/
|
*/
|
||||||
Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature);
|
Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature);
|
||||||
|
|
||||||
Result tsOpenSession(TsSession *s, u32 device_code); ///< [8.0.0+]
|
|
||||||
|
|
||||||
Result tsSessionGetTemperature(TsSession *s, float *temperature); ///< [10.0.0+]
|
|
||||||
void tsSessionClose(TsSession *s);
|
|
@ -54,7 +54,6 @@ Service* uartGetServiceSession(void);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HasPort
|
* @brief HasPort
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPort
|
* @param[in] port \ref UartPort
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
*/
|
*/
|
||||||
@ -62,7 +61,6 @@ Result uartHasPort(UartPort port, bool *out);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HasPortForDev
|
* @brief HasPortForDev
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPortForDev
|
* @param[in] port \ref UartPortForDev
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
*/
|
*/
|
||||||
@ -70,7 +68,6 @@ Result uartHasPortForDev(UartPortForDev port, bool *out);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedBaudRate
|
* @brief IsSupportedBaudRate
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPort
|
* @param[in] port \ref UartPort
|
||||||
* @param[in] baud_rate BaudRate
|
* @param[in] baud_rate BaudRate
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -79,7 +76,6 @@ Result uartIsSupportedBaudRate(UartPort port, u32 baud_rate, bool *out);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedBaudRateForDev
|
* @brief IsSupportedBaudRateForDev
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPortForDev
|
* @param[in] port \ref UartPortForDev
|
||||||
* @param[in] baud_rate BaudRate
|
* @param[in] baud_rate BaudRate
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -88,7 +84,6 @@ Result uartIsSupportedBaudRateForDev(UartPortForDev port, u32 baud_rate, bool *o
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedFlowControlMode
|
* @brief IsSupportedFlowControlMode
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPort
|
* @param[in] port \ref UartPort
|
||||||
* @param[in] flow_control_mode \ref UartFlowControlMode
|
* @param[in] flow_control_mode \ref UartFlowControlMode
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -97,7 +92,6 @@ Result uartIsSupportedFlowControlMode(UartPort port, UartFlowControlMode flow_co
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedFlowControlModeForDev
|
* @brief IsSupportedFlowControlModeForDev
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPortForDev
|
* @param[in] port \ref UartPortForDev
|
||||||
* @param[in] flow_control_mode \ref UartFlowControlMode
|
* @param[in] flow_control_mode \ref UartFlowControlMode
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -113,7 +107,6 @@ Result uartCreatePortSession(UartPortSession *s);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedPortEvent
|
* @brief IsSupportedPortEvent
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPort
|
* @param[in] port \ref UartPort
|
||||||
* @param[in] port_event_type \ref UartPortEventType
|
* @param[in] port_event_type \ref UartPortEventType
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -122,7 +115,6 @@ Result uartIsSupportedPortEvent(UartPort port, UartPortEventType port_event_type
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedPortEventForDev
|
* @brief IsSupportedPortEventForDev
|
||||||
* @note Only available on [1.0.0-16.1.0].
|
|
||||||
* @param[in] port \ref UartPortForDev
|
* @param[in] port \ref UartPortForDev
|
||||||
* @param[in] port_event_type \ref UartPortEventType
|
* @param[in] port_event_type \ref UartPortEventType
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -131,7 +123,7 @@ Result uartIsSupportedPortEventForDev(UartPortForDev port, UartPortEventType por
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedDeviceVariation
|
* @brief IsSupportedDeviceVariation
|
||||||
* @note Only available on [7.0.0-16.1.0].
|
* @note Only available on [7.0.0+].
|
||||||
* @param[in] port \ref UartPort
|
* @param[in] port \ref UartPort
|
||||||
* @param[in] device_variation DeviceVariation
|
* @param[in] device_variation DeviceVariation
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
@ -140,7 +132,7 @@ Result uartIsSupportedDeviceVariation(UartPort port, u32 device_variation, bool
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IsSupportedDeviceVariationForDev
|
* @brief IsSupportedDeviceVariationForDev
|
||||||
* @note Only available on [7.0.0-16.1.0].
|
* @note Only available on [7.0.0+].
|
||||||
* @param[in] port \ref UartPortForDev
|
* @param[in] port \ref UartPortForDev
|
||||||
* @param[in] device_variation DeviceVariation
|
* @param[in] device_variation DeviceVariation
|
||||||
* @param[out] out Output success flag.
|
* @param[out] out Output success flag.
|
||||||
|
@ -23,21 +23,6 @@ typedef struct {
|
|||||||
void* tls_tp; // !! Offset needs to be TLS+0x1F8 for __aarch64_read_tp !!
|
void* tls_tp; // !! Offset needs to be TLS+0x1F8 for __aarch64_read_tp !!
|
||||||
} ThreadVars;
|
} ThreadVars;
|
||||||
|
|
||||||
extern const u8 __tdata_lma[];
|
|
||||||
extern const u8 __tdata_lma_end[];
|
|
||||||
extern u8 __tls_start[];
|
|
||||||
extern u8 __tls_end[];
|
|
||||||
extern size_t __tls_align;
|
|
||||||
|
|
||||||
static inline ThreadVars* getThreadVars(void) {
|
static inline ThreadVars* getThreadVars(void) {
|
||||||
return (ThreadVars*)((u8*)armGetTls() + 0x200 - sizeof(ThreadVars));
|
return (ThreadVars*)((u8*)armGetTls() + 0x200 - sizeof(ThreadVars));
|
||||||
}
|
}
|
||||||
|
|
||||||
NX_INLINE size_t getTlsStartOffset(void)
|
|
||||||
{
|
|
||||||
// TLS region begins with the Thread Control Block (TCB), which is intended
|
|
||||||
// to contain two pointers. The actual tdata/tbss segment follows the TCB,
|
|
||||||
// however if it requires special alignment the offset is rounded up.
|
|
||||||
size_t tcb_sz = 2*sizeof(void*);
|
|
||||||
return __tls_align > tcb_sz ? __tls_align : tcb_sz;
|
|
||||||
}
|
|
||||||
|
@ -16,6 +16,11 @@
|
|||||||
#define USER_TLS_END (0x200 - sizeof(ThreadVars))
|
#define USER_TLS_END (0x200 - sizeof(ThreadVars))
|
||||||
#define NUM_TLS_SLOTS ((USER_TLS_END - USER_TLS_BEGIN) / sizeof(void*))
|
#define NUM_TLS_SLOTS ((USER_TLS_END - USER_TLS_BEGIN) / sizeof(void*))
|
||||||
|
|
||||||
|
extern const u8 __tdata_lma[];
|
||||||
|
extern const u8 __tdata_lma_end[];
|
||||||
|
extern u8 __tls_start[];
|
||||||
|
extern u8 __tls_end[];
|
||||||
|
|
||||||
static Mutex g_threadMutex;
|
static Mutex g_threadMutex;
|
||||||
static Thread* g_threadList;
|
static Thread* g_threadList;
|
||||||
|
|
||||||
@ -40,7 +45,7 @@ static void _EntryWrap(ThreadEntryArgs* args) {
|
|||||||
tv->magic = THREADVARS_MAGIC;
|
tv->magic = THREADVARS_MAGIC;
|
||||||
tv->thread_ptr = args->t;
|
tv->thread_ptr = args->t;
|
||||||
tv->reent = args->reent;
|
tv->reent = args->reent;
|
||||||
tv->tls_tp = (u8*)args->tls-getTlsStartOffset();
|
tv->tls_tp = (u8*)args->tls-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
||||||
tv->handle = args->t->handle;
|
tv->handle = args->t->handle;
|
||||||
|
|
||||||
// Initialize thread info
|
// Initialize thread info
|
||||||
@ -89,35 +94,28 @@ Result threadCreate(
|
|||||||
Thread* t, ThreadFunc entry, void* arg, void* stack_mem, size_t stack_sz,
|
Thread* t, ThreadFunc entry, void* arg, void* stack_mem, size_t stack_sz,
|
||||||
int prio, int cpuid)
|
int prio, int cpuid)
|
||||||
{
|
{
|
||||||
const size_t reent_sz = (sizeof(struct _reent)+0xF) &~ 0xF;
|
|
||||||
const size_t tls_sz = (__tls_end-__tls_start+0xF) &~ 0xF;
|
|
||||||
|
|
||||||
// Verify stack size alignment
|
const size_t tls_sz = (__tls_end-__tls_start+0xF) &~ 0xF;
|
||||||
if (stack_sz & 0xFFF) {
|
const size_t reent_sz = (sizeof(struct _reent)+0xF) &~ 0xF;
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool owns_stack_mem;
|
bool owns_stack_mem;
|
||||||
if (stack_mem == NULL) {
|
if (stack_mem == NULL) {
|
||||||
// Allocate new memory for the stack, tls and reent.
|
// Allocate new memory, stack then reent then tls.
|
||||||
stack_mem = __libnx_aligned_alloc(0x1000, stack_sz + tls_sz + reent_sz);
|
stack_mem = __libnx_aligned_alloc(0x1000, stack_sz + reent_sz + tls_sz);
|
||||||
|
|
||||||
owns_stack_mem = true;
|
owns_stack_mem = true;
|
||||||
} else {
|
} else {
|
||||||
// Verify alignment of provided memory.
|
// Use provided memory for stack, reent, and tls.
|
||||||
if ((uintptr_t)stack_mem & 0xFFF) {
|
if (((uintptr_t)stack_mem & 0xFFF) || (stack_sz & 0xFFF)) {
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we don't go out of bounds.
|
// Ensure we don't go out of bounds.
|
||||||
size_t align_mask = getTlsStartOffset()-1;
|
if (stack_sz <= tls_sz + reent_sz) {
|
||||||
size_t needed_sz = (tls_sz + reent_sz + align_mask) &~ align_mask;
|
|
||||||
if (stack_sz <= needed_sz + sizeof(ThreadEntryArgs)) {
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use provided memory for the stack, tls and reent.
|
stack_sz -= tls_sz + reent_sz;
|
||||||
stack_sz -= needed_sz;
|
|
||||||
owns_stack_mem = false;
|
owns_stack_mem = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,9 +123,9 @@ Result threadCreate(
|
|||||||
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total allocation size may be unaligned in either case.
|
// Stack size may be unaligned in either case.
|
||||||
virtmemLock();
|
virtmemLock();
|
||||||
const size_t aligned_stack_sz = (stack_sz + tls_sz + reent_sz + 0xFFF) & ~0xFFF;
|
const size_t aligned_stack_sz = (stack_sz + tls_sz + reent_sz +0xFFF) & ~0xFFF;
|
||||||
void* stack_mirror = virtmemFindStack(aligned_stack_sz, 0x4000);
|
void* stack_mirror = virtmemFindStack(aligned_stack_sz, 0x4000);
|
||||||
Result rc = svcMapMemory(stack_mirror, stack_mem, aligned_stack_sz);
|
Result rc = svcMapMemory(stack_mirror, stack_mem, aligned_stack_sz);
|
||||||
virtmemUnlock();
|
virtmemUnlock();
|
||||||
@ -136,9 +134,8 @@ Result threadCreate(
|
|||||||
{
|
{
|
||||||
uintptr_t stack_top = (uintptr_t)stack_mirror + stack_sz - sizeof(ThreadEntryArgs);
|
uintptr_t stack_top = (uintptr_t)stack_mirror + stack_sz - sizeof(ThreadEntryArgs);
|
||||||
ThreadEntryArgs* args = (ThreadEntryArgs*) stack_top;
|
ThreadEntryArgs* args = (ThreadEntryArgs*) stack_top;
|
||||||
void *tls = (void*)((uintptr_t)stack_mirror + stack_sz);
|
void *reent = (void*)((uintptr_t)stack_mirror + stack_sz);
|
||||||
void *reent = (void*)((uintptr_t)tls + tls_sz);
|
void *tls = (void*)((uintptr_t)reent + reent_sz);
|
||||||
|
|
||||||
Handle handle;
|
Handle handle;
|
||||||
|
|
||||||
t->handle = INVALID_HANDLE;
|
t->handle = INVALID_HANDLE;
|
||||||
|
@ -1,42 +1,34 @@
|
|||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "kernel/svc.h"
|
|
||||||
#include "runtime/diag.h"
|
#include "runtime/diag.h"
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
typedef struct Mod0Header {
|
void __nx_dynamic(uintptr_t base, const Elf64_Dyn* dyn)
|
||||||
u32 magic_mod0;
|
|
||||||
s32 dyn_offset;
|
|
||||||
s32 bss_start_offset;
|
|
||||||
s32 bss_end_offset;
|
|
||||||
s32 eh_frame_hdr_start_offset;
|
|
||||||
s32 eh_frame_hdr_end_offset;
|
|
||||||
s32 unused;
|
|
||||||
|
|
||||||
u32 magic_lny0;
|
|
||||||
s32 got_start_offset;
|
|
||||||
s32 got_end_offset;
|
|
||||||
|
|
||||||
u32 magic_lny1;
|
|
||||||
s32 relro_start_offset;
|
|
||||||
s32 relro_end_offset;
|
|
||||||
} Mod0Header;
|
|
||||||
|
|
||||||
NX_INLINE void* _dynResolveOffset(const Mod0Header* mod0, s32 offset)
|
|
||||||
{
|
{
|
||||||
return (void*)((uintptr_t)mod0 + offset);
|
const Elf64_Rela* rela = NULL;
|
||||||
}
|
u64 relasz = 0;
|
||||||
|
|
||||||
static void _dynProcessRela(uintptr_t base, const Elf64_Rela* rela, size_t relasz)
|
for (; dyn->d_tag != DT_NULL; dyn++)
|
||||||
{
|
{
|
||||||
for (; relasz--; rela++) {
|
switch (dyn->d_tag)
|
||||||
switch (ELF64_R_TYPE(rela->r_info)) {
|
{
|
||||||
default: {
|
case DT_RELA:
|
||||||
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_BadReloc));
|
rela = (const Elf64_Rela*)(base + dyn->d_un.d_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
case DT_RELASZ:
|
||||||
|
relasz = dyn->d_un.d_val / sizeof(Elf64_Rela);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case R_AARCH64_RELATIVE: {
|
if (rela == NULL)
|
||||||
|
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_BadReloc));
|
||||||
|
|
||||||
|
for (; relasz--; rela++)
|
||||||
|
{
|
||||||
|
switch (ELF64_R_TYPE(rela->r_info))
|
||||||
|
{
|
||||||
|
case R_AARCH64_RELATIVE:
|
||||||
|
{
|
||||||
u64* ptr = (u64*)(base + rela->r_offset);
|
u64* ptr = (u64*)(base + rela->r_offset);
|
||||||
*ptr = base + rela->r_addend;
|
*ptr = base + rela->r_addend;
|
||||||
break;
|
break;
|
||||||
@ -44,57 +36,3 @@ static void _dynProcessRela(uintptr_t base, const Elf64_Rela* rela, size_t relas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
|
||||||
{
|
|
||||||
// Return early if MOD0 header has been invalidated
|
|
||||||
if (mod0->magic_mod0 != 0x30444f4d) { // MOD0
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the BSS area
|
|
||||||
u8* bss_start = _dynResolveOffset(mod0, mod0->bss_start_offset);
|
|
||||||
u8* bss_end = _dynResolveOffset(mod0, mod0->bss_end_offset);
|
|
||||||
if (bss_start != bss_end) {
|
|
||||||
memset(bss_start, 0, bss_end - bss_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve pointer to the ELF dynamic section
|
|
||||||
const Elf64_Dyn* dyn = _dynResolveOffset(mod0, mod0->dyn_offset);
|
|
||||||
|
|
||||||
// Extract relevant information from the ELF dynamic section
|
|
||||||
const Elf64_Rela* rela = NULL;
|
|
||||||
size_t relasz = 0;
|
|
||||||
for (; dyn->d_tag != DT_NULL; dyn++) {
|
|
||||||
switch (dyn->d_tag) {
|
|
||||||
case DT_RELA:
|
|
||||||
rela = (const Elf64_Rela*)(base + dyn->d_un.d_ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DT_RELASZ:
|
|
||||||
relasz = dyn->d_un.d_val / sizeof(Elf64_Rela);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply RELA relocations if present
|
|
||||||
if (rela && relasz) {
|
|
||||||
_dynProcessRela(base, rela, relasz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return early if LNY0/LNY1 extensions are not present
|
|
||||||
if (mod0->magic_lny0 != 0x30594e4c || mod0->magic_lny1 != 0x31594e4c) { // LNY0, LNY1
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reprotect relro segment as read-only now that we're done processing relocations
|
|
||||||
u8* relro_start = _dynResolveOffset(mod0, mod0->relro_start_offset);
|
|
||||||
size_t relro_sz = (u8*)_dynResolveOffset(mod0, mod0->relro_end_offset) - relro_start;
|
|
||||||
Result rc = svcSetMemoryPermission(relro_start, relro_sz, Perm_R);
|
|
||||||
if (R_FAILED(rc)) {
|
|
||||||
diagAbortWithResult(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock the relro segment's permissions
|
|
||||||
svcSetMemoryAttribute(relro_start, relro_sz, MemAttr_IsPermissionLocked, MemAttr_IsPermissionLocked);
|
|
||||||
}
|
|
||||||
|
@ -30,6 +30,10 @@ struct __pthread_t
|
|||||||
|
|
||||||
void __attribute__((weak)) NORETURN __libnx_exit(int rc);
|
void __attribute__((weak)) NORETURN __libnx_exit(int rc);
|
||||||
|
|
||||||
|
extern const u8 __tdata_lma[];
|
||||||
|
extern const u8 __tdata_lma_end[];
|
||||||
|
extern u8 __tls_start[];
|
||||||
|
|
||||||
/// TimeType passed to timeGetCurrentTime() during time initialization. If that fails and __nx_time_type isn't TimeType_Default, timeGetCurrentTime() will be called again with TimeType_Default.
|
/// TimeType passed to timeGetCurrentTime() during time initialization. If that fails and __nx_time_type isn't TimeType_Default, timeGetCurrentTime() will be called again with TimeType_Default.
|
||||||
__attribute__((weak)) TimeType __nx_time_type = TimeType_Default;
|
__attribute__((weak)) TimeType __nx_time_type = TimeType_Default;
|
||||||
|
|
||||||
@ -434,7 +438,7 @@ void newlibSetup(void)
|
|||||||
tv->reent = _impure_ptr;
|
tv->reent = _impure_ptr;
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||||
tv->tls_tp = __tls_start-getTlsStartOffset();
|
tv->tls_tp = __tls_start-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
tv->handle = envGetMainThreadHandle();
|
tv->handle = envGetMainThreadHandle();
|
||||||
|
|
||||||
|
@ -23,20 +23,36 @@ _start:
|
|||||||
b __libnx_exception_entry
|
b __libnx_exception_entry
|
||||||
|
|
||||||
.Lcrt0_main_entry:
|
.Lcrt0_main_entry:
|
||||||
|
// Get pointer to MOD0 struct (contains offsets to important places)
|
||||||
|
adr x28, __nx_mod0
|
||||||
|
|
||||||
|
// Calculate BSS address/size
|
||||||
|
ldp w8, w9, [x28, #8] // load BSS start/end offset from MOD0
|
||||||
|
sub w9, w9, w8 // calculate BSS size
|
||||||
|
add w9, w9, #7 // round up to 8
|
||||||
|
bic w9, w9, #7 // ^
|
||||||
|
add x8, x28, x8 // fixup the start pointer
|
||||||
|
|
||||||
|
// Clear the BSS in 8-byte units
|
||||||
|
1: subs w9, w9, #8
|
||||||
|
str xzr, [x8], #8
|
||||||
|
bne 1b
|
||||||
|
|
||||||
// Preserve registers across function calls
|
// Preserve registers across function calls
|
||||||
mov x25, x0 // entrypoint argument 0
|
mov x25, x0 // entrypoint argument 0
|
||||||
mov x26, x1 // entrypoint argument 1
|
mov x26, x1 // entrypoint argument 1
|
||||||
mov x27, x30 // loader return address
|
mov x27, x30 // loader return address
|
||||||
mov x28, sp // initial stack pointer
|
|
||||||
|
|
||||||
// Perform runtime linking on ourselves (including relocations)
|
|
||||||
adr x0, _start // get aslr base
|
|
||||||
adr x1, __nx_mod0 // get pointer to MOD0 struct
|
|
||||||
bl __nx_dynamic
|
|
||||||
|
|
||||||
// Save initial stack pointer
|
// Save initial stack pointer
|
||||||
|
mov x8, sp
|
||||||
adrp x9, __stack_top
|
adrp x9, __stack_top
|
||||||
str x28, [x9, #:lo12:__stack_top]
|
str x8, [x9, #:lo12:__stack_top]
|
||||||
|
|
||||||
|
// Parse ELF .dynamic section (which applies relocations to our module)
|
||||||
|
adr x0, _start // get aslr base
|
||||||
|
ldr w1, [x28, #4] // pointer to .dynamic section
|
||||||
|
add x1, x28, x1
|
||||||
|
bl __nx_dynamic
|
||||||
|
|
||||||
// Perform system initialization
|
// Perform system initialization
|
||||||
mov x0, x25
|
mov x0, x25
|
||||||
@ -49,8 +65,8 @@ _start:
|
|||||||
ldr w0, [x0, #:lo12:__system_argc]
|
ldr w0, [x0, #:lo12:__system_argc]
|
||||||
adrp x1, __system_argv // argv
|
adrp x1, __system_argv // argv
|
||||||
ldr x1, [x1, #:lo12:__system_argv]
|
ldr x1, [x1, #:lo12:__system_argv]
|
||||||
adrp x30, :got:exit
|
adrp x30, exit
|
||||||
ldr x30, [x30, #:got_lo12:exit]
|
add x30, x30, #:lo12:exit
|
||||||
b main
|
b main
|
||||||
|
|
||||||
.global __nx_exit
|
.global __nx_exit
|
||||||
@ -79,10 +95,6 @@ __nx_mod0:
|
|||||||
.word __got_start__ - __nx_mod0
|
.word __got_start__ - __nx_mod0
|
||||||
.word __got_end__ - __nx_mod0
|
.word __got_end__ - __nx_mod0
|
||||||
|
|
||||||
.ascii "LNY1"
|
|
||||||
.word __relro_start - __nx_mod0
|
|
||||||
.word __data_start - __nx_mod0
|
|
||||||
|
|
||||||
.section .bss.__stack_top, "aw", %nobits
|
.section .bss.__stack_top, "aw", %nobits
|
||||||
.global __stack_top
|
.global __stack_top
|
||||||
.align 3
|
.align 3
|
||||||
|
@ -39,21 +39,3 @@ Result capsdcDecodeJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result capsdcShrinkJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_jpeg, size_t out_jpeg_size, u64 *out_result_size) {
|
|
||||||
const struct {
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
CapsScreenShotDecodeOption opts;
|
|
||||||
} in = { width, height, *opts };
|
|
||||||
return serviceDispatchInOut(&g_capsdcSrv, 4001, in, *out_result_size,
|
|
||||||
.buffer_attrs = {
|
|
||||||
SfBufferAttr_In | SfBufferAttr_HipcMapAlias,
|
|
||||||
SfBufferAttr_Out | SfBufferAttr_HipcMapAlias | SfBufferAttr_HipcMapTransferAllowsNonSecure,
|
|
||||||
},
|
|
||||||
.buffers = {
|
|
||||||
{ jpeg, jpeg_size },
|
|
||||||
{ out_jpeg, out_jpeg_size },
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -538,20 +538,6 @@ Result fsIsSignedSystemPartitionOnSdCardValid(bool *out) {
|
|||||||
return _fsCmdNoInOutBool(&g_fsSrv, out, 640);
|
return _fsCmdNoInOutBool(&g_fsSrv, out, 640);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fsGetProgramId(u64* out, const char *path, FsContentAttributes attr) {
|
|
||||||
if (hosversionBefore(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
char send_path[FS_MAX_PATH] = {0};
|
|
||||||
strncpy(send_path, path, FS_MAX_PATH-1);
|
|
||||||
|
|
||||||
const u8 in = attr;
|
|
||||||
return _fsObjectDispatchInOut(&g_fsSrv, 618, in, *out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
||||||
.buffers = { { send_path, sizeof(send_path) } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id) {
|
Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id) {
|
||||||
if (!hosversionBetween(2, 16))
|
if (!hosversionBetween(2, 16))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
@ -38,26 +38,7 @@ Result fsldrOpenCodeFileSystem(FsCodeInfo* out_code_info, u64 tid, const char *p
|
|||||||
char send_path[FS_MAX_PATH]={0};
|
char send_path[FS_MAX_PATH]={0};
|
||||||
strncpy(send_path, path, FS_MAX_PATH-1);
|
strncpy(send_path, path, FS_MAX_PATH-1);
|
||||||
|
|
||||||
if (hosversionAtLeast(17,0,0)) {
|
if (hosversionAtLeast(16,0,0)) {
|
||||||
const struct {
|
|
||||||
u8 attr;
|
|
||||||
u64 tid;
|
|
||||||
} in = { attr, tid };
|
|
||||||
|
|
||||||
serviceAssumeDomain(&g_fsldrSrv);
|
|
||||||
return serviceDispatchIn(&g_fsldrSrv, 0, in,
|
|
||||||
.buffer_attrs = {
|
|
||||||
SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
|
||||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
|
||||||
},
|
|
||||||
.buffers = {
|
|
||||||
{ send_path, FS_MAX_PATH },
|
|
||||||
{ out_code_info, sizeof(*out_code_info) },
|
|
||||||
},
|
|
||||||
.out_num_objects = 1,
|
|
||||||
.out_objects = &out->s,
|
|
||||||
);
|
|
||||||
} else if (hosversionAtLeast(16,0,0)) {
|
|
||||||
const struct {
|
const struct {
|
||||||
u8 attr;
|
u8 attr;
|
||||||
u64 tid;
|
u64 tid;
|
||||||
|
@ -123,16 +123,10 @@ Result gpioPadGetInterruptEnable(GpioPadSession *p, bool *out) {
|
|||||||
|
|
||||||
Result gpioPadGetInterruptStatus(GpioPadSession *p, GpioInterruptStatus *out) {
|
Result gpioPadGetInterruptStatus(GpioPadSession *p, GpioInterruptStatus *out) {
|
||||||
_Static_assert(sizeof(*out) == sizeof(u32), "GpioInterruptStatus size");
|
_Static_assert(sizeof(*out) == sizeof(u32), "GpioInterruptStatus size");
|
||||||
|
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _gpioCmdNoInOutU32(&p->s, (u32 *)out, 6);
|
return _gpioCmdNoInOutU32(&p->s, (u32 *)out, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result gpioPadClearInterruptStatus(GpioPadSession *p) {
|
Result gpioPadClearInterruptStatus(GpioPadSession *p) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
return _gpioCmdNoInNoOut(&p->s, 7);
|
return _gpioCmdNoInNoOut(&p->s, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,16 +407,6 @@ Result ncmContentStorageClearRegisteredPath(NcmContentStorage* cs) {
|
|||||||
return _ncmCmdNoIO(&cs->s, 29);
|
return _ncmCmdNoIO(&cs->s, 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ncmContentStorageGetProgramId(NcmContentStorage* cs, u64* out, const NcmContentId* content_id, FsContentAttributes attr) {
|
|
||||||
if (hosversionBefore(17,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
const struct {
|
|
||||||
NcmContentId content_id;
|
|
||||||
u8 attr;
|
|
||||||
} in = { *content_id, attr };
|
|
||||||
return serviceDispatchInOut(&cs->s, 30, in, *out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db) {
|
void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db) {
|
||||||
serviceClose(&db->s);
|
serviceClose(&db->s);
|
||||||
}
|
}
|
||||||
@ -596,9 +586,3 @@ Result ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(NcmContentMetaDatabas
|
|||||||
} in = { type, id_offset, {0}, *key };
|
} in = { type, id_offset, {0}, *key };
|
||||||
return serviceDispatchInOut(&db->s, 20, in, *out_content_id);
|
return serviceDispatchInOut(&db->s, 20, in, *out_content_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ncmContentMetaDatabaseGetPlatform(NcmContentMetaDatabase* db, u8* out, const NcmContentMetaKey* key) {
|
|
||||||
if (hosversionBefore(17,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return serviceDispatchInOut(&db->s, 26, *key, *out);
|
|
||||||
}
|
|
||||||
|
@ -1309,29 +1309,6 @@ Result nsCleanupUnavailableAddOnContents(u64 application_id, AccountUid uid) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nsEstimateSizeToMove(u8 *storage_ids, s32 count, NcmStorageId storage_id, u32 flags, u64 application_id, s64 *out) {
|
|
||||||
if (hosversionBefore(10,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
Service srv={0};
|
|
||||||
Result rc = nsGetApplicationManagerInterface(&srv);
|
|
||||||
|
|
||||||
const struct {
|
|
||||||
u8 storage_id;
|
|
||||||
u8 pad[3];
|
|
||||||
u32 flags;
|
|
||||||
u64 application_id;
|
|
||||||
} in = { storage_id, {0}, flags, application_id };
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = serviceDispatchInOut(&srv, 1311, in, *out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
|
||||||
.buffers = { { storage_ids, count*sizeof(u8) } },
|
|
||||||
);
|
|
||||||
|
|
||||||
serviceClose(&srv);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsFormatSdCard(void) {
|
Result nsFormatSdCard(void) {
|
||||||
if (hosversionBefore(2,0,0))
|
if (hosversionBefore(2,0,0))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
@ -25,9 +25,6 @@ static Result _tsCmdInU8Out32(u8 inval, u32 *out, u64 cmd_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature) {
|
Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
u8 tmp_location = location;
|
u8 tmp_location = location;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -42,8 +39,6 @@ Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result tsGetTemperature(TsLocation location, s32 *temperature) {
|
Result tsGetTemperature(TsLocation location, s32 *temperature) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
return _tsCmdInU8Out32(location, (u32*)temperature, 1);
|
return _tsCmdInU8Out32(location, (u32*)temperature, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,23 +48,3 @@ Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature) {
|
|||||||
return _tsCmdInU8Out32(location, (u32*)temperature, 3);
|
return _tsCmdInU8Out32(location, (u32*)temperature, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result tsOpenSession(TsSession *s, u32 device_code) {
|
|
||||||
if (hosversionBefore(8,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_tsSrv, 4, device_code,
|
|
||||||
.out_num_objects = 1,
|
|
||||||
.out_objects = &s->s,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result tsSessionGetTemperature(TsSession *s, float *temperature) {
|
|
||||||
if (hosversionBefore(10,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return serviceDispatchOut(&s->s, 4, *temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsSessionClose(TsSession *s) {
|
|
||||||
serviceClose(&s->s);
|
|
||||||
}
|
|
||||||
|
@ -45,44 +45,26 @@ static Result _uartCmdInTwoU32sOutBool(Service* srv, u32 inval0, u32 inval1, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result uartHasPort(UartPort port, bool *out) {
|
Result uartHasPort(UartPort port, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInU32OutBool(&g_uartSrv, port, out, 0);
|
return _uartCmdInU32OutBool(&g_uartSrv, port, out, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartHasPortForDev(UartPortForDev port, bool *out) {
|
Result uartHasPortForDev(UartPortForDev port, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInU32OutBool(&g_uartSrv, port, out, 1);
|
return _uartCmdInU32OutBool(&g_uartSrv, port, out, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedBaudRate(UartPort port, u32 baud_rate, bool *out) {
|
Result uartIsSupportedBaudRate(UartPort port, u32 baud_rate, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, baud_rate, out, 2);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, baud_rate, out, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedBaudRateForDev(UartPortForDev port, u32 baud_rate, bool *out) {
|
Result uartIsSupportedBaudRateForDev(UartPortForDev port, u32 baud_rate, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, baud_rate, out, 3);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, baud_rate, out, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedFlowControlMode(UartPort port, UartFlowControlMode flow_control_mode, bool *out) {
|
Result uartIsSupportedFlowControlMode(UartPort port, UartFlowControlMode flow_control_mode, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, flow_control_mode, out, 4);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, flow_control_mode, out, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedFlowControlModeForDev(UartPortForDev port, UartFlowControlMode flow_control_mode, bool *out) {
|
Result uartIsSupportedFlowControlModeForDev(UartPortForDev port, UartFlowControlMode flow_control_mode, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, flow_control_mode, out, 5);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, flow_control_mode, out, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,28 +76,22 @@ Result uartCreatePortSession(UartPortSession *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedPortEvent(UartPort port, UartPortEventType port_event_type, bool *out) {
|
Result uartIsSupportedPortEvent(UartPort port, UartPortEventType port_event_type, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, port_event_type, out, 7);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, port_event_type, out, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedPortEventForDev(UartPortForDev port, UartPortEventType port_event_type, bool *out) {
|
Result uartIsSupportedPortEventForDev(UartPortForDev port, UartPortEventType port_event_type, bool *out) {
|
||||||
if (hosversionAtLeast(17,0,0))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, port_event_type, out, 8);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, port_event_type, out, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedDeviceVariation(UartPort port, u32 device_variation, bool *out) {
|
Result uartIsSupportedDeviceVariation(UartPort port, u32 device_variation, bool *out) {
|
||||||
if (!hosversionBetween(7,17))
|
if (hosversionBefore(7,0,0))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, device_variation, out, 9);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, device_variation, out, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result uartIsSupportedDeviceVariationForDev(UartPortForDev port, u32 device_variation, bool *out) {
|
Result uartIsSupportedDeviceVariationForDev(UartPortForDev port, u32 device_variation, bool *out) {
|
||||||
if (!hosversionBetween(7,17))
|
if (hosversionBefore(7,0,0))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, device_variation, out, 10);
|
return _uartCmdInTwoU32sOutBool(&g_uartSrv, port, device_variation, out, 10);
|
||||||
|
183
nx/switch.ld
183
nx/switch.ld
@ -11,11 +11,10 @@ PHDRS
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN( __start__ = 0x0 );
|
|
||||||
|
|
||||||
/* =========== CODE section =========== */
|
/* =========== CODE section =========== */
|
||||||
|
PROVIDE(__start__ = 0x0);
|
||||||
. = __start__;
|
. = __start__;
|
||||||
PROVIDE_HIDDEN( __code_start = . );
|
__code_start = . ;
|
||||||
|
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
@ -49,143 +48,111 @@ SECTIONS
|
|||||||
|
|
||||||
/* =========== RODATA section =========== */
|
/* =========== RODATA section =========== */
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
PROVIDE_HIDDEN( __rodata_start = . );
|
__rodata_start = . ;
|
||||||
|
|
||||||
.nx-module-name : { KEEP (*(.nx-module-name)) } :rodata
|
.nx-module-name : { KEEP (*(.nx-module-name)) } :rodata
|
||||||
|
|
||||||
.rela.dyn : { *(.rela.*) } :rodata
|
|
||||||
.relr.dyn : { *(.relr.*) } :rodata
|
|
||||||
|
|
||||||
.hash : { *(.hash) } :rodata
|
|
||||||
.gnu.hash : { *(.gnu.hash) } :rodata
|
|
||||||
|
|
||||||
.dynsym : { *(.dynsym) } :rodata
|
|
||||||
.dynstr : { *(.dynstr) } :rodata
|
|
||||||
|
|
||||||
.rodata :
|
.rodata :
|
||||||
{
|
{
|
||||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
.tls.align :
|
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } :rodata
|
||||||
{
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :rodata
|
||||||
QUAD( MAX( ALIGNOF(.tdata), ALIGNOF(.tbss) ) )
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :rodata
|
||||||
} :rodata
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } : rodata
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __tls_align = ADDR(.tls.align) );
|
|
||||||
|
|
||||||
.gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } :rodata
|
|
||||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } :rodata
|
|
||||||
.eh_frame : { KEEP (*(.eh_frame)) *(.eh_frame.*) } :rodata
|
|
||||||
.gnu_extab : { *(.gnu_extab*) } : rodata
|
|
||||||
.exception_ranges : { *(.exception_ranges .exception_ranges*) } :rodata
|
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __eh_frame_hdr_start = ADDR(.eh_frame_hdr) );
|
|
||||||
PROVIDE_HIDDEN( __eh_frame_hdr_end = ADDR(.eh_frame_hdr) + SIZEOF(.eh_frame_hdr) );
|
|
||||||
|
|
||||||
|
.dynamic : { *(.dynamic) } :rodata :dyn
|
||||||
|
.dynsym : { *(.dynsym) } :rodata
|
||||||
|
.dynstr : { *(.dynstr) } :rodata
|
||||||
|
.rela.dyn : { *(.rela.*) } :rodata
|
||||||
|
.interp : { *(.interp) } :rodata
|
||||||
|
.hash : { *(.hash) } :rodata
|
||||||
|
.gnu.hash : { *(.gnu.hash) } :rodata
|
||||||
.gnu.version : { *(.gnu.version) } :rodata
|
.gnu.version : { *(.gnu.version) } :rodata
|
||||||
.gnu.version_d : { *(.gnu.version_d) } :rodata
|
.gnu.version_d : { *(.gnu.version_d) } :rodata
|
||||||
.gnu.version_r : { *(.gnu.version_r) } :rodata
|
.gnu.version_r : { *(.gnu.version_r) } :rodata
|
||||||
|
|
||||||
.note.gnu.build-id : { *(.note.gnu.build-id) } :rodata
|
.note.gnu.build-id : { *(.note.gnu.build-id) } :rodata
|
||||||
|
|
||||||
/* =========== RELRO section =========== */
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
PROVIDE_HIDDEN( __relro_start = . );
|
|
||||||
|
|
||||||
.preinit_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN( __preinit_array_start = . );
|
|
||||||
KEEP (*(.preinit_array))
|
|
||||||
PROVIDE_HIDDEN( __preinit_array_end = . );
|
|
||||||
} :data
|
|
||||||
|
|
||||||
.init_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN( __init_array_start = . );
|
|
||||||
KEEP( *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)) )
|
|
||||||
KEEP( *(.init_array .ctors) )
|
|
||||||
PROVIDE_HIDDEN( __init_array_end = . );
|
|
||||||
} :data
|
|
||||||
|
|
||||||
.fini_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN( __fini_array_start = . );
|
|
||||||
KEEP( *(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)) )
|
|
||||||
KEEP( *(.fini_array .dtors) )
|
|
||||||
PROVIDE_HIDDEN( __fini_array_end = . );
|
|
||||||
} :data
|
|
||||||
|
|
||||||
.data.rel.ro :
|
|
||||||
{
|
|
||||||
*(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
|
|
||||||
*(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
|
|
||||||
. = ALIGN(8);
|
|
||||||
} :data
|
|
||||||
|
|
||||||
.dynamic : { *(.dynamic) } :data :dyn
|
|
||||||
|
|
||||||
.got : { *(.got) *(.igot) } :data
|
|
||||||
.got.plt : { *(.got.plt) *(.igot.plt) } :data
|
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __got_start__ = ADDR(.got) );
|
|
||||||
PROVIDE_HIDDEN( __got_end__ = ADDR(.got.plt) + SIZEOF(.got.plt) );
|
|
||||||
|
|
||||||
/* =========== DATA section =========== */
|
/* =========== DATA section =========== */
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
PROVIDE_HIDDEN( __data_start = . );
|
__data_start = . ;
|
||||||
|
|
||||||
.data :
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } :data
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :data
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } : data
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } :data
|
||||||
|
|
||||||
|
.tdata ALIGN(8) :
|
||||||
|
{
|
||||||
|
__tdata_lma = .;
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
__tdata_lma_end = .;
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.tbss ALIGN(8) :
|
||||||
|
{
|
||||||
|
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.preinit_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.init_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP( *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)) )
|
||||||
|
KEEP( *(.init_array .ctors) )
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.fini_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP( *(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)) )
|
||||||
|
KEEP( *(.fini_array .dtors) )
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
} :data
|
||||||
|
|
||||||
|
__got_start__ = .;
|
||||||
|
|
||||||
|
.got : { *(.got) *(.igot) } :data
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) } :data
|
||||||
|
|
||||||
|
__got_end__ = .;
|
||||||
|
|
||||||
|
.data ALIGN(8) :
|
||||||
{
|
{
|
||||||
*(.data .data.* .gnu.linkonce.d.*)
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
SORT(CONSTRUCTORS)
|
SORT(CONSTRUCTORS)
|
||||||
. = ALIGN(8);
|
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
.tdata :
|
.bss ALIGN(8) :
|
||||||
{
|
|
||||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
|
||||||
. = ALIGN(8);
|
|
||||||
} :data
|
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __tdata_lma = ADDR(.tdata) );
|
|
||||||
PROVIDE_HIDDEN( __tdata_lma_end = ADDR(.tdata) + SIZEOF(.tdata) );
|
|
||||||
|
|
||||||
.tbss :
|
|
||||||
{
|
|
||||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
|
||||||
*(.tcommon)
|
|
||||||
. = ALIGN(8);
|
|
||||||
} :data
|
|
||||||
|
|
||||||
.bss :
|
|
||||||
{
|
{
|
||||||
*(.dynbss)
|
*(.dynbss)
|
||||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} :data
|
|
||||||
|
|
||||||
/* Reserve space for the TLS segment of the main thread */
|
/* Reserve space for the TLS segment of the main thread */
|
||||||
.main.tls ALIGN(MAX(ALIGNOF(.tdata),ALIGNOF(.tbss))) :
|
__tls_start = .;
|
||||||
{
|
. += + SIZEOF(.tdata) + SIZEOF(.tbss);
|
||||||
. += SIZEOF(.tdata);
|
__tls_end = .;
|
||||||
. = ALIGN(ALIGNOF(.tbss));
|
} : data
|
||||||
. += SIZEOF(.tbss);
|
__bss_start__ = ADDR(.bss);
|
||||||
} :data
|
__bss_end__ = ADDR(.bss) + SIZEOF(.bss);
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __tls_start = ADDR(.main.tls) );
|
__end__ = ABSOLUTE(.) ;
|
||||||
PROVIDE_HIDDEN( __tls_end = ADDR(.main.tls) + SIZEOF(.main.tls) );
|
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __bss_start__ = ADDR(.bss) );
|
|
||||||
PROVIDE_HIDDEN( __bss_end__ = __tls_end );
|
|
||||||
|
|
||||||
PROVIDE_HIDDEN( __end__ = ABSOLUTE(.) );
|
|
||||||
|
|
||||||
/* =========== Argument buffer =========== */
|
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
PROVIDE_HIDDEN( __argdata__ = ABSOLUTE(.) );
|
__argdata__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
/* ==================
|
/* ==================
|
||||||
==== Metadata ====
|
==== Metadata ====
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
*link:
|
*link:
|
||||||
+ -T %:getenv(DEVKITPRO /libnx/switch.ld) -pie --no-dynamic-linker --spare-dynamic-tags=0 --gc-sections -z text -z now -z nodynamic-undefined-weak --build-id=sha1 --nx-module-name
|
%(old_link) -T %:getenv(DEVKITPRO /libnx/switch.ld) -pie --no-dynamic-linker --spare-dynamic-tags=0 --gc-sections -z text -z nodynamic-undefined-weak --build-id=sha1 --nx-module-name
|
||||||
|
|
||||||
*startfile:
|
*startfile:
|
||||||
crti%O%s crtbegin%O%s --require-defined=main
|
crti%O%s crtbegin%O%s --require-defined=main
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user