Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tangrs committed Oct 16, 2012
0 parents commit 53eface
Show file tree
Hide file tree
Showing 19 changed files with 1,013 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.o
*.elf
*.tns
26 changes: 26 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
GCC = nspire-gcc
LD = nspire-ld
GCCFLAGS = -Os -nostdlib -Wall -W -marm -Werror
LDFLAGS = -lnspireio
OBJCOPY := "$(shell which arm-elf-objcopy 2>/dev/null)"
ifeq (${OBJCOPY},"")
OBJCOPY := arm-none-eabi-objcopy
endif
EXE = linuxloader.tns
OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
DISTDIR = .
vpath %.tns $(DISTDIR)

all: $(EXE)

%.o: %.c
$(GCC) $(GCCFLAGS) -c $<

$(EXE): $(OBJS)
$(LD) $^ -o $(@:.tns=.elf) $(LDFLAGS)
mkdir -p $(DISTDIR)
$(OBJCOPY) -O binary $(@:.tns=.elf) $(DISTDIR)/$@

clean:
rm -f *.o *.elf
rm -f $(DISTDIR)/$(EXE)
147 changes: 147 additions & 0 deletions atag.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
TI-NSPIRE Linux In-Place Bootloader
Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
*/

#include <os.h>
#include <stdint.h>

#include "atag_tags.h"
#include "atag.h"
#include "common.h"
#include "macros.h"

static void* atag_add(void *head, int tagid, ...) {
va_list ap;
va_start(ap, tagid);
char *cmdline = NULL;

((struct atag*)head)->hdr.tag = tagid;

#define SET_NEXT_VARARG(type, element) ((struct atag*)head)->u.type.element = va_arg(ap, uint32_t)
#define SET_SIZE(x) ((struct atag*)head)->hdr.size = 2 + (sizeof(((struct atag*)head)->u.x) / sizeof(uint32_t))
switch (tagid) {
case ATAG_MEM:
SET_SIZE(mem);
SET_NEXT_VARARG(mem, size);
SET_NEXT_VARARG(mem, start);
break;
case ATAG_VIDEOTEXT:
SET_SIZE(videotext);
SET_NEXT_VARARG(videotext, x);
SET_NEXT_VARARG(videotext, y);
SET_NEXT_VARARG(videotext, video_page);
SET_NEXT_VARARG(videotext, video_mode);
SET_NEXT_VARARG(videotext, video_cols);
SET_NEXT_VARARG(videotext, video_ega_bx);
SET_NEXT_VARARG(videotext, video_isvga);
SET_NEXT_VARARG(videotext, video_points);
break;
case ATAG_RAMDISK:
SET_SIZE(ramdisk);
SET_NEXT_VARARG(ramdisk, flags);
SET_NEXT_VARARG(ramdisk, size);
SET_NEXT_VARARG(ramdisk, start);
break;
case ATAG_INITRD2:
SET_SIZE(initrd2);
SET_NEXT_VARARG(initrd2, start);
SET_NEXT_VARARG(initrd2, size);
break;
case ATAG_SERIAL:
SET_SIZE(serialnr);
SET_NEXT_VARARG(serialnr, low);
SET_NEXT_VARARG(serialnr, high);
break;
case ATAG_REVISION:
SET_SIZE(revision);
SET_NEXT_VARARG(revision, rev);
break;
case ATAG_VIDEOLFB:
SET_SIZE(videolfb);
SET_NEXT_VARARG(videolfb, lfb_width);
SET_NEXT_VARARG(videolfb, lfb_height);
SET_NEXT_VARARG(videolfb, lfb_depth);
SET_NEXT_VARARG(videolfb, lfb_linelength);
SET_NEXT_VARARG(videolfb, lfb_base);
SET_NEXT_VARARG(videolfb, lfb_size);
SET_NEXT_VARARG(videolfb, red_size);
SET_NEXT_VARARG(videolfb, red_pos);
SET_NEXT_VARARG(videolfb, green_size);
SET_NEXT_VARARG(videolfb, green_pos);
SET_NEXT_VARARG(videolfb, blue_size);
SET_NEXT_VARARG(videolfb, blue_pos);
SET_NEXT_VARARG(videolfb, rsvd_size);
SET_NEXT_VARARG(videolfb, rsvd_pos);
break;
case ATAG_CORE:
case ATAG_NONE:
((struct atag*)head)->hdr.size = 2;
break;
case ATAG_CMDLINE:
cmdline = va_arg(ap, char*);
((struct atag*)head)->hdr.size = 2 + ((strlen(cmdline) + sizeof(uint32_t)) / sizeof(uint32_t));
break;
default:
printl("Invalid ATAG id %d", tagid);
return head;
}
size_t tag_size = (((struct atag*)head)->hdr.size * sizeof(uint32_t));

if (tagid == ATAG_NONE) ((struct atag*)head)->hdr.size = 0;
if (cmdline) {
strcpy(((struct atag*)head)->u.cmdline.cmdline, cmdline);
}
va_end(ap);
return (char*)head + tag_size;
}

