/* 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; }