SHIFT = 0xff,
};
-static const unsigned char keymap[][2] = {
+static unsigned char keymap[][2] = {
{0 }, /* 0 */
{27, 27 }, /* 1 - ESC */
{'1', '!'}, /* 2 */
{'o', 'O'},
{'p', 'P'},
{'[', '{'},
-// {']','}'}, /* 27 */
- {'+', '*'}, /* 27 */
+ {']', '}'}, /* 27 */
{'\r','\r'}, /* 28 - Enter */
{0, 0 }, /* 29 - Ctrl */
{'a', 'A'}, /* 30 */
{'m', 'M'},
{',', '<'},
{'.', '>'},
-// {'/', '?'}, /* 53 */
- {'-', '_'}, /* 53 */
+ {'/', '?'}, /* 53 */
{SHIFT, SHIFT}, /* 54 - Right Shift */
{0, 0}, /* 55 - Print Screen */
{0, 0}, /* 56 - Alt */
{0xae,0xae}, /* 83 - Numeric keypad '.' */
};
+IMPLEMENT
+void
+Keyb::set_keymap(Keyb::Keymap km)
+{
+ // This is a one-time switch over only.
+ if (km == Keymap_de)
+ {
+ // Simple patch to german layout
+ keymap[ 3][1] = '"';
+ keymap[ 7][1] = '&';
+ keymap[ 8][1] = '/';
+ keymap[ 9][1] = '(';
+ keymap[10][1] = ')';
+ keymap[11][1] = '=';
+ keymap[12][1] = '?';
+ keymap[13][1] = '`';
+ keymap[21][0] = 'z';
+ keymap[21][1] = 'Z';
+ keymap[27][0] = '+';
+ keymap[27][1] = '*';
+ keymap[41][0] = '^';
+ keymap[43][0] = '#';
+ keymap[43][1] = '\'';
+ keymap[44][0] = 'y';
+ keymap[44][1] = 'Y';
+ keymap[51][1] = ';';
+ keymap[52][1] = ':';
+ keymap[53][0] = '-';
+ keymap[53][1] = '_';
+ }
+}
IMPLEMENT
int Keyb::getchar(bool wait)
// implemented empty
int write(char const *str, size_t len);
+
+ enum Keymap { Keymap_en, Keymap_de };
+ void set_keymap(Keymap);
};
IMPLEMENT
int
-Keyb::write( char const *, size_t len)
+Keyb::write(char const *, size_t len)
{
return len;
}
{
return DIRECT | IN;
}
-
unsigned offs(Mword pin) const { return (pin >> 3) * 4; }
public:
- Gpio_eint_chip(Mword gpio_base)
- : Irq_chip_gen(8 * 16), _gpio_base(gpio_base)
+ Gpio_eint_chip(Mword gpio_base, unsigned num_irqs)
+ : Irq_chip_gen(num_irqs), _gpio_base(gpio_base)
{}
void mask(Mword pin)
class Gpio_cascade_xab_irq : public Irq_base
{
public:
- explicit Gpio_cascade_xab_irq(Gpio_eint_chip *g)
- : _eint_gc(g)
+ explicit Gpio_cascade_xab_irq(Gpio_eint_chip *g, unsigned special = 0)
+ : _eint_gc(g), _special(special)
{ set_hit(&handler_wrapper<Gpio_cascade_xab_irq>); }
void switch_mode(unsigned) {}
private:
Gpio_eint_chip *_eint_gc;
+ unsigned _special;
};
PUBLIC
{
Mword p = _eint_gc->pending();
Upstream_irq ui(this, u);
- _eint_gc->irq(p - 8)->hit(&ui);
+ if (1)
+ {
+ int grp = (p >> 3) & 0x1f;
+ int pin = p & 7;
+
+ if (_special == 1)
+ {
+ if (grp > 7)
+ grp += 5;
+ }
+ else if (_special == 2)
+ grp += 2;
+
+ _eint_gc->irq((grp - 1) * 8 + pin)->hit(&ui);
+ }
+ else
+ _eint_gc->irq(p - 8)->hit(&ui);
}
// ------------
_cc = new Boot_object<Combiner_chip>();
_wu_gc = new Boot_object<Gpio_wakeup_chip>(Kmem::Gpio2_phys_base);
- _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base));
- _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base));
+ _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base), 18 * 8);
+ _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base), 14 * 8);
// Combiners
for (unsigned i = 0; i < 16; ++i)
g->unmask(64);
// xa GIC:32+47
- g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc1), 79);
+ g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc1, Platform::is_4412() ? 1 : 0), 79);
g->unmask(79);
// xb GIC:32+46
- g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc2), 78);
+ g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc2, Platform::is_4412() ? 2 : 0), 78);
g->unmask(78);
{ 160, _gic.cpu(Cpu_number(0)) },
{ 20 * 8, _cc },
{ 4 * 8, _wu_gc },
- { 13 * 8, _ei_gc1 },
- { 12 * 8, _ei_gc2 },
+ { 18 * 8, _ei_gc1 },
+ { 14 * 8, _ei_gc2 },
//{ 1 * 8, _ei_gc3 }, // Do not know upstream IRQ-num :(
//{ 5 * 8, _ei_gc4 }, // Do not know upstream IRQ-num :(
};
_wu_gc = new Boot_object<Gpio_wakeup_chip>(Kmem::Gpio1_phys_base);
- _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base));
- _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base));
- _ei_gc3 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio3_phys_base));
- _ei_gc4 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio4_phys_base));
+ _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base), 13 * 8);
+ _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base), 8 * 8);
+ _ei_gc3 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio3_phys_base), 5 * 8);
+ _ei_gc4 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio4_phys_base), 1 * 8);
// Combiners
for (unsigned i = 0; i < 32; ++i)
// - part4: ext-int 0x700: 50
static Chip_block socblock[] = {
- { 160, Pic::gic },
- { 32 * 8, _cc },
- { 32, _wu_gc },
- { 13 * 8, _ei_gc1 },
- { 8 * 8, _ei_gc2 },
- { 5 * 8, _ei_gc3 },
- { 1 * 8, _ei_gc4 },
+ { 160, Pic::gic },
+ { 32 * 8, _cc },
+ { 32, _wu_gc },
+ { _ei_gc1->nr_irqs(), _ei_gc1 },
+ { _ei_gc2->nr_irqs(), _ei_gc2 },
+ { _ei_gc3->nr_irqs(), _ei_gc3 },
+ { _ei_gc4->nr_irqs(), _ei_gc4 },
};
_block = socblock;
IMPLEMENT
void
-Exynos_smc::cpuboot(Mword phys_start, unsigned cpu)
+Exynos_smc::cpuboot(Mword, unsigned cpu)
{
call(Cpu1boot, cpu);
}
class Boot_alloced
{
private:
+ enum { Debug_boot_alloc };
struct Block : cxx::S_list_item
{ size_t size; };
void *
Boot_alloced::alloc(size_t size)
{
- printf("Boot_alloc: size=0x%lx\n", (unsigned long)size);
+ if (Debug_boot_alloc)
+ printf("Boot_alloc: size=0x%lx\n", (unsigned long)size);
// this is best fit list-based allocation
alloc_size <<= 1;
Block *b = (Block*)Kmem_alloc::allocator()->unaligned_alloc(alloc_size);
- printf("Boot_alloc: allocated extra memory block @%p (size=%lx)\n",
- b, alloc_size);
+ if (Debug_boot_alloc)
+ printf("Boot_alloc: allocated extra memory block @%p (size=%lx)\n",
+ b, alloc_size);
if (!b)
return 0;
void *b = *best;
Block *rem = (Block *)(((Address)b + size + sizeof(Block) - 1) & ~(sizeof(Block) - 1));
long rem_sz = (Address)b + (*best)->size - (Address)rem;
- printf("Boot_alloc: @ %p\n", b);
+ if (Debug_boot_alloc)
+ printf("Boot_alloc: @ %p\n", b);
if (rem_sz > (long)sizeof(Block))
{
rem->size = rem_sz;
_free.replace(best, rem);
- printf("Boot_alloc: remaining free block @ %p (size=%lx)\n", rem, rem_sz);
+ if (Debug_boot_alloc)
+ printf("Boot_alloc: remaining free block @ %p (size=%lx)\n", rem, rem_sz);
}
else
_free.erase(best);
void Boot_console::init()
{
keyb.construct();
+ if (Koptions::o()->opt(Koptions::F_keymap_de))
+ keyb->set_keymap(Keyb::Keymap_de);
Kconsole::console()->register_console(keyb);
if (Koptions::o()->opt(Koptions::F_noscreen))
F_apic = 1 << 8,
F_loadcnt = 1 << 9,
F_watchdog = 1 << 10,
+ F_keymap_de = 1 << 11,
F_irq0 = 1 << 13,
F_nosfn = 1 << 15,
F_jdb_never_stop = 1 << 16,
</li>
<li>Return the local thread capability of a pthread thread:
- Use \c pthread_getl4cap(pthread_t *t) to get the capability index of
+ Use \c pthread_getl4cap(pthread_t t) to get the capability index of
the pthread t.
For example:
--- /dev/null
+PLATFORM_NAME = "Samsung Exynos4"
+PLATFORM_ARCH = arm
+PLATFORM_RAM_BASE = 0x40000000
+PLATFORM_RAM_SIZE_MB = 1024
--- /dev/null
+PLATFORM_NAME = "Samsung Exynos5"
+PLATFORM_ARCH = arm
+PLATFORM_RAM_BASE = 0x40000000
+PLATFORM_RAM_SIZE_MB = 2047
CPPFLAGS += -DSINGLE_SECTION
endif
+ifeq ($(ARCH),ppc32)
+LOADER_MBI := 1
+endif
+
+ifeq ($(ARCH),sparc)
+LOADER_MBI := 1
+endif
+
# convenience
ifneq ($(E),)
CPPFLAGS += -DREALMODE_LOADING -DSINGLE_SECTION
# don't install bootstrap_$(ENTRY_FN).elf
INSTALL_FILES = bootstrap.load
+MOD_ADDR = 0x00150000
endif
ifneq ($(LOADER_MBI),0)
SRC_CC += loader_mbi.cc
-MOD_ADDR = 0x00150000
CPPFLAGS += -DLOADER_MBI
endif
SUPPORT_CC_arm-kirkwood := platform/kirkwood.cc
SUPPORT_CC_arm-rpi_a := platform/rpi.cc
SUPPORT_CC_arm-rpi_b := platform/rpi.cc
+SUPPORT_CC_arm-exynos4 := platform/exynos.cc
+SUPPORT_CC_arm-exynos5 := platform/exynos.cc
# PPC
SUPPORT_CC_ppc32-mpc5200 := platform/mpc5200.cc
unlink("$modname.extra.s", "$modname.obj", "$modname.ugz");
}
-sub build_mbi_modules_obj(@)
+sub build_mbi_modules_obj($@)
{
+ my $cmdline = shift;
my @mods = @_;
my $asm_string;
".ascii \"$mods[$i]->{cmdline}\"; .byte 0; \n";
}
+ $asm_string .= ".global _mbi_cmdline \n".
+ "_mbi_cmdline: \n".
+ ".ascii \"$cmdline\"; .byte 0; \n";
+
write_to_file("mbi_modules.s", $asm_string);
system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.s");
unlink("mbi_modules.s");
$mods[$i]->{modname} = sprintf "mod%02d", $i;
}
- build_mbi_modules_obj(@mods);
+ build_mbi_modules_obj($entry{bootstrap}{cmdline}, @mods);
for (my $i = 0; $i < @mods; $i++) {
build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname},
sub dump_entry(@)
{
my %entry = @_;
- print join(' ', map { $_->{cmdline} } @{$entry{mods}}), "\n";
+ print "modaddr=$entry{modaddr}\n";
+ print "$entry{bootstrap}{command}\n";
+ print "$entry{bootstrap}{cmdline}\n";
+ print join("\n", map { $_->{cmdline} } @{$entry{mods}}), "\n";
+ print join(' ', map { $_ } @{$entry{files}}), "\n";
}
# ------------------------------------------------------------------------
do
c = uart()->get_char(0);
- while (c == -1)
- ;
+ while (c == -1);
return c;
}
/*
- * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ * (c) 2008-2013 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
#include "loader_mbi.h"
-l4util_mb_info_t loader_mbi;
+static l4util_mb_info_t my_loader_mbi;
-l4util_mb_info_t *init_loader_mbi(void *realmode_pointer)
+l4util_mb_info_t *loader_mbi()
{
- loader_mbi.flags = L4UTIL_MB_MEMORY;
- loader_mbi.mem_lower = 0x9f * 4;
+ return &my_loader_mbi;
+}
+
+void loader_mbi_add_cmdline(const char *cmdline)
+{
+ my_loader_mbi.cmdline = (l4_uint32_t)(unsigned long)cmdline;
+ my_loader_mbi.flags |= L4UTIL_MB_CMDLINE;
+}
+
+l4util_mb_info_t *init_loader_mbi_x86_realmode(void *realmode_pointer)
+{
+ my_loader_mbi.flags |= L4UTIL_MB_MEMORY;
+ my_loader_mbi.mem_lower = 0x9f * 4;
unsigned long *cmd_line_ptr;
- loader_mbi.mem_upper = *(unsigned long *)((char *)realmode_pointer + 0x1e0);
- printf("Detected memory size: %dKB\n", loader_mbi.mem_upper);
+ my_loader_mbi.mem_upper = *(unsigned long *)((char *)realmode_pointer + 0x1e0);
+ printf("Detected memory size: %dKB\n", my_loader_mbi.mem_upper);
cmd_line_ptr = (unsigned long *)((char *)realmode_pointer + 0x228);
if (cmd_line_ptr && *cmd_line_ptr)
{
- loader_mbi.flags |= L4UTIL_MB_CMDLINE;
- loader_mbi.cmdline = *cmd_line_ptr;
+ my_loader_mbi.flags |= L4UTIL_MB_CMDLINE;
+ my_loader_mbi.cmdline = *cmd_line_ptr;
}
-
- return &loader_mbi;
+
+ return &my_loader_mbi;
}
/*
- * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ * (c) 2008-2013 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
#include <l4/util/mb_info.h>
-l4util_mb_info_t *init_loader_mbi(void *);
+l4util_mb_info_t *loader_mbi();
+l4util_mb_info_t *init_loader_mbi_x86_realmode(void *);
+void loader_mbi_add_cmdline(const char *cmdline);
#endif /* ! __BOOTSTRAP__LOADER_MBI_H__ */
* \file
* \brief Support for Exynos platforms
*
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
*
*/
/*
- * (c) 2011-2013 Author(s)
+ * (c) 2013 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
void init()
{
static L4::Uart_s5pv210 _uart;
+ const unsigned long uart_offset = 0x10000;
+ unsigned long uart_base;
unsigned uart_nr = 2;
- unsigned long uart_base = 0x12c00000;
- unsigned long uart_offset = 0x10000;
+
+#ifdef PLATFORM_TYPE_exynos4
+ uart_base = 0x13800000;
+#else
+ uart_base = 0x12c00000;
+#endif
static L4::Io_register_block_mmio r(uart_base + uart_nr * uart_offset);
_uart.startup(&r);
set_stdio_uart(&_uart);
}
+
+ void reboot()
+ {
+#ifdef PLATFORM_TYPE_exynos4
+ *(unsigned *)0x10020400 = 1;
+#else
+ *(unsigned *)0x10040400 = 1;
+#endif
+ }
+
};
}
*_end = region;
++_end;
+ _combined_size += region.size();
}
void
return;
}
- if (mem.begin() >= _upper_limit)
+ if (_combined_size >= _max_combined_size)
{
- printf(" Dropping %s region ", _name);
+ printf(" Dropping '%s' region ", _name);
mem.print();
- printf(" due to %lld MB limit\n", _upper_limit >> 20);
+ printf(" due to %lld MB limit\n", _max_combined_size >> 20);
return;
}
- if (mem.end() >= _upper_limit - 1)
+ if (_combined_size + mem.size() > _max_combined_size)
{
- printf(" Limiting %s region ", _name);
+ printf(" Limiting '%s' region ", _name);
mem.print();
- mem.end(_upper_limit - 1);
+ mem.end(mem.begin() + _max_combined_size - _combined_size - 1);
printf(" to ");
mem.print();
- printf(" due to %lld MB limit\n", _upper_limit >> 20);
+ printf(" due to %lld MB limit\n", _max_combined_size >> 20);
}
add_nolimitcheck(mem, may_overlap);
void
Region::print() const
{
- printf(" [%9llx, %9llx] {%9llx}", begin(), end(), end() - begin() + 1);
+ printf(" [%9llx, %9llx] {%9llx}", begin(), end(), size());
}
void
void end(unsigned long long e) { _end = e; }
/** Get the name of the region. */
char const *name() const { return _name; }
+ /** Get size of the region */
+ unsigned long long size() const { return _end - _begin + 1; }
/** Set the name of the region. */
void name(char const *name) { _name = name; }
/** Get the type of the region. */
*/
void init(Region *store, unsigned size,
const char *name,
- unsigned long long upper_limit = ~0ULL)
+ unsigned long long max_combined_size = ~0ULL)
{
_reg = _end = store;
_max = _reg + size;
_name = name;
- _upper_limit = upper_limit;
+ _max_combined_size = max_combined_size;
+ _combined_size = 0;
}
/** Search for a region that overlaps o. */
unsigned long long find_free(Region const &search,
unsigned long long size, unsigned align);
- /**
- * Add a new memory region to the list. The new region must not overlap
- * any known region.
- */
- void add_nolimitcheck(Region const &r, bool may_overlap = false);
-
/**
* Add a new region, with a upper limit check and verboseness.
*/
Region *_reg;
const char *_name;
- unsigned long long _upper_limit;
+ unsigned long long _max_combined_size;
+ unsigned long long _combined_size;
private:
void swap(Region *a, Region *b);
unsigned long long next_free(unsigned long long start);
bool test_fit(unsigned long long start, unsigned long long _size);
+ /**
+ * Add a new memory region to the list. The new region must not overlap
+ * any known region.
+ */
+ void add_nolimitcheck(Region const &r, bool may_overlap = false);
};
#endif
for (Region *i = ram.begin(); i < ram.end(); ++i)
{
printf(" RAM: %016llx - %016llx: %lldkB\n",
- i->begin(), i->end(), (i->end() - i->begin() + 1) >> 10);
- sum += i->end() - i->begin() + 1;
+ i->begin(), i->end(), i->size() >> 10);
+ sum += i->size();
}
if (show_total)
printf(" Total RAM: %lldMB\n", sum >> 20);
extern l4util_mb_mod_t _modules_mbi_start[];
extern l4util_mb_mod_t _modules_mbi_end[];
+extern char _mbi_cmdline[];
/**
* Create the basic multi-boot structure in IMAGE_MODE
;
}
+#ifdef IMAGE_MODE
+ {
+ loader_mbi_add_cmdline(_mbi_cmdline);
+ mbi = loader_mbi();
+ }
+#endif
+
+ if (check_arg(mbi, "-wait"))
+ {
+ puts("\nL4 Bootstrapper is waiting for key input to continue...");
+ if (getchar() == -1)
+ puts(" ...no key input available.");
+ else
+ puts(" ...going on.");
+ }
+
puts("\nL4 Bootstrapper");
puts(" Build: #" BUILD_NR " " BUILD_DATE
#ifdef ARCH_x86
#ifdef REALMODE_LOADING
/* create synthetic multi boot info */
- mbi = init_loader_mbi(realmode_si);
+ mbi = init_loader_mbi_x86_realmode(realmode_si);
(void)flag;
#else
(void)realmode_si;
#endif
#elif defined(ARCH_arm)
- l4util_mb_info_t my_mbi;
- memset(&my_mbi, 0, sizeof(my_mbi));
- mbi = &my_mbi;
+ mbi = loader_mbi();
(void)realmode_si;
(void)flag;
#elif defined(ARCH_ppc32)
+ mbi = loader_mbi();
+
(void)realmode_si;
(void)flag;
- l4util_mb_info_t my_mbi;
L4_drivers::Of_if of_if;
printf(" Detecting ram size ...\n");
unsigned long ram_size = of_if.detect_ramsize();
printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024));
- /* setup mbi and detect OF devices */
- memset(&my_mbi, 0, sizeof(my_mbi));
- mbi = &my_mbi;
+ /* detect OF devices */
unsigned long drives_addr, drives_length;
if (of_if.detect_devices(&drives_addr, &drives_length))
ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
#elif defined(ARCH_sparc)
- l4util_mb_info_t my_mbi;
- memset(&my_mbi, 0, sizeof(my_mbi));
- mbi = &my_mbi;
+ mbi = loader_mbi();
(void)realmode_si;
(void)flag;
roottask = 0;
if (const char *s = check_arg(mbi, "-modaddr"))
- _mod_addr = strtoul(s + 9, 0, 0);
+ _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
_mod_addr = l4_round_page(_mod_addr);
unsigned long ram_size_mb = scan_ram_size(RAM_BASE, RAM_SIZE_MB);
printf(" Memory size is %ldMB%s (%08lx - %08lx)\n",
ram_size_mb, ram_size_mb != RAM_SIZE_MB ? " (Limited by Scan)" : "",
- (unsigned long)RAM_BASE, RAM_BASE + (ram_size_mb << 20));
+ (unsigned long)RAM_BASE, RAM_BASE + (ram_size_mb << 20) - 1);
ram->add(Region::n(RAM_BASE,
(unsigned long long)RAM_BASE + (ram_size_mb << 20),
".ram", Region::Ram));
void
l4_vm_vmx_copy_state(void const *vmcs, void *_dst, void const *_src) L4_NOTHROW
{
- l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs;
- offsets += 0x20;
+ l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs + 0x20;
unsigned offs = offsets[28] * 64;
unsigned size = offsets[29] * 64;