static void* atag_begin(void *head) {
return atag_add(head, ATAG_CORE);
}

#define ATAG(...) do { \
if (current > (char*)settings.atag.start + settings.atag.size) { \
printl("Internal error. ATAG buffer overrun\n"); \
return -1; \
} \
current = atag_add(current, __VA_ARGS__); \
} while (0)

int atag_build() {
char *current;
if (!settings.atag.start) {
printl("Internal error. settings.atag.start = NULL\n");
return -1;
}
current = atag_begin(settings.atag.start);
/*
Begin building list of ATAGs
*/
if (settings.phys.size)
ATAG(ATAG_MEM, settings.phys.size, settings.phys.start);
if (strlen(settings.kernel_cmdline))
ATAG(ATAG_CMDLINE, settings.kernel_cmdline);
if (settings.ramdisk_loaded)
ATAG(ATAG_INITRD2, settings.ramdisk.addr, settings.ramdisk.size);
/*
End list. Stop here
*/
ATAG(ATAG_NONE);
return 0;
}

#undef ATAG
36 changes: 36 additions & 0 deletions atag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
TI-NSPIRE Linux In-Place Bootloader
Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
*/

#ifndef ATAG_H
#define ATAG_H

/* list of possible tags */
#define ATAG_NONE 0x00000000
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009

int atag_build();

#endif
92 changes: 92 additions & 0 deletions atag_tags.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
Taken from http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
This file is BSD Licensed.
*/
#ifndef ATAG_TAGS_H
#define ATAG_TAGS_H
/* structures for each atag */
struct atag_header {
uint32_t size; /* length of tag in words including this header */
uint32_t tag; /* tag type */
};

struct atag_core {
uint32_t flags;
uint32_t pagesize;
uint32_t rootdev;
};

struct atag_mem {
uint32_t size;
uint32_t start;
};

struct atag_videotext {
uint8_t x;
uint8_t y;
uint16_t video_page;
uint8_t video_mode;
uint8_t video_cols;
uint16_t video_ega_bx;
uint8_t video_lines;
uint8_t video_isvga;
uint16_t video_points;
};

struct atag_ramdisk {
uint32_t flags;
uint32_t size;
uint32_t start;
};

struct atag_initrd2 {
uint32_t start;
uint32_t size;
};

struct atag_serialnr {
uint32_t low;
uint32_t high;
};

struct atag_revision {
uint32_t rev;
};

struct atag_videolfb {
uint16_t lfb_width;
uint16_t lfb_height;
uint16_t lfb_depth;
uint16_t lfb_linelength;
uint32_t lfb_base;
uint32_t lfb_size;
uint8_t red_size;
uint8_t red_pos;
uint8_t green_size;
uint8_t green_pos;
uint8_t blue_size;
uint8_t blue_pos;
uint8_t rsvd_size;
uint8_t rsvd_pos;
};

struct atag_cmdline {
char cmdline[1];
};

struct atag {
struct atag_header hdr;
union {
struct atag_core core;
struct atag_mem mem;
struct atag_videotext videotext;
struct atag_ramdisk ramdisk;
struct atag_initrd2 initrd2;
struct atag_serialnr serialnr;
struct atag_revision revision;
struct atag_videolfb videolfb;
struct atag_cmdline cmdline;
} u;
};

#endif
74 changes: 74 additions & 0 deletions cmd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
TI-NSPIRE Linux In-Place Bootloader
Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
*/

#include <os.h>

#include "kernel.h"
#include "common.h"
#include "load.h"
#include "macros.h"

/*
Returns number of filled arguments.
Var args are all of type char**
*/
int cmd_args(char* args, unsigned max_n, ...) {
va_list ap;
va_start(ap, max_n);

char *ptr = args;
unsigned i;
for (i=0; i<max_n && *args; i++) {
if (*args == ' ') {
*args = '\0';
char **fill = va_arg(ap,char**);
*fill = ptr;
ptr = args + 1;
}
args++;
}

va_end(ap);
return i;
}

/*
Returns 1 if program should gracefully exit
Returns 0 if further commands can be executed
*/
#define DEFINE_COMMAND(s, f) else if (!strncmp(#s, cmd, sizeof(#s)-1)) f(cmd+sizeof(#s))
int process_cmd(char * cmd) {
if (*cmd == '\0') return 0;
else if (!strcmp("exit", cmd)) return 1;
/*
Define custom commands below
DEFINE_COMMAND( function_name, function_to_call );
function_to_call should accept one parameter which is
pointer to arguments
*/
DEFINE_COMMAND(kernel, load_kernel);
DEFINE_COMMAND(initrd, load_ramdisk);
DEFINE_COMMAND(dump, dump_settings);
DEFINE_COMMAND(boot, kernel_boot);
/*
End command list. Do not add any more after here
*/
else { printl("Unknown command\n"); }
return 0;
}
#undef DEFINE_COMMAND
Loading

0 comments on commit 53eface

Please sign in to comment.