资源预览内容
第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
第9页 / 共15页
第10页 / 共15页
亲,该文档总共15页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
PSPPSP 模块教程模块教程自译挖坑PSP 模块教程 (ModuleTutorialv1)本帖最后由 natuki 于 2009-10-29 22:45 编辑 自译挖坑PSP 模块教程 (ModuleTutorialv1)译到 8.1.5 没动力了,考试挖坑提醒自己,也希望有心人拍砖指导=模块,输出,输入,补丁一,建立模块,纯输出/程序。二,后台到底发生了啥,内核如何管理模块及其 IO。三,如何动态 patch 内存里的模块,以改变系统行为满足需要。读者要懂点 C ,PSPSDK(怎么编译跑一个 HELLOworld) ,要是懂点MIPS 汇编的基础概念会更好。1 引言最为 PSP 开发新手,你大概装了 PSPSDK,玩了玩 cygwin,或者装了个本地 POSIX 环境然后你试着编译运行了 SDK 的示例。你多少熟悉 C 语言编程,你知道 Makefile 咋工作,还有点儿汇编的基本知识(MIPS 汇编,我们只是碰到点儿简单的,像寄存器/CPU 的指令集) ,然后往下看。读了些东西 google 了些东西,你知道 PRX 和 ELF 的不同,知道内核模式和用户模式是啥,你写了第一个 helloworld 程序,创建了自己的 EBOOT.PBP。现在你问“嗯接下来做啥?” ,你面前有两条路:你可以加入内核一方,关心内核内部的细节;或者加入用户一方,考虑PSP 和 PSPSDK 作为一组 API,在上面做自制程序。不管是那边,我们都希望这里解释的东西会有点儿用。2 目标和非目标这个教程打算说说“下一步做啥”对于 PSP 编程来说,试图填上“我能跑一个 helloworld”和“我能写自己的固件和降级程序”之间的空白。 (提醒一下这空白还很大)不是从零开始的教程,下面几点不会讲,许多教程已经讲过了:。怎么用 SDK 建开发环境。虽然不是直接必要,但是你需要知道如何编译自己的例子和代码片段。清楚“helloworld”main.c 文件和相关的 makefile 结构。知道怎么配置 PSP 跑自制程序,不管是用啥固件。知道怎么用 PSPLINK 启动,传输,及调试程序。盗版,改芯片,非法动作在这个教程里面,要考虑下边的话题:。非常基础的 MIPS 汇编。最好懂点 MIPS 汇编指令和 CPU 寄存器,会帮助你理解细节。如何建立模块(像 PRX) ,定义输出库与输出函数(纯输出模块) 。由于技术和设计原因(目前的 PSPSDK 不支持)只能从已知模块输出函数,而不能是变量。注意这不是致命问题,你想输出变量的时候,可以总是包装起来或者改变属性。像 int get_i()和 void set_i()来对付 i 的值。如何建立其他的模块用于输入输出函数。管道的角色,如何建立输入表,什么是 NID,怎么计算。如何动态建立可执行输出函数。PSP 内核如何管理加载内核。抽象数据类型包含什么,模块性息如何保存于内存。如何动态修改已存在的模块(“patching”补丁) ,其实用的具体情况。根据这教程更多目的,需要一个 1.5 的固件。我个人用的是 PSPSDK的最近子版本,在 Linux 系统上,我的固件是 3.03OE-C。这教程里我们在内核模式工作是为了简便,也是为了些技术原因。技术原因是,我们要看看模块系统的内部细节,而有些函数像sceKernelFindModuleByName 只能在内核模式。为了简便是因为,要想克服这些限制,就需要做点小手脚,像是包装函数,或者让不受限用户访问内核呼叫的方法,即名叫“桥” ,例如 kubridge 或者kvshbridge,这就会超出教程范围了。结果的 EBOT.PBP 应当放到GAME150 文件夹里,并且包含一个静态 ELF 在主程序中。EBOOT.PBP和需要的 PRX 们放在一起。3 感谢我没装做这里的想法都是我的或者原创的。有些技术和计算机科学一样老,不限于 PSP。PSP 相关的信息收集于一些源,站点,典型的有:。PSPDEV 站点 http:/www.pspdev.org 以及它论坛许多帖子。MPH 站点,破解 NID 函数注目。Tyranid 优秀的 PSPLink,PSPSDK 和 PRXTOOL 程序。PspPet 如 PSARDumper 之类的主意和代码。Moonlight / Dark_Alex 自制固件理念的证明。google 朋友。还有很多,很多4 系统模型整个教程,我们考虑一下系统模型:一个叫“客户端”的实体,从一个叫“服务器”的实体请求服务,“服务器”依次参考另外一个“管理员”实体, “管理员”实体基于一个标识符对客户端进行提权。 “管理员”是一个封闭的系统,并且可以抽出低层操作。每个系统都以一个模块来实现。服务器和管理员应该是输出模块。5 PRX 与 ELF 模块5.1 啥是 ELF?ELF (Executable and Linking Format) 是目标文件即 object file 的一种格式。ELF 对于可执行来说,是可重定位以及共享对象(一般是模块) ,正如 GIF 或 JPG 之于图像。ELF 标准从基础上确定一个文件的二进制格式。在简单情况下,它定义一个 ELF 头部,后跟若干段。每个段有一个目的,例如包含模块程序指令,定义模块输出函数,定义模块输入函数;包括已初始化。5.2 啥是 PRX?PRX (Relocatable eXecutable)类似 ELF。 (这段待补完)5.3 啥是 EBOOT?EBOOT.PBP 文件类似于 Windows 里的 exe 文件。它将主可执行文件和其他元数据(metadata)文件打包在一起,如用于在 XMB 下显示的.png 文件,同样用于在 XMB 下显示的.sfo 视频文件。PBP 文件的格式是简单的:它有一个固定大小的 PBP 头部,包括:一个 4byte 的幻数(magic number 译)(0,P,B,P) ,一个 u32 版本号,8个偏移到打包的文件“PARAM.SFO” , “ICON1.PMF” ,“UNKNOWN.PNG” , “PIC1.PNG” , “SND0.AT3” , “UNKNOWN.PSP”和“UNKNOWN.PSAR” 。5.4 限制使用 OE 固件时,1.5 内核可以启动一个 EBOOT 中的静态 elf,而不用对其进行 kxploit,不论是在内核模式还是用户模式。对于 3.03固件,模块则需要是 PRX 格式并且在用户模式下。从 3.10 OE 开始,模块如果在用户模式下,则可以是静态 ELF 和 PRX。因为 OE 固件是破解过的,所以你可以从放在 MS 上的用户模式,使用内核模式加载并启动模块,如果你需要内核模式的程序,创建一个用户模式的外壳,用来加载启动内核内存区的主程序。6 初始化6.1 模块入口:crt0 ,启动文件,以及 module_start当 PSP 内核加载,启动一个模块,例如一个程序时,它读取 EBOOT.PBP 文件,抽取出 ELF 或者 PRX 模块(二者在此教程的目的下基本上是一个东西,仅有几点细节区别,如固定与可重定位的内存地址) ,分析模块段,进行一些链接,来用已加载的模块输出 和系统呼叫“连接”模块的输入,在内存中创建一份复制,然后进入到模块入口。另外模块的开发者需要做决定,是在一个新的独立的线程来执行模块入口,还是让申请加载与启动模块的线程来执行。前者意味着一个叫“主线程”的建立(main 这名字和经典 C 函数的 main没关系) ,后者意味着你需要仔细参考在入口点会进行什么样的操作:若模块将要被用作函数库,或只是简单加载另外的工作线程,入口点就会是简单的,并且不需要独立的线程,但是如果要做更复杂的事,就需要个主线程(没有主线程就不能在入口点中休眠) 。有定义主线程特点的宏,如是否在内核模式运行,vsh 模式,或用户模式,是否会使用 VFPU,等等。因此,内核需要两个基本的东西,a)要能够读取/分析模块信息,b)知道模块入口点在哪儿能找到。特别地,内核希望能找到 ELF/PRX 中的段,段给出了模块信息,模块输出标识符(函数) ,叫做 module_start。不断的重复同样的任务,敲入需要的 boilerplate 代码是很不舒服的工作。因此,SDK 抽象出一些细节,提供给你舒适的宏,作为替代。6.1.1 模块信息使用宏 PSP_MODULE_INFO 可以容易的给出需要的模块性息。PSP_MODULE_INFO(“Module name“, 0x1000, 1, 0);复制代码这个宏用于陈述模块的名字,模块的“模式” (内核,用户或 VSH) ,以及主副版本(v1.0) 。在内部,这个宏声明sceModuleInfo 来包含模块属性,模块名字,以及指针,指针指向包含模块输出(显出以供他用)输入(从其他模块使用)标识符的表格,并且定义需要的 ELF/PRX 段,内核将会在段里寻找这些信息。/*模块信息结构, 用于声明一个模块 (库 或 可执行) 。此结构在所有的 PSP 可执行里面都需要。*/typedef struct _scemoduleinfo unsigned short modattribute;unsigned char modversion2;char modname27;char terminal;void * gp_value;void * ent_top;void * ent_end;void * stub_top;void * stub_end; _sceModuleInfo;typedef const _sceModuleInfo SceModuleInfo;复制代码关于宏的细节,查看 pspsdk/src/user/pspmoduleinfo.h模块模式你在此陈述你是想要用户模式还是内核模式(或者其他的超出此教程,如 VSH) 。历史上,在许多程序里使用数字值。清晰起见,也许你想用稍详细点儿的:enum PspModuleInfoAttrPSP_MODULE_USER = 0,PSP_MODULE_KERNEL = 0X1000,;复制代码 6.1.2 主线程 还是 不要主线程?就像前面讨论过的,你需要决定是否要一个新线程(不清楚就是要)。如果不需要/需要的话,可以使用宏 PSP_NO_CREATE_MAIN_THREAD()复制代码就行了。相反,如果你想要主线程,你可以扭转几个参数,使用以下宏:PSP_MAIN_THREAD_PRIORITY(priority)PSP_MAIN_THREAD_STACK_SIZE_KB(size_kb) PSP_MAIN_THREAD_ATTR(attr)PSP_MAIN_THREAD_NAME(S)复制代码或者使用一个单一的。#define PSP_MAIN_THREAD_PARAMS(priority, size_kb, attribute) PSP_MAIN_THREAD_PRIORITY(priority);PSP_MAIN_THREAD_STACK_SIZE_KB(size_kb);PSP_MAIN_THREAD_ATTR(attribute)复制代码 6.1.3 堆大小最后,你可以定义一定量的内存用于分配给堆(内存池,通过类似malloc/ free 之类函数可在里面分配与取消内存) 。这超出目前教程范围,只是说一下这个宏名字:PSP_HEAP_SIZE_KB(size_kb)复制代码有些情况下,可能会想要取成 0。6.1.4 我的 main 在哪儿呢?若你有 C 编程过,
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号