1 #include <psl1ght/lv2.h>
4 #include <sysutil/video.h>
6 #include <rsx/reality.h>
14 #include "peek_poke.h"
20 void xputs(const char *msg
);
22 VideoConfiguration vconfig
;
25 unsigned char *read_file(FILE * f
, size_t * sz
)
30 fseek(f
, 0, SEEK_END
);
32 fseek(f
, 0, SEEK_SET
);
34 unsigned char *userlandBuffer
= malloc(*sz
);
35 if (!userlandBuffer
) {
38 fread(userlandBuffer
, 1, *sz
, f
);
40 if (*((u32
*) userlandBuffer
) == 0) {
42 userlandBuffer
= NULL
;
44 return userlandBuffer
;
58 gcmContextData
*context
;
60 int currentBuffer
= 0;
65 // Block the PPU thread untill the previous flip operation has finished.
66 while (gcmGetFlipStatus() != 0) {
74 assert(gcmSetFlip(context
, buffer
) == 0);
75 realityFlushBuffer(context
);
76 gcmSetWaitFlip(context
);
79 void makeBuffer(int id
, int size
)
81 buffer
*buf
= malloc(sizeof(buffer
));
82 buf
->ptr
= rsxMemAlign(16, size
);
83 assert(buf
->ptr
!= NULL
);
85 assert(realityAddressToOffset(buf
->ptr
, &buf
->offset
) == 0);
86 assert(gcmSetDisplayBuffer
87 (id
, buf
->offset
, res
.width
* 4, res
.width
, res
.height
) == 0);
89 buf
->width
= res
.width
;
90 buf
->height
= res
.height
;
100 lv1_undocumented_function_114(0, 0xC, HV_SIZE
, &mmap_lpar_addr
);
102 snprintf(buf
, sizeof(buf
),
103 "Error code %d calling lv1_undocumented_function_114",
109 mm_map_lpar_memory_region(mmap_lpar_addr
, HV_BASE
, HV_SIZE
, 0xC, 0);
111 snprintf(buf
, sizeof(buf
),
112 "Error code %d calling mm_map_lpar_memory_region",
122 if (mmap_lpar_addr
!= 0) {
123 lv1_undocumented_function_115(mmap_lpar_addr
);
129 void *host_addr
= memalign(1024 * 1024, 1024 * 1024);
130 assert(host_addr
!= NULL
);
132 context
= realityInit(0x10000, 1024 * 1024, host_addr
);
133 assert(context
!= NULL
);
135 assert(videoGetState(0, 0, &state
) == 0);
136 assert(state
.state
== 0);
138 assert(videoGetResolution(state
.displayMode
.resolution
, &res
) == 0);
140 memset(&vconfig
, 0, sizeof(VideoConfiguration
));
141 vconfig
.resolution
= state
.displayMode
.resolution
;
142 vconfig
.format
= VIDEO_BUFFER_FORMAT_XRGB
;
143 vconfig
.pitch
= res
.width
* 4;
145 assert(videoConfigure(0, &vconfig
, NULL
, 0) == 0);
146 assert(videoGetState(0, 0, &state
) == 0);
148 s32 buffer_size
= 4 * res
.width
* res
.height
;
150 gcmSetFlipMode(GCM_FLIP_VSYNC
);
151 makeBuffer(0, buffer_size
);
152 makeBuffer(1, buffer_size
);
154 gcmResetFlipStatus();
158 static const struct {
162 } s_known_platforms
[] = {
164 0x1600C0ULL
, "FAT 16M", "3.55"}, {
165 0x0980C0ULL
, "FAT 256M", "3.55"}, {
166 0x0A7E60ULL
, "Slim", "3.55"}, {
167 0x12A0C0ULL
, "FAT 256M", "3.15"},};
169 #define NBELMS(a) (sizeof((a))/sizeof((a)[0]))
171 void install_bootos()
175 uint64_t lv2_kernel_filename_offset
= 0;
179 xputs("Mapping LV1...");
182 xputs("Cannot map LV1!");
186 /* First try quickscanning the PS3_LPAR kernel filename */
189 ("Quickscanning LV1 PS3_LPAR kernel filename at known offsets...");
191 for (i
= 0; i
< NBELMS(s_known_platforms
); i
++) {
192 if (lv1_peek(s_known_platforms
[i
].offset
) ==
193 0x2F666C682F6F732FULL
194 && lv1_peek(s_known_platforms
[i
].offset
+ 8) ==
195 0x6C76325F6B65726EULL
) {
196 lv2_kernel_filename_offset
=
197 s_known_platforms
[i
].offset
;
207 for (i
= 0; i
< HV_SIZE
; i
+= 8) {
208 if (10 * ten
> HV_SIZE
) {
209 snprintf(ts
, sizeof(ts
),
210 "Scanning LV1 PS3_LPAR kernel filename on full LV1 "
211 "address space... %08llX %02d%%",
213 (int)(i
* (uint64_t) 100 / HV_SIZE
));
218 if (q1
== 0x2F666C682F6F732FULL
219 && q2
== 0x6C76325F6B65726EULL
) {
220 lv2_kernel_filename_offset
= i
- 8;
228 xputs("Unmapping LV1...");
233 xputs("No LV1 PS3_LPAR kernel filename found.");
237 snprintf(ts
, sizeof(ts
),
238 "LV1 PS3_LPAR kernel filename offset at %08llX.",
239 lv2_kernel_filename_offset
& 0xFFFFFFFFULL
);
242 for (i
= 0; i
< NBELMS(s_known_platforms
); i
++) {
243 if (lv2_kernel_filename_offset
== s_known_platforms
[i
].offset
) {
244 snprintf(ts
, sizeof(ts
),
245 "Detected a PS3 %s running FW %s",
246 s_known_platforms
[i
].type
,
247 s_known_platforms
[i
].fw
);
255 ("Please report your PS3 model, its firmware version and the offset found.");
257 // Lv2Patcher works on mapped memory for lv1, and doesn't account for base offset (1<<63)
258 lv2_kernel_filename_offset
+= HV_BASE
;
259 lv2_kernel_filename_offset
&= 0xFFFFFFFFULL
;
262 (837, (u64
) "CELL_FS_IOS:BUILTIN_FLSH1", (u64
) "CELL_FS_FAT",
263 (u64
) "/dev_rwflash", 0, 0, 0, 0, 0)) {
264 xputs("Flash remap failed!");
266 xputs("Reading BootOS...");
267 FILE *f
= fopen("/dev_hdd0/game/LNX000001/USRDIR/bootos.bin", "r");
269 xputs("Cannot open BootOS binary!");
273 u8
*data
= (u8
*) read_file(f
, &sz
);
275 xputs("Cannot read BootOS binary!");
279 unlink("/dev_rwflash/lv2_kernel.self");
281 FILE *g
= fopen("/dev_rwflash/lv2_kernel.self", "w");
284 xputs("Cannot open flash!");
289 sprintf(ts
, "Writing BootOS: %02d%%",
290 (int)((sz1
- sz
) * 100 / sz1
));
293 fwrite(data
+ (sz1
- sz
), CHUNK
, 1, g
);
296 fwrite(data
+ (sz1
- sz
), sz
, 1, g
);
303 xputs("Adding \"Linux\" entry...");
304 f
= fopen("/dev_hdd0/game/LV2000000/USRDIR/linux.txt", "w");
306 xputs("Cannot add a new patchset to LV2 patcher!");
309 fputs("# Linux\nlv1en\n", f
);
310 fprintf(f
, "%08lX: 2f6c6f63616c5f73\n", lv2_kernel_filename_offset
);
311 fprintf(f
, "%08lX: 7973302f6c76325f\n", lv2_kernel_filename_offset
+ 8);
312 fprintf(f
, "%08lX: 6b65726e656c2e73\n",
313 lv2_kernel_filename_offset
+ 16);
314 fprintf(f
, "%08lX: 656c6600\n", lv2_kernel_filename_offset
+ 24);
315 fprintf(f
, "%08lX: 000000000000001b\n",
316 lv2_kernel_filename_offset
+ 0x120);
317 fputs("lv1dis\n", f
);
321 xputs("Creating kboot configuration file...");
322 f
= fopen("/dev_hdd0/kboot.conf", "w");
324 ("Install Debian GNU/Linux=http://ftp.debian.org/debian/dists/squeeze/main/installer-powerpc/current/images/powerpc64/netboot/vmlinux initrd=http://ftp.debian.org/debian/dists/squeeze/main/installer-powerpc/current/images/powerpc64/netboot/initrd.gz preseed/url=http://boot.khore.org/mod/preseed.cfg auto=true interface=auto priority=critical\n",
329 xputs("Creating 10G file...");
330 f = fopen("/dev_hdd0/linux.img", "w");
331 data = malloc(1 << 20);
332 for(i = 0; i < 10240; i++)
333 fwrite(data, 1 << 20, 1, f);
339 xputs("Please run the LV2 patcher.");
343 void xputs(const char *msg
)
350 for (i
= 0; i
< res
.height
; i
++) {
351 for (j
= 0; j
< res
.width
; j
++) {
352 buffers
[currentBuffer
]->ptr
[i
* res
.width
+ j
] =
357 memcpy(buffers
[currentBuffer
]->ptr
,
358 buffers
[!currentBuffer
]->ptr
,
359 res
.width
* res
.height
* sizeof(u32
));
362 memmove(buffers
[currentBuffer
]->ptr
,
363 buffers
[currentBuffer
]->ptr
+ res
.width
* 40,
364 res
.width
* (res
.height
- 40) * sizeof(u32
));
367 for (i
= y
; i
< y
+ 32; i
++) {
368 for (j
= 0; j
< res
.width
; j
++) {
369 buffers
[currentBuffer
]->ptr
[i
* res
.width
+ j
] =
373 print(150, y
, msg
, buffers
[currentBuffer
]->ptr
);
374 if (msg
[strlen(msg
+ 1)] != '%') {
378 currentBuffer
= !currentBuffer
;
387 sconsoleInit(FONT_COLOR_BLACK
, FONT_COLOR_WHITE
, res
.width
, res
.height
);
389 xputs("== BootOS Installer ==");
391 Lv2Syscall1(838, (u64
) "/dev_rwflash");
393 xputs("Press [X] to exit.");
395 ioPadGetInfo(&padinfo
);
396 for (i
= 0; i
< MAX_PADS
; i
++) {
397 if (padinfo
.status
[i
]) {
398 ioPadGetData(i
, &paddata
);
399 if (paddata
.BTN_CROSS
) {