mirror of
https://github.com/fail0verflow/mini.git
synced 2025-02-20 05:22:42 +01:00
nand/nandfs stuff
not working yet :/
This commit is contained in:
parent
1eef8e083c
commit
66f09a14de
2
Makefile
2
Makefile
@ -12,7 +12,7 @@ TARGET = iosboot.bin
|
|||||||
ELF = iosboot.elf
|
ELF = iosboot.elf
|
||||||
OBJECTS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
|
OBJECTS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
|
||||||
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o \
|
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o \
|
||||||
exception.o exception_asm.o crypto.o nand.o nandfs.o
|
exception.o exception_asm.o crypto.o nand.o
|
||||||
|
|
||||||
$(TARGET) : $(ELF) $(ELFLOADER)
|
$(TARGET) : $(ELF) $(ELFLOADER)
|
||||||
@echo "MAKEBIN $@"
|
@echo "MAKEBIN $@"
|
||||||
|
41
crypto.c
41
crypto.c
@ -3,6 +3,9 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
#include "gecko.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
|
||||||
#define AES_CMD_RESET 0
|
#define AES_CMD_RESET 0
|
||||||
@ -29,6 +32,21 @@ void crypto_initialize()
|
|||||||
irq_enable(IRQ_AES);
|
irq_enable(IRQ_AES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void crypto_ipc(volatile ipc_request *req)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (req->req) {
|
||||||
|
case IPC_KEYS_GETOTP:
|
||||||
|
memcpy((void *)req->args[0], &otp, sizeof(otp));
|
||||||
|
dc_flushrange((void *)req->args[0], sizeof(otp));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gecko_printf("IPC: unknown SLOW CRYPTO request %04x\n",
|
||||||
|
req->req);
|
||||||
|
}
|
||||||
|
ipc_post(req->code, req->tag, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _aes_irq = 0;
|
static int _aes_irq = 0;
|
||||||
|
|
||||||
@ -99,4 +117,25 @@ void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aes_ipc(volatile ipc_request *req)
|
||||||
|
{
|
||||||
|
switch (req->req) {
|
||||||
|
case IPC_AES_RESET:
|
||||||
|
aes_reset();
|
||||||
|
break;
|
||||||
|
case IPC_AES_SETIV:
|
||||||
|
aes_set_iv((u8 *)req->args);
|
||||||
|
break;
|
||||||
|
case IPC_AES_SETKEY:
|
||||||
|
aes_set_key((u8 *)req->args);
|
||||||
|
break;
|
||||||
|
case IPC_AES_DECRYPT:
|
||||||
|
aes_decrypt((u8 *)req->args[0], (u8 *)req->args[1],
|
||||||
|
req->args[2], req->args[3]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gecko_printf("IPC: unknown SLOW AES request %04x\n",
|
||||||
|
req->req);
|
||||||
|
}
|
||||||
|
ipc_post(req->code, req->tag, 0);
|
||||||
|
}
|
||||||
|
3
crypto.h
3
crypto.h
@ -2,6 +2,7 @@
|
|||||||
#define __CRYPTO_H__ 1
|
#define __CRYPTO_H__ 1
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -42,6 +43,7 @@ typedef struct
|
|||||||
extern otp_t otp;
|
extern otp_t otp;
|
||||||
|
|
||||||
void crypto_read_otp();
|
void crypto_read_otp();
|
||||||
|
void crypto_ipc(volatile ipc_request *req);
|
||||||
|
|
||||||
void crypto_initialize();
|
void crypto_initialize();
|
||||||
|
|
||||||
@ -50,5 +52,6 @@ void aes_set_iv(u8 *iv);
|
|||||||
void aes_empty_iv();
|
void aes_empty_iv();
|
||||||
void aes_set_key(u8 *key);
|
void aes_set_key(u8 *key);
|
||||||
void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv);
|
void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv);
|
||||||
|
void aes_ipc(volatile ipc_request *req);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
7
ipc.c
7
ipc.c
@ -7,6 +7,7 @@
|
|||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
static volatile ipc_request in_queue[IPC_IN_SIZE] ALIGNED(32) MEM2_BSS;
|
static volatile ipc_request in_queue[IPC_IN_SIZE] ALIGNED(32) MEM2_BSS;
|
||||||
static volatile ipc_request out_queue[IPC_OUT_SIZE] ALIGNED(32) MEM2_BSS;
|
static volatile ipc_request out_queue[IPC_OUT_SIZE] ALIGNED(32) MEM2_BSS;
|
||||||
@ -95,6 +96,12 @@ static int process_slow(volatile ipc_request *req)
|
|||||||
case IPC_DEV_NAND:
|
case IPC_DEV_NAND:
|
||||||
nand_ipc(req);
|
nand_ipc(req);
|
||||||
break;
|
break;
|
||||||
|
case IPC_DEV_KEYS:
|
||||||
|
crypto_ipc(req);
|
||||||
|
break;
|
||||||
|
case IPC_DEV_AES:
|
||||||
|
aes_ipc(req);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
|
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
|
||||||
}
|
}
|
||||||
|
10
ipc.h
10
ipc.h
@ -6,10 +6,11 @@
|
|||||||
#define IPC_FAST 0x01
|
#define IPC_FAST 0x01
|
||||||
#define IPC_SLOW 0x00
|
#define IPC_SLOW 0x00
|
||||||
|
|
||||||
#define IPC_DEV_SYS 0x00
|
#define IPC_DEV_SYS 0x00
|
||||||
#define IPC_DEV_NAND 0x01
|
#define IPC_DEV_NAND 0x01
|
||||||
#define IPC_DEV_SD 0x02
|
#define IPC_DEV_SD 0x02
|
||||||
#define IPC_DEV_KEYS 0x03
|
#define IPC_DEV_KEYS 0x03
|
||||||
|
#define IPC_DEV_AES 0x04
|
||||||
#define IPC_DEV_MISC 0x10
|
#define IPC_DEV_MISC 0x10
|
||||||
|
|
||||||
#define IPC_SYS_PING 0x0000
|
#define IPC_SYS_PING 0x0000
|
||||||
@ -45,6 +46,11 @@
|
|||||||
#define IPC_KEYS_GETOTP 0x0000
|
#define IPC_KEYS_GETOTP 0x0000
|
||||||
#define IPC_KEYS_GETEEP 0x0001
|
#define IPC_KEYS_GETEEP 0x0001
|
||||||
|
|
||||||
|
#define IPC_AES_RESET 0x0000
|
||||||
|
#define IPC_AES_SETIV 0x0001
|
||||||
|
#define IPC_AES_SETKEY 0x0002
|
||||||
|
#define IPC_AES_DECRYPT 0x0003
|
||||||
|
|
||||||
#define IPC_MISC_BACKUP_DOBLOCK 0x0001
|
#define IPC_MISC_BACKUP_DOBLOCK 0x0001
|
||||||
|
|
||||||
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
|
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
|
||||||
|
3
irq.c
3
irq.c
@ -4,6 +4,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
#include "nand.h"
|
||||||
|
|
||||||
void irq_setup_stack(void);
|
void irq_setup_stack(void);
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ void irq_handler(void)
|
|||||||
write32(HW_IRQFLAG, IRQF_TIMER);
|
write32(HW_IRQFLAG, IRQF_TIMER);
|
||||||
}
|
}
|
||||||
if(flags & IRQF_NAND) {
|
if(flags & IRQF_NAND) {
|
||||||
gecko_printf("IRQ: NAND\n");
|
// gecko_printf("IRQ: NAND\n");
|
||||||
write32(NAND_CMD, 0x7fffffff); // shut it up
|
write32(NAND_CMD, 0x7fffffff); // shut it up
|
||||||
write32(HW_IRQFLAG, IRQF_NAND);
|
write32(HW_IRQFLAG, IRQF_NAND);
|
||||||
nand_irq();
|
nand_irq();
|
||||||
|
7
main.c
7
main.c
@ -16,9 +16,6 @@
|
|||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
|
|
||||||
// TODO: move to powerpc
|
|
||||||
#include "nandfs.h"
|
|
||||||
|
|
||||||
void *vector;
|
void *vector;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -174,10 +171,6 @@ void *_main(void *base)
|
|||||||
nand_initialize();
|
nand_initialize();
|
||||||
gecko_puts("NAND initialized.\n");
|
gecko_puts("NAND initialized.\n");
|
||||||
|
|
||||||
// TODO: move to powerpc
|
|
||||||
nandfs_initialize();
|
|
||||||
gecko_puts("NAND FS initialized.\n");
|
|
||||||
|
|
||||||
gecko_puts("Initializing IPC...\n");
|
gecko_puts("Initializing IPC...\n");
|
||||||
ipc_initialize();
|
ipc_initialize();
|
||||||
|
|
||||||
|
10
nand.c
10
nand.c
@ -53,7 +53,7 @@ void nand_irq(void)
|
|||||||
code = ipc_code;
|
code = ipc_code;
|
||||||
tag = ipc_tag;
|
tag = ipc_tag;
|
||||||
ipc_code = ipc_tag = 0;
|
ipc_code = ipc_tag = 0;
|
||||||
ipc_post(code, tag, 1, 0);
|
ipc_post(code, tag, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,25 +195,25 @@ void nand_ipc(volatile ipc_request *req)
|
|||||||
switch (req->req) {
|
switch (req->req) {
|
||||||
case IPC_NAND_RESET:
|
case IPC_NAND_RESET:
|
||||||
nand_reset();
|
nand_reset();
|
||||||
ipc_post(req->code, req->tag, 1, 0);
|
ipc_post(req->code, req->tag, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_NAND_GETID:
|
case IPC_NAND_GETID:
|
||||||
ipc_post(req->code, req->tag, 2, 0, nand_get_id());
|
ipc_post(req->code, req->tag, 1, nand_get_id());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_NAND_READ:
|
case IPC_NAND_READ:
|
||||||
ipc_code = req->code;
|
ipc_code = req->code;
|
||||||
ipc_tag = req->tag;
|
ipc_tag = req->tag;
|
||||||
nand_read_page(req->args[0], (void *)req->args[1],
|
nand_read_page(req->args[0], (void *)req->args[1],
|
||||||
(void *)req->args[1]);
|
(void *)req->args[2]);
|
||||||
break;
|
break;
|
||||||
#ifdef NAND_SUPPORT_WRITE
|
#ifdef NAND_SUPPORT_WRITE
|
||||||
case IPC_NAND_WRITE:
|
case IPC_NAND_WRITE:
|
||||||
ipc_code = req->code;
|
ipc_code = req->code;
|
||||||
ipc_tag = req->tag;
|
ipc_tag = req->tag;
|
||||||
nand_write_page(req->args[0], (void *)req->args[1],
|
nand_write_page(req->args[0], (void *)req->args[1],
|
||||||
(void *)req->args[1]);
|
(void *)req->args[2]);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef NAND_SUPPORT_ERASE
|
#ifdef NAND_SUPPORT_ERASE
|
||||||
|
214
nandfs.c
214
nandfs.c
@ -1,214 +0,0 @@
|
|||||||
#include "nandfs.h"
|
|
||||||
#include "nand.h"
|
|
||||||
#include "gecko.h"
|
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
#define PAGE_SIZE 2048
|
|
||||||
|
|
||||||
struct _nandfs_file_node {
|
|
||||||
u8 name[NANDFS_NAME_LEN];
|
|
||||||
u8 attr;
|
|
||||||
u8 wtf;
|
|
||||||
union {
|
|
||||||
u16 first_child;
|
|
||||||
u16 first_cluster;
|
|
||||||
};
|
|
||||||
u16 sibling;
|
|
||||||
u32 size;
|
|
||||||
u32 uid;
|
|
||||||
u16 gid;
|
|
||||||
u32 dummy;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct _nandfs_sffs {
|
|
||||||
u8 magic[4];
|
|
||||||
u32 version;
|
|
||||||
u32 dummy;
|
|
||||||
|
|
||||||
s16 cluster_table[32768];
|
|
||||||
struct _nandfs_file_node files[6143];
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
static struct _nandfs_sffs sffs __attribute__((aligned(32))) MEM2_BSS;
|
|
||||||
static u8 buffer[8*2048] __attribute__((aligned(32))) MEM2_BSS;
|
|
||||||
static s32 initialized = 0;
|
|
||||||
|
|
||||||
s32 nandfs_initialize()
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
u32 supercluster = 0;
|
|
||||||
u32 supercluster_version = 0;
|
|
||||||
|
|
||||||
nand_reset();
|
|
||||||
|
|
||||||
for(i = 0x7F00; i < 0x7fff; i++) {
|
|
||||||
nand_read_page(i*8, (void *)&sffs, NULL);
|
|
||||||
if(memcmp(sffs.magic, "SFFS", 4) != 0)
|
|
||||||
continue;
|
|
||||||
if(supercluster == 0 || sffs.version > supercluster_version) {
|
|
||||||
supercluster = i;
|
|
||||||
supercluster_version = sffs.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(supercluster == 0) {
|
|
||||||
gecko_printf("no supercluster found. "
|
|
||||||
" your nand filesystem is seriously broken...\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
gecko_printf("using supercluster starting at page %08x\n",
|
|
||||||
supercluster);
|
|
||||||
|
|
||||||
for(i = 0; i < sizeof(struct _nandfs_sffs)/(PAGE_SIZE*8);
|
|
||||||
i++) {
|
|
||||||
/* nand_read_cluster(supercluster + i,
|
|
||||||
((u8 *)&sffs) + (i * PAGE_SIZE * 8));*/
|
|
||||||
}
|
|
||||||
|
|
||||||
initialized = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 nandfs_open(struct nandfs_fp *fp, const char *path)
|
|
||||||
{
|
|
||||||
char *ptr, *ptr2;
|
|
||||||
u32 len;
|
|
||||||
struct _nandfs_file_node *cur = sffs.files;
|
|
||||||
|
|
||||||
if (initialized != 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memset(fp, 0, sizeof(*fp));
|
|
||||||
|
|
||||||
if(strcmp(cur->name, "/") != 0) {
|
|
||||||
gecko_printf("your nandfs is corrupted. fixit!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = &sffs.files[cur->first_child];
|
|
||||||
|
|
||||||
ptr = (char *)path;
|
|
||||||
do {
|
|
||||||
ptr++;
|
|
||||||
ptr2 = strchr(ptr, '/');
|
|
||||||
if (ptr2 == NULL)
|
|
||||||
len = strlen(ptr);
|
|
||||||
else {
|
|
||||||
ptr2++;
|
|
||||||
len = ptr2 - ptr - 1;
|
|
||||||
}
|
|
||||||
if (len > 12)
|
|
||||||
{
|
|
||||||
gecko_printf("invalid length: %s %s %s [%d]\n",
|
|
||||||
ptr, ptr2, path, len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
gecko_printf("length: %d\n", len);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
int res = strncmp(cur->name, ptr, len);
|
|
||||||
if(ptr2 != NULL && strncmp(cur->name, ptr, len) == 0
|
|
||||||
&& strnlen(cur->name, 12) == len
|
|
||||||
&& (cur->attr&3) == 2
|
|
||||||
&& (cur->first_child&0xffff) != (s16)0xffff) {
|
|
||||||
cur = &sffs.files[cur->first_child];
|
|
||||||
ptr = ptr2-1;
|
|
||||||
break;
|
|
||||||
} else if(ptr2 == NULL &&
|
|
||||||
strncmp(cur->name, ptr, len) == 0 &&
|
|
||||||
strnlen(cur->name, 12) == len &&
|
|
||||||
(cur->attr&3) == 1) {
|
|
||||||
break;
|
|
||||||
} else if((cur->sibling&0xffff) != 0xffff) {
|
|
||||||
cur = &sffs.files[cur->sibling];
|
|
||||||
} else {
|
|
||||||
gecko_printf("unable to find %s (%s)\n", ptr,
|
|
||||||
path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} while(ptr2 != NULL);
|
|
||||||
|
|
||||||
fp->first_cluster = cur->first_cluster;
|
|
||||||
fp->cur_cluster = fp->first_cluster;
|
|
||||||
fp->offset = 0;
|
|
||||||
fp->size = cur->size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 nandfs_read(void *ptr, u32 size, u32 nmemb, struct nandfs_fp *fp)
|
|
||||||
{
|
|
||||||
u32 total = size*nmemb;
|
|
||||||
u32 copy_offset, copy_len;
|
|
||||||
|
|
||||||
if (initialized != 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (fp->offset + total > fp->size)
|
|
||||||
total = fp->size - fp->offset;
|
|
||||||
|
|
||||||
if (total == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while(total > 0) {
|
|
||||||
// nand_read_decrypted_cluster(fp->cur_cluster, buffer);
|
|
||||||
copy_offset = fp->offset % (PAGE_SIZE * 8);
|
|
||||||
copy_len = (PAGE_SIZE * 8) - copy_offset;
|
|
||||||
if(copy_len > total)
|
|
||||||
copy_len = total;
|
|
||||||
memcpy(ptr, buffer + copy_offset, copy_len);
|
|
||||||
total -= copy_len;
|
|
||||||
fp->offset += copy_len;
|
|
||||||
|
|
||||||
if ((copy_offset + copy_len) >= (PAGE_SIZE * 8))
|
|
||||||
fp->cur_cluster = sffs.cluster_table[fp->cur_cluster];
|
|
||||||
}
|
|
||||||
|
|
||||||
return size*nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 nandfs_seek(struct nandfs_fp *fp, s32 offset, u32 whence)
|
|
||||||
{
|
|
||||||
if (initialized != 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
switch (whence) {
|
|
||||||
case NANDFS_SEEK_SET:
|
|
||||||
if (offset > fp->size)
|
|
||||||
return -1;
|
|
||||||
if (offset > 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
fp->offset = offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NANDFS_SEEK_CUR:
|
|
||||||
if ((fp->offset + offset) > fp->size ||
|
|
||||||
(fp->offset + offset) < 0)
|
|
||||||
return -1;
|
|
||||||
fp->offset += offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NANDFS_SEEK_END:
|
|
||||||
default:
|
|
||||||
if ((fp->size + offset) > fp->size ||
|
|
||||||
(fp->size + offset) < 0)
|
|
||||||
return -1;
|
|
||||||
fp->offset = fp->size + offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int skip = fp->offset;
|
|
||||||
fp->cur_cluster = fp->first_cluster;
|
|
||||||
while (skip > (2048*8)) {
|
|
||||||
fp->cur_cluster = sffs.cluster_table[fp->cur_cluster];
|
|
||||||
skip -= 2048*8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
25
nandfs.h
25
nandfs.h
@ -1,25 +0,0 @@
|
|||||||
#ifndef __NANDFS_H__
|
|
||||||
#define __NANDFS_H__
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
#define NANDFS_NAME_LEN 12
|
|
||||||
|
|
||||||
#define NANDFS_SEEK_SET 0
|
|
||||||
#define NANDFS_SEEK_CUR 1
|
|
||||||
#define NANDFS_SEEK_END 2
|
|
||||||
|
|
||||||
struct nandfs_fp {
|
|
||||||
s16 first_cluster;
|
|
||||||
s32 cur_cluster;
|
|
||||||
u32 size;
|
|
||||||
u32 offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
s32 nandfs_initialize();
|
|
||||||
|
|
||||||
s32 nandfs_open(struct nandfs_fp *fp, const char *path);
|
|
||||||
s32 nandfs_read(void *ptr, u32 size, u32 nmemb, struct nandfs_fp *fp);
|
|
||||||
s32 nandfs_seek(struct nandfs_fp *fp, s32 offset, u32 whence);
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
x
Reference in New Issue
Block a user