Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Commit

Permalink
Changes required for RISC OS to boot with a new partition offset
Browse files Browse the repository at this point in the history
  • Loading branch information
lurch committed Apr 28, 2014
1 parent 331b30b commit c779efa
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 73 deletions.
9 changes: 5 additions & 4 deletions recovery/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define CONFIG_H

/* Version number displayed in the title bar */
#define VERSION_NUMBER "1.3.2"
#define VERSION_NUMBER "1.3.5"

/* Color of the background */
// #define BACKGROUND_COLOR Qt::white
Expand All @@ -21,7 +21,7 @@
#define HOMEPAGE "http://www.raspberrypi.org/phpBB3/"

/* Location to download the list of available distributions from */
#define DEFAULT_REPO_SERVER "http://downloads.raspberrypi.org/os_list.json"
#define DEFAULT_REPO_SERVER "http://downloads.raspberrypi.org/os_list_v2.json"

/* Size of recovery FAT partition in MB.
* First partition starts at offset 1 MB (sector 2048)
Expand All @@ -42,8 +42,9 @@
#define FAT_PARTITION_OF_IMAGE "/dev/mmcblk0p5"

/* RiscOS magic */
#define RISCOS_SECTOR_OFFSET (1536 * 2048)
#define RISCOS_FAT_SIZE (48 * 2048)
#define RISCOS_OFFSET_KEY "riscos_offset"
#define RISCOS_OFFSET (1760)
#define RISCOS_SECTOR_OFFSET (RISCOS_OFFSET * 2048)

#define RISCOS_BLOB_FILENAME "/mnt/riscos-boot.bin"
#define RISCOS_BLOB_SECTOR_OFFSET (1)
Expand Down
154 changes: 89 additions & 65 deletions recovery/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,23 @@ void MainWindow::repopulate()
}
}

/* Whether this OS should be displayed in the list of installable OSes */
bool canInstallOs(const QString& name, const QVariantMap& values)
{
/* Can't simply pull "name" from "values" because in some JSON files it's "os_name" and in others it's "name"
/* RISC_OS needs a matching riscos_offset */
if (nameMatchesRiscOS(name))
{
if (!values.contains(RISCOS_OFFSET_KEY) || (values.value(RISCOS_OFFSET_KEY).toInt() != RISCOS_OFFSET))
{
return false;
}
}

return true;
}

QMap<QString, QVariantMap> MainWindow::listImages()
{
QMap<QString,QVariantMap> images;
Expand All @@ -329,32 +346,36 @@ QMap<QString, QVariantMap> MainWindow::listImages()
continue;
QVariantMap osv = Json::loadFromFile(imagefolder+"/os.json").toMap();

if (QFile::exists(imagefolder+"/flavours.json"))
QString basename = osv.value("name").toString();
if (canInstallOs(basename, osv))
{
QVariantMap v = Json::loadFromFile(imagefolder+"/flavours.json").toMap();
QVariantList fl = v.value("flavours").toList();

foreach (QVariant f, fl)
if (QFile::exists(imagefolder+"/flavours.json"))
{
QVariantMap fm = f.toMap();
if (fm.contains("name"))
QVariantMap v = Json::loadFromFile(imagefolder+"/flavours.json").toMap();
QVariantList fl = v.value("flavours").toList();

foreach (QVariant f, fl)
{
QString name = fm.value("name").toString();
if (name == RECOMMENDED_IMAGE)
fm["recommended"] = true;
fm["folder"] = imagefolder;
fm["release_date"] = osv.value("release_date");
images[imagefolder+"#"+name] = fm;
QVariantMap fm = f.toMap();
if (fm.contains("name"))
{
QString name = fm.value("name").toString();
if (name == RECOMMENDED_IMAGE)
fm["recommended"] = true;
fm["folder"] = imagefolder;
fm["release_date"] = osv.value("release_date");
images[imagefolder+"#"+name] = fm;
}
}
}
}
else
{
QString name = osv.value("name").toString();
if (name.contains(RECOMMENDED_IMAGE))
osv["recommended"] = true;
osv["folder"] = imagefolder;
images[imagefolder+"#"+name] = osv;
else
{
QString name = basename;
if (name.contains(RECOMMENDED_IMAGE))
osv["recommended"] = true;
osv["folder"] = imagefolder;
images[imagefolder+"#"+name] = osv;
}
}
}

