Installing Linux on internal HDD
From PS3Wiki
Contents |
Booting Debian netinstall with petitboot from USB
- I used a netboot image of Debian for installation: http://d-i.debian.org/daily-images/powerpc/daily/powerpc64/netboot/
- Download vmlinux and initrd.gz and store it on a USB device
- Mount the USB device with petitboot on /mnt/usb
That's how i booted Debian netinstall from petitboot:
kexec -l /mnt/usb/vmlinux --initrd=/mnt/usb/initrd.gz --append="root=/dev/ps3da1 video=720p" sync kexec -e swapoff -a
Installing Debian on internal HDD
- The problem with the default Debian Installer is that it uses the default SONY ps3disk block device driver to access HDD. This driver tries to use the first accessible HDD region for installation, and in petitboot booted with GameOS rights the first accessible HDD region will be the one owned by GameOS (UFS2), so be carefull or you will install your Linux on GameOS HDD region.
- To fix this i patched HV temporarily and disabled access to all HDD regiosn except the one for Linux during Debian installation.
- In the next days i will try to recompile the Debian Squeeze Installer and replace the default SONY ps3disk device driver with my own which i already tested on my PS3 Linux successfully.
Additional Linux Device Drivers
- I use vanilla Linux kernels on my PS3 and do not modify it at all except patching disk and flash block device drivers in order to get access to several HDD, FLASH and VFLASH regions at once
- You will also need additional Linux block device drivers for VFLASH and FLASH storage devices
- I will soon upload all the additional drivers i implemented
ps3ram.c
- It allows you full access to 256 MB of PS3 with patched HV call 114
/*
* PS3 RAM Driver
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <asm/lv1call.h>
#define DEVICE_NAME "ps3ram"
#define RAM_SIZE (256 * 1024 * 1024)
static u64 ps3ram_lpar_addr;
static u8 *ps3ram;
static loff_t ps3ram_llseek(struct file *file, loff_t offset, int origin)
{
loff_t res;
mutex_lock(&file->f_mapping->host->i_mutex);
switch (origin) {
case 1:
offset += file->f_pos;
break;
case 2:
offset += RAM_SIZE;
break;
}
if (offset < 0) {
res = -EINVAL;
goto out;
}
file->f_pos = offset;
res = file->f_pos;
out:
mutex_unlock(&file->f_mapping->host->i_mutex);
return res;
}
static ssize_t ps3ram_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
u64 size;
u8 *src;
int res;
pr_debug("%s:%u: Reading %zu bytes at position %lld to U0x%p\n",
__func__, __LINE__, count, *pos, buf);
size = RAM_SIZE;
if (*pos >= size || !count)
return 0;
if (*pos + count > size) {
pr_debug("%s:%u Truncating count from %zu to %llu\n", __func__,
__LINE__, count, size - *pos);
count = size - *pos;
}
src = ps3ram + *pos;
pr_debug("%s:%u: copy %lu bytes from 0x%p to U0x%p\n",
__func__, __LINE__, count, src, buf);
if (buf) {
if (copy_to_user(buf, src, count)) {
res = -EFAULT;
goto fail;
}
}
*pos += count;
return count;
fail:
return res;
}
static ssize_t ps3ram_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
u64 size;
u8 *dst;
int res;
pr_debug("%s:%u: Writing %zu bytes at position %lld from U0x%p\n",
__func__, __LINE__, count, *pos, buf);
size = RAM_SIZE;
if (*pos >= size || !count)
return 0;
if (*pos + count > size) {
pr_debug("%s:%u Truncating count from %zu to %llu\n", __func__,
__LINE__, count, size - *pos);
count = size - *pos;
}
dst = ps3ram + *pos;
pr_debug("%s:%u: copy %lu bytes from U0x%p to 0x%p\n",
__func__, __LINE__, count, buf, dst);
if (buf) {
if (copy_from_user(dst, buf, count)) {
res = -EFAULT;
goto fail;
}
}
*pos += count;
return count;
fail:
return res;
}
static const struct file_operations ps3ram_fops = {
.owner = THIS_MODULE,
.llseek = ps3ram_llseek,
.read = ps3ram_read,
.write = ps3ram_write,
};
static struct miscdevice ps3ram_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &ps3ram_fops,
};
static int __init ps3ram_init(void)
{
int res;
res = lv1_undocumented_function_114(0, PAGE_SHIFT, RAM_SIZE, &ps3ram_lpar_addr);
if (res) {
pr_debug("%s:%u: lpar map failed %d\n", __func__, __LINE__, res);
res = -EFAULT;
goto fail;
}
ps3ram = ioremap(ps3ram_lpar_addr, RAM_SIZE);
if (!ps3ram) {
pr_debug("%s:%d: ioremap failed\n", __func__, __LINE__);
res = -EFAULT;
goto fail_lpar_unmap;
}
res = misc_register(&ps3ram_misc);
if (res) {
pr_debug("%s:%u: misc_register failed %d\n",
__func__, __LINE__, res);
goto fail_iounmap;
}
pr_debug("%s:%u: registered misc device %d\n",
__func__, __LINE__, ps3ram_misc.minor);
return 0;
fail_iounmap:
iounmap(ps3ram);
fail_lpar_unmap:
lv1_undocumented_function_115(ps3ram_lpar_addr);
fail:
return res;
}
static void __exit ps3ram_exit(void)
{
misc_deregister(&ps3ram_misc);
iounmap(ps3ram);
lv1_undocumented_function_115(ps3ram_lpar_addr);
}
module_init(ps3ram_init);
module_exit(ps3ram_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PS3 RAM Driver");
MODULE_AUTHOR("Graf Chokolo");
Usage:
# hexdump -C /dev/ps3ram | less