/*
nspirelinuxloader - A in-place Linux bootloader for TI-Nspire calculator
Copyright (C) 2011 Daniel Tang
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, either version 3 of the License, or
(at your option) any later version.
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, see .
*/
#include
#include "const.h"
#include "loader.h"
#include "payload.h" /*Dynamically generated*/
static void panic() {
while (1);
}
void* loadParameters() {
struct atag * params;
if (!(params = malloc(MAX_PARAM_SIZE)))
{
show_msgbox("LinuxNspire","Cannot allocate memory for params");
panic();
}
//memset(params, 0, MAX_PARAM_SIZE);
/* Header ATAG */
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size(atag_core);
params->u.core.flags = 1;
params->u.core.pagesize = SYSTEM_PAGESIZE;
params->u.core.rootdev = 0;
params = tag_next(params);
/* Ramdisk ATAG */
/*params->hdr.tag = ATAG_RAMDISK;
params->hdr.size = tag_size(atag_ramdisk);
params = tag_next(params);*/
/* Memory ATAG */
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size(atag_mem);
params->u.mem.start = PHYSICAL_MEMORY_ADDR;
params->u.mem.size = PHYSICAL_MEMORY_SIZE;
params = tag_next(params);
/* Finishing tag */
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
return params;
}
void* loadKernel() {
void* kernel;
FILE* f;
if (!(kernel = malloc(MAX_KERNEL_SIZE)))
{
show_msgbox("LinuxNspire","Cannot allocate memory for kernel");
panic();
}
//memset(kernel, 0, MAX_KERNEL_SIZE);
f = fopen("/documents/linux/zImage.tns","rb");
if (!f) {
show_msgbox("LinuxNspire","Cannot find the kernel");
panic();
}
fread(kernel, 0x1, MAX_KERNEL_SIZE, f);
fclose(f);
return kernel;
}
int main() {
void *kerneladdr, *paramsaddr;
kerneladdr = loadKernel();
paramsaddr = loadParameters();
/* Dirty check to see if we'll overwrite anything */
if (kerneladdr < KERNEL_LOAD_ADDR+MAX_KERNEL_SIZE)
show_msgbox("LinuxNspire","Possible overwriting for kernel");
if (paramsaddr < KERNEL_LOAD_ADDR+MAX_KERNEL_SIZE)
show_msgbox("LinuxNspire","Possible overwriting for params");
/* Load the payload that will copy our stuff to their right locations */
struct memcpy_addrs kernel_addrs = {
.src = (uint32_t)kerneladdr, /* yay for casting pointers to ints */
.dest = (uint32_t)KERNEL_LOAD_ADDR,
.size = MAX_KERNEL_SIZE
};
struct memcpy_addrs param_addrs = {
.src = (uint32_t)paramsaddr,
.dest = (uint32_t)PARAM_LOAD_ADDR,
.size = MAX_PARAM_SIZE
};
/* Load our relocation code to a safe area where it won't be overwritten*/
memcpy((void*)SAFE_ADDR, payload, sizeof(payload));
/* Pass control to the payload which will relocate everything and jump to the kernel
entry point*/
((void (*)(struct memcpy_addrs*, struct memcpy_addrs*))SAFE_ADDR)(&kernel_addrs,¶m_addrs);
/* This is just to make the compiler happy. We should never ever return here */
return 0;
}