Expand Down Expand Up @@ -885,61 +906,64 @@ void MainWindow::processJson(QVariant json)
{
QVariantMap os = osv.toMap();

if (os.contains("flavours"))
QString basename = os.value("os_name").toString();
if (canInstallOs(basename, os))
{
QVariantList flavours = os.value("flavours").toList();

foreach (QVariant flv, flavours)
if (os.contains("flavours"))
{
QVariantMap flavour = flv.toMap();
QVariantMap item = os;
QString name = flavour.value("name").toString();
QString description = flavour.value("description").toString();
QString iconurl = flavour.value("icon").toString();

item.insert("name", name);
item.insert("description", description);
item.insert("icon", iconurl);
QVariantList flavours = os.value("flavours").toList();

if (!alreadyHasItem(name, item.value("release_date")))
foreach (QVariant flv, flavours)
{
QVariantMap flavour = flv.toMap();
QVariantMap item = os;
QString name = flavour.value("name").toString();
QString description = flavour.value("description").toString();
QString iconurl = flavour.value("icon").toString();

item.insert("name", name);
item.insert("description", description);
item.insert("icon", iconurl);

if (!alreadyHasItem(name, item.value("release_date")))
{
if (!iconurl.isEmpty())
iconurls.insert(iconurl);

bool recommended = (name == RECOMMENDED_IMAGE);
if (recommended)
name += " ["+tr("RECOMMENDED")+"]";

QListWidgetItem *witem = new QListWidgetItem(name+"\n"+description);
witem->setCheckState(Qt::Unchecked);
witem->setData(Qt::UserRole, item);
witem->setData(SecondIconRole, internetIcon);

if (recommended)
ui->list->insertItem(0, witem);
else
ui->list->addItem(witem);
}
}
}
if (os.contains("description"))
{
QString name = basename;
QString description = os.value("description").toString();
if (!alreadyHasItem(name, os.value("release_date")))
{
os["name"] = name;
QString iconurl = os.value("icon").toString();
if (!iconurl.isEmpty())
iconurls.insert(iconurl);

bool recommended = (name == RECOMMENDED_IMAGE);
if (recommended)
name += " ["+tr("RECOMMENDED")+"]";

QListWidgetItem *witem = new QListWidgetItem(name+"\n"+description);
QListWidgetItem *witem = new QListWidgetItem(name+"\n"+description, ui->list);
witem->setCheckState(Qt::Unchecked);
witem->setData(Qt::UserRole, item);
witem->setData(Qt::UserRole, os);
witem->setData(SecondIconRole, internetIcon);

if (recommended)
ui->list->insertItem(0, witem);
else
ui->list->addItem(witem);
}
}
}
if (os.contains("description"))
{
QString name = os.value("os_name").toString();
QString description = os.value("description").toString();

if (!alreadyHasItem(name, os.value("release_date")))
{
os["name"] = name;
QString iconurl = os.value("icon").toString();
if (!iconurl.isEmpty())
iconurls.insert(iconurl);

QListWidgetItem *witem = new QListWidgetItem(name+"\n"+description, ui->list);
witem->setCheckState(Qt::Unchecked);
witem->setData(Qt::UserRole, os);
witem->setData(SecondIconRole, internetIcon);
}
}
}

/* Download icons */
Expand Down Expand Up @@ -1053,7 +1077,7 @@ void MainWindow::updateNeeded()
QVariantMap entry = item->data(Qt::UserRole).toMap();
_neededMB += entry.value("nominal_size").toInt();

if (entry.value("name").toString().contains("risc", Qt::CaseInsensitive))
if (nameMatchesRiscOS(entry.value("name").toString()))
{
/* RiscOS needs to start at a predetermined sector, calculate the extra space needed for that */
int startSector = getFileContents("/sys/class/block/mmcblk0p2/start").trimmed().toULongLong();
Expand Down
24 changes: 21 additions & 3 deletions recovery/multiimagewritethread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,26 @@ void MultiImageWriteThread::run()
}
}
}
if (folder.contains("risc", Qt::CaseInsensitive))
if (nameMatchesRiscOS(folder))
{
/* Check the riscos_offset in os.json matches what we're expecting.
In theory we shouldn't hit either of these errors because the invalid RISC_OS
should have been filtered out already (not added to OS-list) in mainwindow.cpp */
QVariantMap vos = Json::loadFromFile(folder+"/os.json").toMap();
if (vos.contains(RISCOS_OFFSET_KEY))
{
int riscos_offset = vos.value(RISCOS_OFFSET_KEY).toInt();
if (riscos_offset != RISCOS_OFFSET)
{
emit error(tr("RISCOS cannot be installed. RISCOS offset value mismatch."));
return;
}
}
else
{
emit error(tr("RISCOS cannot be installed. RISCOS offset value missing."));
return;
}
if (startSector > RISCOS_SECTOR_OFFSET-2048)
{
emit error(tr("RISCOS cannot be installed. Size of recovery partition too large."));
Expand Down Expand Up @@ -102,7 +120,7 @@ void MultiImageWriteThread::run()
{
for (QMultiMap<QString,QString>::const_iterator iter = _images.constBegin(); iter != _images.constEnd(); iter++)
{
if (iter.key().contains("risc", Qt::CaseInsensitive))
if (nameMatchesRiscOS(iter.key()))
{
if (!processImage(iter.key(), iter.value()))
return;
Expand Down Expand Up @@ -197,7 +215,7 @@ bool MultiImageWriteThread::processImage(const QString &folder, const QString &f
else
parttype = 0x83; /* Linux native */

if (folder.contains("risc", Qt::CaseInsensitive) && (fstype == "FAT" || fstype == "fat"))
if (nameMatchesRiscOS(folder) && (fstype == "FAT" || fstype == "fat"))
{
/* Let Risc OS start at known offset */
int startSector = getFileContents("/sys/class/block/mmcblk0p2/start").trimmed().toULongLong();
Expand Down
5 changes: 5 additions & 0 deletions recovery/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ void getOverscan(int &top, int &bottom, int &left, int &right)
::close(fd);
}
}

bool nameMatchesRiscOS(const QString &name)
{
return name.contains("risc", Qt::CaseInsensitive);
}
2 changes: 1 addition & 1 deletion recovery/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
QByteArray getFileContents(const QString &filename);
void putFileContents(const QString &filename, const QByteArray &data);
void getOverscan(int &top, int &bottom, int &left, int &right);

bool nameMatchesRiscOS(const QString &name);
#endif // UTIL_H
Binary file modified sdcontent/riscos-boot.bin
Binary file not shown.

0 comments on commit c779efa

Please sign in to comment.