/branches/arm/boot/arch/arm32/loader/mm.h |
---|
26,6 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32boot |
* @{ |
*/ |
33,20 → 34,25 |
*/ |
#ifndef __MM_H__ |
#define __MM_H__ |
#ifndef BOOT_arm32__MM_H |
#define BOOT_arm32__MM_H |
#ifndef __ASM__ |
#include "types.h" |
#endif |
/** Frame width. */ |
#define FRAME_WIDTH 12 /* 4KB frames */ |
/** Frame size. */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define PAGE_WIDTH FRAME_WIDTH |
/** Page size in 2-level paging which is switched on later in the kernel initialization. */ |
#define PAGE_SIZE FRAME_SIZE |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
55,27 → 61,31 |
# define PA2KA(x) ((x) + 0x80000000) |
#endif |
/** Number of entries in PTL0 */ |
#define PTL0_ENTRIES_ARCH (1<<12) /* 4096 */ |
/** Frames per 1MB section */ |
/** Number of entries in PTL0. */ |
#define PTL0_ENTRIES (1<<12) /* 4096 */ |
/** Size of an entry in PTL0. */ |
#define PTL0_ENTRY_SIZE 4 |
/** Number of frames per 1MB section. */ |
#define FRAMES_PER_SECTION ( ( 1 << 20 ) / FRAME_SIZE ) |
/** Converts adress to frame number */ |
/** Returns number of frame the address belongs to. */ |
#define ADDR2PFN( addr ) ( ((uintptr_t)(addr))>>FRAME_WIDTH ) |
/** Descriptor type that signs "section" page table entry |
* (one-level paging with 1MB sized pages) */ |
#define PTE_DESCRIPTOR_SECTION 2 |
/** Describes "section" page table entry (one-level paging with 1MB sized pages). */ |
#define PTE_DESCRIPTOR_SECTION 0x2 |
/** Access rights to page table: user-no access, kernel-read/write */ |
#define PTE_AP_USER_NO_KERNEL_RW 1 |
/** Page table access rights: user - no access, kernel - read/write. */ |
#define PTE_AP_USER_NO_KERNEL_RW 0x1 |
#ifndef __ASM__ |
/** Page table level 0 entry - "section" format (one-level paging, 1MB sized |
* pages). Used only for booting the kernel. */ |
/** Page table level 0 entry - "section" format is used (one-level paging, 1MB sized |
* pages). Used only while booting the kernel. */ |
typedef struct { |
unsigned descriptor_type : 2; |
unsigned bufferable : 1; |
89,14 → 99,12 |
} __attribute__ ((packed)) pte_level0_section_t; |
/** Page table that holds 1:1 mapping for booting the kernel. */ |
extern pte_level0_section_t page_table[PTL0_ENTRIES_ARCH]; |
/** Page table that holds 1:1 virtual to physical mapping used while booting the kernel. */ |
extern pte_level0_section_t page_table[PTL0_ENTRIES]; |
extern void mmu_start(void); |
/** Starts the MMU - initializes page table and enables paging. */ |
void mmu_start(void); |
/** Enables paging. */ |
static inline void enable_paging() |
{ |
107,17 → 115,14 |
// behave as a client of domains |
"ldr r0, =0x55555555 \n" |
"mcr p15, 0, r0, c3, c0, 0 \n" |
// current settings |
"mrc p15, 0, r0, c1, c0, 0 \n" |
/* TODO: talk to Alf why needed |
// mask to disable aligment checks; system & rom bit set to 0 (has no |
// special effect) |
"ldr r1, =0xfffffe8f \n" |
"and r0, r0, r1 \n" |
*/ |
// mask to enable paging |
"ldr r1, =0x00000001 \n" |
"orr r0, r0, r1 \n" |
// store settings |
"mcr p15, 0, r0, c1, c0, 0 \n" |
: |
127,17 → 132,20 |
} |
/** Sets the address of level 0 page table. |
* \param pt pointer to the page table to set |
/** Sets the address of level 0 page table to CP15 register 2. |
* |
* @param pt Address of a page table to set. |
*/ |
static inline void set_ptl0_address(pte_level0_section_t* pt) |
{ |
asm volatile ( "mcr p15, 0, %0, c2, c0, 0 \n" |
asm volatile ( |
"mcr p15, 0, %0, c2, c0, 0 \n" |
: |
: "r"(pt) |
); |
} |
#endif |
#endif |
/branches/arm/boot/arch/arm32/loader/asm.S |
---|
36,50 → 36,50 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, lr} |
beq case_4 |
case_1: |
beq 4f |
1: |
cmp r2, #0 |
movne ip, #0 |
beq case_3 |
case_2: |
beq 3f |
2: |
ldrb r3, [ip, r1] |
strb r3, [ip, r0] |
add ip, ip, #1 |
cmp ip, r2 |
bne case_2 |
case_3: |
bne 2b |
3: |
mov r0, r1 |
ldmia sp!, {r4, pc} |
case_4: |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
cmp r0, r3 |
bne case_1 |
bne 1b |
movs r4, r2, lsr #2 |
moveq lr, r4 |
beq case_6 |
beq 6f |
mov lr, #0 |
mov ip, lr |
case_5: |
5: |
ldr r3, [ip, r1] |
add lr, lr, #1 |
cmp lr, r4 |
str r3, [ip, r0] |
add ip, ip, #4 |
bne case_5 |
case_6: |
bne 5b |
6: |
ands r4, r2, #3 |
beq case_3 |
beq 3b |
mov r3, lr, lsl #2 |
add r0, r3, r0 |
add ip, r3, r1 |
mov r2, #0 |
case_7: |
7: |
ldrb r3, [r2, ip] |
strb r3, [r2, r0] |
add r2, r2, #1 |
cmp r2, r4 |
bne case_7 |
b case_3 |
bne 7b |
b 3b |
/branches/arm/boot/arch/arm32/loader/boot.S |
---|
42,9 → 42,11 |
bx r0 |
# align for start of page |
# place page_table to PT section |
.section PT |
# make place for first level page table |
# make place for PTL0 page table |
page_table: |
.skip PTL0_ENTRIES_ARCH * 4 |
.skip PTL0_ENTRIES * PTL0_ENTRY_SIZE |
/branches/arm/boot/arch/arm32/loader/main.c |
---|
26,6 → 26,14 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32boot |
* @{ |
*/ |
/** @file |
*/ |
#include "main.h" |
#include "asm.h" |
#include "_components.h" |
33,8 → 41,10 |
#include "mm.h" |
#define KERNEL_VIRTUAL_ADDRESS 0x80150000 |
/** Kernel entry point address. */ |
#define KERNEL_VIRTUAL_ADDRESS 0x80200000 |
char *release = RELEASE; |
#ifdef REVISION |
49,7 → 59,8 |
char *timestamp = ""; |
#endif |
/** Print version information. */ |
/** Prints bootloader version information. */ |
static void version_print(void) |
{ |
printf("HelenOS ARM32 Bootloader\nRelease %s%s%s\nCopyright (c) 2007 HelenOS project\n", |
56,7 → 67,7 |
release, revision, timestamp); |
} |
/** Copies all images to #KERNEL_VIRTUAL_ADDRESS and jumps there. */ |
/** Copies all images (kernel + user tasks) to #KERNEL_VIRTUAL_ADDRESS and jumps there. */ |
void bootstrap(void) |
{ |
mmu_start(); |
97,3 → 108,6 |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo, sizeof(bootinfo)); |
} |
/** @} |
*/ |
/branches/arm/boot/arch/arm32/loader/asm.h |
---|
26,12 → 26,39 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifndef __ASM_H__ |
#define __ASM_H__ |
/** @addtogroup arm32boot |
* @{ |
*/ |
/** @file |
*/ |
#ifndef BOOT_arm32_ASM_H |
#define BOOT_arm32_ASM_H |
/** Copies #cnt bytes from #dst to #src. |
* |
* @param dst Destination address. |
* @param src Source address. |
* @param cnt Count of bytes to be copied. |
*/ |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
/*void memcpy(void *dst, void *src, int cnt);*/ |
/** Jumps to the kernel. |
* |
* @param entry Kernel entry point address. |
* @param bootinfo Structure holding information about loaded tasks. |
* @param bootinto_size Size of the #bootinfo structure. |
*/ |
void jump_to_kernel(void *entry, void *bootinfo, unsigned int bootinfo_size) __attribute__((noreturn)); |
#endif |
/** @} |
*/ |
/branches/arm/boot/arch/arm32/loader/main.h |
---|
26,29 → 26,54 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifndef __MAIN_H__ |
#define __MAIN_H__ |
/** Align to the nearest higher address. |
/** @addtogroup arm32boot |
* @{ |
*/ |
/** @file |
*/ |
#ifndef BOOT_arm32_MAIN_H |
#define BOOT_arm32_MAIN_H |
/** Aligns to the nearest higher address. |
* |
* @param addr Address or size to be aligned. |
* @param addr Address or number to be aligned. |
* @param align Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1)) |
/** Maximum number of tasks in the #bootinfo_t structure. */ |
#define TASKMAP_MAX_RECORDS 32 |
/** Structure holding information about single loaded task. */ |
typedef struct { |
/** Address where the task was placed. */ |
void *addr; |
/** Size of the task binary. */ |
unsigned int size; |
} task_t; |
/** Structure holding information about loaded tasks. */ |
typedef struct { |
/** Number of loaded tasks. */ |
unsigned int cnt; |
/** Array of loaded tasks. */ |
task_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
/** Run when the CPU is switched on. */ |
extern void start(void); |
extern void bootstrap(void); |
#endif |
/** @} |
*/ |
/branches/arm/boot/arch/arm32/loader/mm.c |
---|
26,6 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32boot |
* @{ |
*/ |
32,17 → 33,19 |
/** @file |
*/ |
#include "mm.h" |
/** Initializes section page table entry. |
/** Initializes "section" page table entry. |
* |
* Will be readable/writable by kernel with no access from user mode. |
* Will belong to domain 0. No cache or buffering is enabled. |
* |
* \param pte page table entry to set |
* \param frame first frame in the section (frame number) |
* \note If frame is not 1MB aligned, first lower 1MB aligned frame will be used. |
* @param pte Section entry to initialize. |
* @param frame First frame in the section (frame number). |
* |
* @note If #frame is not 1MB aligned, first lower 1MB aligned frame will be used. |
*/ |
static void init_pte_level0_section(pte_level0_section_t* pte, unsigned frame) |
{ |
58,23 → 61,27 |
} |
/** Initializes page table used while booting the kernel. */ |
static void init_page_table(void) |
{ |
int i; |
const unsigned int first_kernel_section = ADDR2PFN(PA2KA(0)) / FRAMES_PER_SECTION; |
const unsigned int first_kernel_section = ADDR2PFN(PA2KA(0)) / FRAMES_PER_SECTION; |
// create 1:1 mapping virtual-physical (in lower 2GB) |
// create 1:1 virtual-physical mapping (in lower 2GB) |
for(i = 0; i < first_kernel_section; i++) { |
init_pte_level0_section(&page_table[i], i * FRAMES_PER_SECTION); |
} |
// create kernel mapping (in upper 2GB), physical addresses starting from 0 |
for(i = first_kernel_section; i < PTL0_ENTRIES_ARCH; i++) { |
// create 1:1 virtual-physical mapping in kernel space (upper 2GB), |
// physical addresses start from 0 |
for (i = first_kernel_section; i < PTL0_ENTRIES; i++) { |
init_pte_level0_section(&page_table[i], (i - first_kernel_section) * FRAMES_PER_SECTION); |
} |
} |
/** Starts the MMU - initializes page table and enables paging. |
*/ |
void mmu_start() { |
init_page_table(); |
set_ptl0_address(page_table); |
81,6 → 88,7 |
enable_paging(); |
} |
/** @} |
*/ |
/branches/arm/boot/arch/arm32/loader/types.h |
---|
26,9 → 26,18 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifndef TYPES_H__ |
#define TYPES_H__ |
/** @addtogroup arm32boot |
* @{ |
*/ |
/** @file |
*/ |
#ifndef BOOT_arm32_TYPES_H |
#define BOOT_arm32_TYPES_H |
#include <gentypes.h> |
typedef signed char int8_t; |
41,4 → 50,10 |
typedef uint32_t uintptr_t; |
typedef uint32_t unative_t; |
#endif |
/** @} |
*/ |
/branches/arm/boot/arch/arm32/loader/print/gxemul.c |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2007 Michal Kebrt |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32boot |
* @{ |
*/ |
/** @file |
*/ |
#include <printf.h> |
/** Address where characters to be printed are expected. */ |
#define PUTC_ADDRESS 0x10000000 |
/** Prints a character to the console. |
* |
* @param ch Character to be printed. |
*/ |
static void putc(char ch) |
{ |
*((volatile char *)PUTC_ADDRESS) = ch; |
} |
/** Prints a string to the console. |
* |
* @param str String to be printed. |
* @param len Number of characters to be printed. |
*/ |
void write(const char *str, const int len) |
{ |
int i; |
for (i = 0; i < len; ++i) { |
putc(str[i]); |
} |
} |
/** @} |
*/ |