/branches/sparc/kernel/arch/sparc64/include/drivers/ns16550.h |
---|
35,7 → 35,67 |
#ifndef KERN_sparc64_NS16550_H_ |
#define KERN_sparc64_NS16550_H_ |
#include <arch/types.h> |
#include <arch/drivers/kbd.h> |
/* NS16550 registers */ |
#define RBR_REG 0 /** Receiver Buffer Register. */ |
#define IER_REG 1 /** Interrupt Enable Register. */ |
#define IIR_REG 2 /** Interrupt Ident Register (read). */ |
#define FCR_REG 2 /** FIFO control register (write). */ |
#define LCR_REG 3 /** Line Control register. */ |
#define LSR_REG 5 /** Line Status Register. */ |
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */ |
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */ |
/** Structure representing the ns16550 device. */ |
typedef struct { |
devno_t devno; |
volatile uint8_t *reg; /** Memory mapped registers of the ns16550. */ |
} ns16550_t; |
static inline uint8_t ns16550_rbr_read(ns16550_t *dev) |
{ |
return dev->reg[RBR_REG]; |
} |
static inline uint8_t ns16550_ier_read(ns16550_t *dev) |
{ |
return dev->reg[IER_REG]; |
} |
static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v) |
{ |
dev->reg[IER_REG] = v; |
} |
static inline uint8_t ns16550_iir_read(ns16550_t *dev) |
{ |
return dev->reg[IIR_REG]; |
} |
static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v) |
{ |
dev->reg[FCR_REG] = v; |
} |
static inline uint8_t ns16550_lcr_read(ns16550_t *dev) |
{ |
return dev->reg[LCR_REG]; |
} |
static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v) |
{ |
dev->reg[LCR_REG] = v; |
} |
static inline uint8_t ns16550_lsr_read(ns16550_t *dev) |
{ |
return dev->reg[LSR_REG]; |
} |
#endif |
/** @} |
/branches/sparc/kernel/arch/sparc64/include/asm.h |
---|
42,56 → 42,7 |
#include <arch/register.h> |
#include <config.h> |
#include <arch/stack.h> |
#include <arch/barrier.h> |
static inline void outb(ioport_t port, uint8_t v) |
{ |
*((volatile uint8_t *)(port)) = v; |
memory_barrier(); |
} |
static inline void outw(ioport_t port, uint16_t v) |
{ |
*((volatile uint16_t *)(port)) = v; |
memory_barrier(); |
} |
static inline void outl(ioport_t port, uint32_t v) |
{ |
*((volatile uint32_t *)(port)) = v; |
memory_barrier(); |
} |
static inline uint8_t inb(ioport_t port) |
{ |
uint8_t rv; |
rv = *((volatile uint8_t *)(port)); |
memory_barrier(); |
return rv; |
} |
static inline uint16_t inw(ioport_t port) |
{ |
uint16_t rv; |
rv = *((volatile uint16_t *)(port)); |
memory_barrier(); |
return rv; |
} |
static inline uint32_t inl(ioport_t port) |
{ |
uint32_t rv; |
rv = *((volatile uint32_t *)(port)); |
memory_barrier(); |
return rv; |
} |
/** Read Processor State register. |
* |
* @return Value of PSTATE register. |
/branches/sparc/kernel/arch/sparc64/include/types.h |
---|
54,8 → 54,6 |
typedef uint64_t ipl_t; |
typedef uint64_t ioport_t; |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
/branches/sparc/kernel/arch/sparc64/src/drivers/kbd.c |
---|
147,7 → 147,7 |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550_init(devno, inr, (ioport_t)vaddr); |
ns16550_init(devno, inr, vaddr); |
break; |
#endif |
default: |
/branches/sparc/kernel/arch/ia64/include/asm.h |
---|
39,11 → 39,10 |
#include <arch/types.h> |
#include <arch/register.h> |
typedef uint64_t ioport_t; |
#define IA64_IOSPACE_ADDRESS 0xE001000000000000ULL |
static inline void outb(ioport_t port,uint8_t v) |
static inline void outb(uint64_t port,uint8_t v) |
{ |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
50,7 → 49,7 |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void outw(ioport_t port,uint16_t v) |
static inline void outw(uint64_t port,uint16_t v) |
{ |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
57,7 → 56,7 |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void outl(ioport_t port,uint32_t v) |
static inline void outl(uint64_t port,uint32_t v) |
{ |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
66,7 → 65,7 |
static inline uint8_t inb(ioport_t port) |
static inline uint8_t inb(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
73,7 → 72,7 |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))); |
} |
static inline uint16_t inw(ioport_t port) |
static inline uint16_t inw(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
80,7 → 79,7 |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 )))); |
} |
static inline uint32_t inl(ioport_t port) |
static inline uint32_t inl(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
99,14 → 98,9 |
{ |
uint64_t v; |
//I'm not sure why but this code bad inlines in scheduler, |
//so THE shifts about 16B and causes kernel panic |
//asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1))); |
//return v; |
asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1))); |
//this code have the same meaning but inlines well |
asm volatile ("mov %0 = r12" : "=r" (v) ); |
return v & (~(STACK_SIZE-1)); |
return v; |
} |
/** Return Processor State Register. |
158,16 → 152,6 |
return v; |
} |
static inline uint64_t cr64_read(void) |
{ |
uint64_t v; |
asm volatile ("mov %0 = cr64\n" : "=r" (v)); |
return v; |
} |
/** Write ITC (Interval Timer Counter) register. |
* |
* @param v New counter value. |
/branches/sparc/kernel/arch/ia64/include/mm/page.h |
---|
46,20 → 46,8 |
/** Bit width of the TLB-locked portion of kernel address space. */ |
#define KERNEL_PAGE_WIDTH 28 /* 256M */ |
#define IO_PAGE_WIDTH 26 /* 64M */ |
#define FW_PAGE_WIDTH 28 /* 256M */ |
/** Staticly mapped IO spaces */ |
/* Firmware area (bellow 4GB in phys mem) */ |
#define FW_OFFSET 0x00000000F0000000 |
/* Legacy IO space */ |
#define IO_OFFSET 0x0001000000000000 |
/* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000*/ |
#define VIO_OFFSET 0x0002000000000000 |
#define PPN_SHIFT 12 |
#define VRN_SHIFT 61 |
/branches/sparc/kernel/arch/ia64/include/drivers/it.h |
---|
41,7 → 41,7 |
* from firmware. |
* |
*/ |
#define IT_DELTA it_delta |
#define IT_DELTA 100000 |
extern void it_init(void); |
/branches/sparc/kernel/arch/ia64/include/bootinfo.h |
---|
29,8 → 29,8 |
#ifndef KERN_ia64_BOOTINFO_H_ |
#define KERN_ia64_BOOTINFO_H_ |
#define BOOTINFO_ADDRESS 0x4401000 |
#define CONFIG_INIT_TASKS 32 |
typedef struct { |
46,12 → 46,6 |
typedef struct { |
binit_t taskmap; |
unsigned long * sapic; |
unsigned long sys_freq; |
unsigned long freq_scale; |
unsigned int wakeup_intno; |
} bootinfo_t; |
extern bootinfo_t *bootinfo; |
/branches/sparc/kernel/arch/ia64/include/cpu.h |
---|
38,7 → 38,6 |
#include <arch/types.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
#include <arch/bootinfo.h> |
#define FAMILY_ITANIUM 0x7 |
#define FAMILY_ITANIUM2 0x1f |
64,33 → 63,6 |
return v; |
} |
#define CR64_ID_SHIFT 24 |
#define CR64_ID_MASK 0xff000000 |
#define CR64_EID_SHIFT 16 |
#define CR64_EID_MASK 0xff0000 |
static inline int ia64_get_cpu_id(void) |
{ |
uint64_t cr64=cr64_read(); |
return ((CR64_ID_MASK)&cr64)>>CR64_ID_SHIFT; |
} |
static inline int ia64_get_cpu_eid(void) |
{ |
uint64_t cr64=cr64_read(); |
return ((CR64_EID_MASK)&cr64)>>CR64_EID_SHIFT; |
} |
static inline void ipi_send_ipi(int id,int eid,int intno) |
{ |
(bootinfo->sapic)[2*(id*256+eid)]=intno; |
} |
#endif |
/** @} |
/branches/sparc/kernel/arch/ia64/include/atomic.h |
---|
51,20 → 51,6 |
return v; |
} |
static inline uint64_t test_and_set(atomic_t *val) { |
uint64_t v; |
asm volatile ( |
"movl %0=0x01;;\n" |
"xchg8 %0=%1,%0;;\n" |
: "=r" (v),"+m" (val->count) |
); |
return v; |
} |
static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); } |
static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); } |
/branches/sparc/kernel/arch/ia64/Makefile.inc |
---|
82,7 → 82,6 |
arch/$(ARCH)/src/mm/vhpt.c \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/smp/smp.c \ |
arch/$(ARCH)/src/drivers/it.c |
ifeq ($(MACHINE),ski) |
99,7 → 98,3 |
BFD = binary |
endif |
ifeq ($(CONFIG_SMP),y) |
DEFS += -DCONFIG_SMP |
endif |
/branches/sparc/kernel/arch/ia64/src/smp/smp.c |
---|
File deleted |
/branches/sparc/kernel/arch/ia64/src/mm/frame.c |
---|
42,31 → 42,20 |
* for real ia64 systems that provide memory map. |
*/ |
#define MEMORY_SIZE (64 * 1024 * 1024) |
#define MEMORY_BASE (0 * 64 * 1024 * 1024) |
#define MEMORY_BASE (64 * 1024 * 1024) |
#define ONE_TO_ONE_MAPPING_SIZE (256*1048576) // Mapped at start |
#define ROM_BASE 0xa0000 //For ski |
#define ROM_SIZE (384 * 1024) //For ski |
void poke_char(int x,int y,char ch, char c); |
uintptr_t last_frame; |
void frame_arch_init(void) |
{ |
if(config.cpu_active==1) |
{ |
zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0); |
zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0); |
/* |
* Blacklist ROM regions. |
*/ |
//frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE)); |
frame_mark_unavailable(ADDR2PFN(0), SIZE2FRAMES(1048576)); |
last_frame=SIZE2FRAMES((VRN_KERNEL<<VRN_SHIFT)+ONE_TO_ONE_MAPPING_SIZE); |
} |
/* |
* Blacklist ROM regions. |
*/ |
frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE)); |
} |
/** @} |
/branches/sparc/kernel/arch/ia64/src/mm/page.c |
---|
47,7 → 47,6 |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <memstr.h> |
#include <align.h> |
static void set_environment(void); |
263,27 → 262,5 |
v->present.tag.tag_word = tag; |
} |
extern uintptr_t last_frame; |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) { |
uintptr_t addr = PFN2ADDR(i); |
page_mapping_insert(AS_KERNEL, virtaddr + addr, physaddr + addr, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
} |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
return virtaddr; |
} |
/** @} |
*/ |
/branches/sparc/kernel/arch/ia64/src/drivers/it.c |
---|
46,16 → 46,6 |
#define IT_SERVICE_CLOCKS 64 |
#define FREQ_NUMERATOR_SHIFT 32 |
#define FREQ_NUMERATOR_MASK 0xffffffff00000000LL |
#define FREQ_DENOMINATOR_SHIFT 0 |
#define FREQ_DENOMINATOR_MASK 0xffffffffLL |
uint64_t it_delta; |
static irq_t it_irq; |
static irq_ownership_t it_claim(void); |
65,25 → 55,14 |
void it_init(void) |
{ |
cr_itv_t itv; |
if(config.cpu_active==1) |
{ |
irq_initialize(&it_irq); |
it_irq.inr = INTERRUPT_TIMER; |
it_irq.devno = device_assign_devno(); |
it_irq.claim = it_claim; |
it_irq.handler = it_interrupt; |
irq_register(&it_irq); |
uint64_t base_freq; |
base_freq = ((bootinfo->freq_scale) & FREQ_NUMERATOR_MASK) >> FREQ_NUMERATOR_SHIFT; |
base_freq *= bootinfo->sys_freq; |
base_freq /= ((bootinfo->freq_scale) & FREQ_DENOMINATOR_MASK) >> FREQ_DENOMINATOR_SHIFT; |
it_delta = base_freq /HZ; |
} |
irq_initialize(&it_irq); |
it_irq.inr = INTERRUPT_TIMER; |
it_irq.devno = device_assign_devno(); |
it_irq.claim = it_claim; |
it_irq.handler = it_interrupt; |
irq_register(&it_irq); |
/* initialize Interval Timer external interrupt vector */ |
itv.value = itv_read(); |
itv.vector = INTERRUPT_TIMER; |
/branches/sparc/kernel/arch/ia64/src/ia64.c |
---|
54,17 → 54,7 |
#include <arch/drivers/ega.h> |
#include <arch/bootinfo.h> |
#include <genarch/kbd/i8042.h> |
#include <genarch/kbd/ns16550.h> |
#include <smp/smp.h> |
#include <smp/ipi.h> |
#include <arch/atomic.h> |
#include <panic.h> |
#include <print.h> |
/*NS16550 as a COM 1*/ |
#define NS16550_IRQ 4 |
#define NS16550_PORT 0x3f8 |
bootinfo_t *bootinfo; |
void arch_pre_main(void) |
112,15 → 102,12 |
void arch_post_mm_init(void) |
{ |
if(config.cpu_active==1) |
{ |
irq_init(INR_COUNT, INR_COUNT); |
irq_init(INR_COUNT, INR_COUNT); |
#ifdef SKI |
ski_init_console(); |
ski_init_console(); |
#else |
ega_init(); |
ega_init(); |
#endif |
} |
it_init(); |
} |
140,9 → 127,6 |
{ |
while (1) { |
i8042_poll(); |
#ifdef CONFIG_NS16550 |
ns16550_poll(); |
#endif |
thread_usleep(POLL_INTERVAL); |
} |
} |
151,7 → 135,7 |
void arch_post_smp_init(void) |
{ |
{ |
if (config.cpu_active == 1) { |
/* |
* Create thread that polls keyboard. |
*/ |
169,10 → 153,6 |
/* keyboard controller */ |
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE); |
#ifdef CONFIG_NS16550 |
ns16550_init(kbd, NS16550_IRQ, NS16550_PORT); // as a COM 1 |
#else |
#endif |
thread_t *t; |
t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
184,7 → 164,6 |
} |
} |
/** Enter userspace and never return. */ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
245,7 → 224,7 |
void arch_reboot(void) |
{ |
outb(0x64,0xfe); |
// TODO |
while (1); |
} |
/branches/sparc/kernel/arch/ia64/src/start.S |
---|
39,10 → 39,12 |
#define KERNEL_TRANSLATION_D 0x0010000000000661 |
#define KERNEL_TRANSLATION_VIO 0x0010000000000671 |
#define KERNEL_TRANSLATION_IO 0x00100FFFFC000671 |
#define KERNEL_TRANSLATION_FW 0x00100000F0000671 |
#define VIO_OFFSET 0x0002000000000000 |
#define IO_OFFSET 0x0001000000000000 |
.section K_TEXT_START, "ax" |
.global kernel_image_start |
51,18 → 53,6 |
kernel_image_start: |
.auto |
#identifi self(CPU) in OS structures by ID / EID |
mov r9=cr64 |
mov r10=1 |
movl r12=0xffffffff |
movl r8=cpu_by_id_eid_list |
and r8=r8,r12 |
shr r9=r9,16 |
add r8=r8,r9 |
st1 [r8]=r10 |
mov psr.l = r0 |
srlz.i |
srlz.d |
124,25 → 114,8 |
itr.d dtr[r7] = r10 |
#setup mapping for fimware arrea (also SAPIC) |
mov r11 = cr.itir ;; |
movl r10 = ~0xfc;; |
and r10 =r10 , r11 ;; |
movl r11 = (FW_PAGE_WIDTH << PS_SHIFT);; |
or r10 =r10 , r11 ;; |
mov cr.itir = r10;; |
movl r7 = 3 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) | FW_OFFSET |
mov cr.ifa = r8 |
movl r10 = (KERNEL_TRANSLATION_FW) |
itr.d dtr[r7] = r10 |
# initialize PSR |
movl r10 = (PSR_DT_MASK | PSR_RT_MASK | PSR_IT_MASK | PSR_IC_MASK) /* Enable paging */ |
mov r9 = psr |
169,12 → 142,6 |
# switch to register bank 1 |
bsw.1 |
#Am'I BSP or AP |
movl r20=bsp_started;; |
ld8 r20=[r20];; |
cmp.eq p3,p2=r20,r0;; |
# initialize register stack |
mov ar.rsc = r0 |
193,35 → 160,25 |
movl r1 = _hardcoded_load_address |
/* |
* Initialize hardcoded_* variables. Do only BSP |
* Initialize hardcoded_* variables. |
*/ |
(p3) movl r14 = _hardcoded_ktext_size |
(p3) movl r15 = _hardcoded_kdata_size |
(p3) movl r16 = _hardcoded_load_address ;; |
(p3) addl r17 = @gprel(hardcoded_ktext_size), gp |
(p3) addl r18 = @gprel(hardcoded_kdata_size), gp |
(p3) addl r19 = @gprel(hardcoded_load_address), gp |
(p3) addl r21 = @gprel(bootinfo), gp |
movl r14 = _hardcoded_ktext_size |
movl r15 = _hardcoded_kdata_size |
movl r16 = _hardcoded_load_address ;; |
addl r17 = @gprel(hardcoded_ktext_size), gp |
addl r18 = @gprel(hardcoded_kdata_size), gp |
addl r19 = @gprel(hardcoded_load_address), gp |
addl r21 = @gprel(bootinfo), gp |
;; |
(p3) st8 [r17] = r14 |
(p3) st8 [r18] = r15 |
(p3) st8 [r19] = r16 |
(p3) st8 [r21] = r20 |
st8 [r17] = r14 |
st8 [r18] = r15 |
st8 [r19] = r16 |
st8 [r21] = r20 |
ssm (1 << 19) ;; /* Disable f32 - f127 */ |
srlz.i |
srlz.d ;; |
(p2) movl r18 = main_ap ;; |
(p2) mov b1 = r18 ;; |
(p2) br.call.sptk.many b0 = b1 |
#Mark that BSP is on |
mov r20=1;; |
movl r21=bsp_started;; |
st8 [r21]=r20;; |
br.call.sptk.many b0 = arch_pre_main |
movl r18 = main_bsp ;; |
231,46 → 188,3 |
0: |
br 0b |
.align 4096 |
kernel_image_ap_start: |
.auto |
#identifi self(CPU) in OS structures by ID / EID |
mov r9=cr64 |
mov r10=1 |
movl r12=0xffffffff |
movl r8=cpu_by_id_eid_list |
and r8=r8,r12 |
shr r9=r9,16 |
add r8=r8,r9 |
st1 [r8]=r10 |
#wait for wakeup sychro signal (#3 in cpu_by_id_eid_list) |
kernel_image_ap_start_loop: |
movl r11=kernel_image_ap_start_loop |
and r11=r11,r12 |
mov b1 = r11 |
ld1 r20=[r8];; |
movl r21=3;; |
cmp.eq p2,p3=r20,r21;; |
(p3)br.call.sptk.many b0 = b1 |
movl r11=kernel_image_start |
and r11=r11,r12 |
mov b1 = r11 |
br.call.sptk.many b0 = b1 |
.align 16 |
.global bsp_started |
bsp_started: |
.space 8 |
.align 4096 |
.global cpu_by_id_eid_list |
cpu_by_id_eid_list: |
.space 65536 |
/branches/sparc/kernel/arch/ppc32/src/asm.S |
---|
66,9 → 66,9 |
mr sp, r4 |
# %r6 is defined to hold pcb_ptr - set it to 0 |
# %r3 is defined to hold pcb_ptr - set it to 0 |
xor r6, r6, r6 |
xor r3, r3, r3 |
# jump to userspace |
/branches/sparc/kernel/arch/ppc32/src/mm/tlb.c |
---|
96,6 → 96,7 |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
printf("Page fault.\n"); |
*pfrc = rc; |
return NULL; |
default: |
/branches/sparc/kernel/arch/ppc64/src/mm/page.c |
---|
103,6 → 103,7 |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
printf("Page fault.\n"); |
*pfrc = rc; |
return NULL; |
default: |
/branches/sparc/kernel/arch/mips32/src/mm/tlb.c |
---|
429,6 → 429,7 |
break; |
case AS_PF_FAULT: |
page_table_lock(AS, true); |
printf("Page fault.\n"); |
*pfrc = AS_PF_FAULT; |
return NULL; |
break; |
/branches/sparc/kernel/genarch/include/kbd/ns16550.h |
---|
48,75 → 48,7 |
extern irq_ownership_t ns16550_claim(void); |
extern void ns16550_irq_handler(irq_t *irq, void *arg, ...); |
#include <arch/types.h> |
#ifndef ia64 |
#include <arch/drivers/kbd.h> |
#endif |
/* NS16550 registers */ |
#define RBR_REG 0 /** Receiver Buffer Register. */ |
#define IER_REG 1 /** Interrupt Enable Register. */ |
#define IIR_REG 2 /** Interrupt Ident Register (read). */ |
#define FCR_REG 2 /** FIFO control register (write). */ |
#define LCR_REG 3 /** Line Control register. */ |
#define LSR_REG 5 /** Line Status Register. */ |
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */ |
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */ |
/** Structure representing the ns16550 device. */ |
typedef struct { |
devno_t devno; |
volatile ioport_t io_port; /** Memory mapped registers of the ns16550. */ |
} ns16550_t; |
static inline uint8_t ns16550_rbr_read(ns16550_t *dev) |
{ |
return inb(dev->io_port+RBR_REG); |
} |
static inline void ns16550_rbr_write(ns16550_t *dev, uint8_t v) |
{ |
outb(dev->io_port+RBR_REG,v); |
} |
static inline uint8_t ns16550_ier_read(ns16550_t *dev) |
{ |
return inb(dev->io_port+IER_REG); |
} |
static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v) |
{ |
outb(dev->io_port+IER_REG,v); |
} |
static inline uint8_t ns16550_iir_read(ns16550_t *dev) |
{ |
return inb(dev->io_port+IIR_REG); |
} |
static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v) |
{ |
outb(dev->io_port+FCR_REG,v); |
} |
static inline uint8_t ns16550_lcr_read(ns16550_t *dev) |
{ |
return inb(dev->io_port+LCR_REG); |
} |
static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v) |
{ |
outb(dev->io_port+LCR_REG,v); |
} |
static inline uint8_t ns16550_lsr_read(ns16550_t *dev) |
{ |
return inb(dev->io_port+LSR_REG); |
} |
#endif |
/** @} |
*/ |
/branches/sparc/kernel/genarch/src/kbd/key.c |
---|
39,13 → 39,9 |
#ifdef CONFIG_I8042 |
#include <genarch/kbd/scanc_pc.h> |
#endif |
#if (defined(sparc64)) |
#if (defined(CONFIG_Z8530) || defined(CONFIG_NS16550)) |
#include <genarch/kbd/scanc_sun.h> |
#endif |
#endif |
#include <synch/spinlock.h> |
#include <console/chardev.h> |
#include <macros.h> |
/branches/sparc/kernel/genarch/src/kbd/ns16550.c |
---|
38,10 → 38,8 |
#include <genarch/kbd/key.h> |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_sun.h> |
#ifndef ia64 |
#include <arch/drivers/kbd.h> |
#include <arch/drivers/ns16550.h> |
#endif |
#include <ddi/irq.h> |
#include <ipc/irq.h> |
#include <cpu.h> |
111,13 → 109,13 |
* @param inr Interrupt number. |
* @param vaddr Virtual address of device's registers. |
*/ |
void ns16550_init(devno_t devno, inr_t inr, ioport_t port) |
void ns16550_init(devno_t devno, inr_t inr, uintptr_t vaddr) |
{ |
chardev_initialize("ns16550_kbd", &kbrd, &ops); |
stdin = &kbrd; |
ns16550.devno = devno; |
ns16550.io_port = port; |
ns16550.reg = (uint8_t *) vaddr; |
irq_initialize(&ns16550_irq); |
ns16550_irq.devno = devno; |
127,21 → 125,10 |
irq_register(&ns16550_irq); |
sysinfo_set_item_val("kbd", NULL, true); |
#ifndef ia64 |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
#endif |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.virtual", NULL, port); |
#ifdef ia64 |
uint8_t c; |
c = ns16550_lcr_read(&ns16550); |
ns16550_lcr_write(&ns16550, 0x80 | c); |
ns16550_rbr_write(&ns16550, 0x0c); |
ns16550_ier_write(&ns16550, 0x00); |
ns16550_lcr_write(&ns16550, c); |
#endif |
sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr); |
ns16550_grab(); |
} |
165,7 → 152,6 |
{ |
} |
char ns16550_key_read(chardev_t *d) |
{ |
char ch; |
175,7 → 161,6 |
while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY)) |
; |
x = ns16550_rbr_read(&ns16550); |
#ifndef ia64 |
if (x != IGNORE_CODE) { |
if (x & KEY_RELEASE) |
key_released(x ^ KEY_RELEASE); |
182,15 → 167,6 |
else |
active_read_key_pressed(x); |
} |
#else |
extern chardev_t kbrd; |
if(x != 0x0d) { |
if(x == 0x7f) |
x = '\b'; |
chardev_push_character(&kbrd, x); |
} |
#endif |
} |
return ch; |
} |
225,7 → 201,6 |
uint8_t x; |
x = ns16550_rbr_read(&ns16550); |
#ifndef ia64 |
if (x != IGNORE_CODE) { |
if (x & KEY_RELEASE) |
key_released(x ^ KEY_RELEASE); |
232,15 → 207,6 |
else |
key_pressed(x); |
} |
#else |
extern chardev_t kbrd; |
if(x != 0x0d) { |
if (x == 0x7f) |
x = '\b'; |
chardev_push_character(&kbrd, x); |
} |
#endif |
} |
} |
/branches/sparc/kernel/generic/src/main/main.c |
---|
329,7 → 329,6 |
* collide with another CPU coming up. To prevent this, we |
* switch to this cpu's private stack prior to waking kmp up. |
*/ |
context_save(&CPU->saved_context); |
context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), |
(uintptr_t) CPU->stack, CPU_STACK_SIZE); |
context_restore(&CPU->saved_context); |
/branches/sparc/kernel/generic/src/main/kinit.c |
---|
169,7 → 169,7 |
} |
int rc = program_create_from_image((void *) init.tasks[i].addr, |
"init-bin", &programs[i]); |
&programs[i]); |
if (rc == 0 && programs[i].task != NULL) { |
/* |
/branches/sparc/kernel/generic/src/proc/thread.c |
---|
279,7 → 279,7 |
* guarantee that the task won't cease to exist during the |
* call. The task's lock may not be held. |
* @param flags Thread flags. |
* @param name Symbolic name (a copy is made). |
* @param name Symbolic name. |
* @param uncounted Thread's accounting doesn't affect accumulated task |
* accounting. |
* |
316,7 → 316,6 |
interrupts_restore(ipl); |
memcpy(t->name, name, THREAD_NAME_BUFLEN); |
t->name[THREAD_NAME_BUFLEN - 1] = '\0'; |
t->thread_code = func; |
t->thread_arg = arg; |
709,7 → 708,7 |
* |
*/ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, |
size_t name_len, thread_id_t *uspace_thread_id) |
thread_id_t *uspace_thread_id) |
{ |
thread_t *t; |
char namebuf[THREAD_NAME_BUFLEN]; |
716,15 → 715,10 |
uspace_arg_t *kernel_uarg; |
int rc; |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
/* |
* In case of failure, kernel_uarg will be deallocated in this function. |
* In case of success, kernel_uarg will be freed in uinit(). |
/branches/sparc/kernel/generic/src/proc/task.c |
---|
130,7 → 130,7 |
/** Create new task with no threads. |
* |
* @param as Task's address space. |
* @param name Symbolic name (a copy is made). |
* @param name Symbolic name. |
* |
* @return New task's structure. |
* |
148,10 → 148,7 |
spinlock_initialize(&ta->lock, "task_ta_lock"); |
list_initialize(&ta->th_head); |
ta->as = as; |
memcpy(ta->name, name, TASK_NAME_BUFLEN); |
ta->name[TASK_NAME_BUFLEN - 1] = '\0'; |
ta->name = name; |
atomic_set(&ta->refcount, 0); |
atomic_set(&ta->lifecount, 0); |
ta->context = CONTEXT; |
/branches/sparc/kernel/generic/src/proc/program.c |
---|
67,10 → 67,9 |
* |
* @param as Address space containing a binary program image. |
* @param entry_addr Program entry-point address in program address space. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program information. |
*/ |
void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p) |
void program_create(as_t *as, uintptr_t entry_addr, program_t *p) |
{ |
as_area_t *a; |
uspace_arg_t *kernel_uarg; |
82,7 → 81,7 |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
p->task = task_create(as, name); |
p->task = task_create(as, "app"); |
ASSERT(p->task); |
/* |
107,7 → 106,6 |
* executable image. The task is returned in *task. |
* |
* @param image_addr Address of an executable program image. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program info. If image_addr |
* points to a loader image, p->task will be set to |
* NULL and EOK will be returned. |
114,7 → 112,7 |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_from_image(void *image_addr, char *name, program_t *p) |
int program_create_from_image(void *image_addr, program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
138,7 → 136,7 |
return EOK; |
} |
program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p); |
program_create(as, ((elf_header_t *) image_addr)->e_entry, p); |
return EOK; |
} |
145,12 → 143,10 |
/** Create a task from the program loader image. |
* |
* @param p Buffer for storing program info. |
* @param name Name to set for the program's task. |
* |
* @param p Buffer for storing program info. |
* @return EOK on success or negative error code. |
*/ |
int program_create_loader(program_t *p, char *name) |
int program_create_loader(program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
171,8 → 167,7 |
return ENOENT; |
} |
program_create(as, ((elf_header_t *) program_loader)->e_entry, |
name, p); |
program_create(as, ((elf_header_t *) program_loader)->e_entry, p); |
return EOK; |
} |
193,20 → 188,16 |
* Creates a new task from the program loader image, connects a phone |
* to it and stores the phone id into the provided buffer. |
* |
* @param uspace_phone_id Userspace address where to store the phone id. |
* @param name Name to set on the new task (typically the same |
* as the command used to execute it). |
* @param uspace_phone_id Userspace address where to store the phone id. |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_program_spawn_loader(int *uspace_phone_id, char *uspace_name, |
size_t name_len) |
unative_t sys_program_spawn_loader(int *uspace_phone_id) |
{ |
program_t p; |
int fake_id; |
int rc; |
int phone_id; |
char namebuf[TASK_NAME_BUFLEN]; |
fake_id = 0; |
216,26 → 207,11 |
if (rc != 0) |
return rc; |
/* Cap length of name and copy it from userspace. */ |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
/* Allocate the phone for communicating with the new task. */ |
phone_id = phone_alloc(); |
if (phone_id < 0) |
return ELIMIT; |
/* Spawn the new task. */ |
rc = program_create_loader(&p, namebuf); |
rc = program_create_loader(&p); |
if (rc != 0) |
return rc; |
/branches/sparc/kernel/generic/src/mm/tlb.c |
---|
134,9 → 134,7 |
void tlb_shootdown_ipi_send(void) |
{ |
#ifndef ia64 |
ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI); |
#endif |
} |
/** Receive TLB shootdown message. */ |
/branches/sparc/kernel/generic/src/ipc/kbox.c |
---|
45,7 → 45,6 |
void ipc_kbox_cleanup(void) |
{ |
ipl_t ipl; |
bool have_kb_thread; |
/* Only hold kb_cleanup_lock while setting kb_finished - this is enough */ |
64,17 → 63,6 |
* wake up and terminate. |
*/ |
ipc_answerbox_slam_phones(&TASK->kernel_box, have_kb_thread); |
/* |
* If the task was being debugged, clean up debugging session. |
* This is necessarry as slamming the phones won't force |
* kbox thread to clean it up since sender != debugger. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
if (have_kb_thread) { |
LOG("join kb_thread..\n"); |
91,75 → 79,13 |
spinlock_unlock(&TASK->kernel_box.lock); |
} |
/** Handle hangup message in kbox. |
* |
* @param call The IPC_M_PHONE_HUNGUP call structure. |
* @param last Output, the function stores @c true here if |
* this was the last phone, @c false otherwise. |
**/ |
static void kbox_proc_phone_hungup(call_t *call, bool *last) |
{ |
ipl_t ipl; |
LOG("kbox_proc_phone_hungup()\n"); |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->udebug.debugger) { |
/* Terminate debugging session (if any) */ |
LOG("kbox: terminate debug session\n"); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} else { |
LOG("kbox: was not debugger\n"); |
} |
LOG("kbox: continue with hangup message\n"); |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kernel_box, call); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
spinlock_lock(&TASK->answerbox.lock); |
if (list_empty(&TASK->answerbox.connected_phones)) { |
/* |
* Last phone has been disconnected. Detach this thread so it |
* gets freed and signal to the caller. |
*/ |
/* Only detach kbox thread unless already terminating. */ |
mutex_lock(&TASK->kb_cleanup_lock); |
if (&TASK->kb_finished == false) { |
/* Detach kbox thread so it gets freed from memory. */ |
thread_detach(TASK->kb_thread); |
TASK->kb_thread = NULL; |
} |
mutex_unlock(&TASK->kb_cleanup_lock); |
LOG("phone list is empty\n"); |
*last = true; |
} else { |
*last = false; |
} |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} |
/** Implementing function for the kbox thread. |
* |
* This function listens for debug requests. It terminates |
* when all phones are disconnected from the kbox. |
* |
* @param arg Ignored. |
*/ |
static void kbox_thread_proc(void *arg) |
{ |
call_t *call; |
int method; |
bool done; |
ipl_t ipl; |
(void)arg; |
LOG("kbox_thread_proc()\n"); |
169,28 → 95,46 |
call = ipc_wait_for_call(&TASK->kernel_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_NONE); |
if (call == NULL) |
continue; /* Try again. */ |
if (call != NULL) { |
method = IPC_GET_METHOD(call->data); |
switch (IPC_GET_METHOD(call->data)) { |
if (method == IPC_M_DEBUG_ALL) { |
udebug_call_receive(call); |
} |
case IPC_M_DEBUG_ALL: |
/* Handle debug call. */ |
udebug_call_receive(call); |
break; |
if (method == IPC_M_PHONE_HUNGUP) { |
LOG("kbox: handle hangup message\n"); |
case IPC_M_PHONE_HUNGUP: |
/* |
* Process the hangup call. If this was the last |
* phone, done will be set to true and the |
* while loop will terminate. |
*/ |
kbox_proc_phone_hungup(call, &done); |
break; |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->udebug.debugger) { |
/* Terminate debugging session (if any) */ |
LOG("kbox: terminate debug session\n"); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} else { |
LOG("kbox: was not debugger\n"); |
} |
default: |
/* Ignore */ |
break; |
LOG("kbox: continue with hangup message\n"); |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kernel_box, call); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
spinlock_lock(&TASK->answerbox.lock); |
if (list_empty(&TASK->answerbox.connected_phones)) { |
/* Last phone has been disconnected */ |
TASK->kb_thread = NULL; |
done = true; |
LOG("phone list is empty\n"); |
} |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} |
} |
} |
/branches/sparc/kernel/generic/include/proc/task.h |
---|
54,8 → 54,6 |
#include <proc/scheduler.h> |
#include <udebug/udebug.h> |
#define TASK_NAME_BUFLEN 20 |
struct thread; |
/** Task structure. */ |
69,8 → 67,8 |
* threads. |
*/ |
SPINLOCK_DECLARE(lock); |
char name[TASK_NAME_BUFLEN]; |
char *name; |
/** List of threads contained in this task. */ |
link_t th_head; |
/** Address space. */ |
/branches/sparc/kernel/generic/include/proc/thread.h |
---|
259,8 → 259,7 |
extern slab_cache_t *fpu_context_slab; |
/* Thread syscall prototypes. */ |
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg, |
char *uspace_name, size_t name_len, thread_id_t *uspace_thread_id); |
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, thread_id_t *uspace_thread_id); |
extern unative_t sys_thread_exit(int uspace_status); |
extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id); |
/branches/sparc/kernel/generic/include/proc/program.h |
---|
52,15 → 52,12 |
extern void *program_loader; |
extern void program_create(as_t *as, uintptr_t entry_addr, char *name, |
program_t *p); |
extern int program_create_from_image(void *image_addr, char *name, |
program_t *p); |
extern int program_create_loader(program_t *p, char *name); |
extern void program_create(as_t *as, uintptr_t entry_addr, program_t *p); |
extern int program_create_from_image(void *image_addr, program_t *p); |
extern int program_create_loader(program_t *p); |
extern void program_ready(program_t *p); |
extern unative_t sys_program_spawn_loader(int *uspace_phone_id, |
char *uspace_name, size_t name_len); |
extern unative_t sys_program_spawn_loader(int *uspace_phone_id); |
#endif |
/branches/sparc/kernel/generic/include/synch/spinlock.h |
---|
36,7 → 36,6 |
#define KERN_SPINLOCK_H_ |
#include <arch/types.h> |
#include <arch/barrier.h> |
#include <preemption.h> |
#include <atomic.h> |
#include <debug.h> |
/branches/sparc/kernel/generic/include/stdarg.h |
---|
45,7 → 45,7 |
#define va_start(ap, last) __builtin_va_start(ap, last) |
#define va_arg(ap, type) __builtin_va_arg(ap, type) |
#define va_end(ap) __builtin_va_end(ap) |
#define va_copy(dst, src) __builtin_va_copy(dst, src) |
#define va_copy(dst,src) __builtin_va_copy(dst,src) |
#endif |
/branches/sparc/kernel/kernel.config |
---|
123,7 → 123,7 |
! [(ARCH=ia32|ARCH=amd64)&CONFIG_FB=y] CONFIG_VESA_BPP (choice) |
# Support for SMP |
! [ARCH=ia32|ARCH=amd64|ARCH=ia32xen|ARCH=sparc64|ARCH=ia64] CONFIG_SMP (y/n) |
! [ARCH=ia32|ARCH=amd64|ARCH=ia32xen|ARCH=sparc64] CONFIG_SMP (y/n) |
# Improved support for hyperthreading |
! [(ARCH=ia32|ARCH=amd64|ARCH=ia32xen)&CONFIG_SMP=y] CONFIG_HT (y/n) |
144,7 → 144,7 |
! [ARCH=sparc64] CONFIG_Z8530 (y/n) |
# Support for NS16550 serial port |
! [ARCH=sparc64|ARCH=ia64] CONFIG_NS16550 (y/n) |
! [ARCH=sparc64] CONFIG_NS16550 (y/n) |
# Support for Serengeti console |
! [ARCH=sparc64] CONFIG_SGCN (y/n) |
/branches/sparc/boot/arch/sparc64/loader/Makefile |
---|
154,7 → 154,7 |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
/branches/sparc/boot/arch/ia64/loader/Makefile |
---|
88,8 → 88,6 |
boot.S |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin |
NOCOMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
/branches/sparc/boot/arch/ia64/loader/gefi/apps/Makefile |
---|
28,7 → 28,7 |
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o |
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) |
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
LOADLIBES = -lefi -lgnuefi |
FORMAT = efi-app-$(ARCH) |
TARGETS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi printenv.efi t7.efi |
/branches/sparc/boot/arch/ia64/loader/gefi/HelenOS/Makefile |
---|
28,7 → 28,7 |
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o |
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) |
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
LOADLIBES = -lefi -lgnuefi |
FORMAT = efi-app-$(ARCH) |
45,29 → 45,16 |
-j .rela -j .reloc --target=$(FORMAT) hello.so hello.efi |
$(OBJDUMP) -d hello.efi > hello.disass |
#When selected first lines or second lines, select if image is linked into hello or not - usefull for network boot |
#hello.so: hello.o image.o |
hello.so: hello.o image.bin |
# $(LD) $(LDFLAGS) -Map hello.map hello.o image.o -o hello.so $(LOADLIBES) #link image inside hello |
$(LD) $(LDFLAGS) -Map hello.map hello.o -o hello.so $(LOADLIBES) #dont link image inside hello |
hello.so: hello.o image.o |
$(LD) $(LDFLAGS) -Map hello.map hello.o -o hello.so $(LOADLIBES) |
hello.o: hello.c |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c hello.c -o hello.o |
image.bin: ../../image.boot |
image.o: ../../image.boot |
$(OBJCOPY) -O binary ../../image.boot image.bin |
$(OBJCOPY) -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
image.o: ../../image.boot mkimage |
$(OBJCOPY) -O binary ../../image.boot image.bin |
./mkimage |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c image.c -o image.o |
# $(OBJCOPY) -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
mkimage: mkimage.c |
gcc -o mkimage mkimage.c |
gefi: |
make -C .. prefix=$(PREFIX) |
/branches/sparc/boot/arch/ia64/loader/gefi/HelenOS/hello.c |
---|
1,23 → 1,9 |
#include <efi.h> |
#include <efilib.h> |
#include <../../../../../../kernel/arch/ia64/include/bootinfo.h> |
#define KERNEL_LOAD_ADDRESS 0x4400000 |
//Link image as a data array into hello - usefull with network boot |
//#define IMAGE_LINKED |
bootinfo_t *bootinfo=(bootinfo_t *)BOOTINFO_ADDRESS; |
#ifdef IMAGE_LINKED |
extern char HOSimage[]; |
extern int HOSimagesize; |
#endif |
static CHAR16 * |
a2u (char *str) |
{ |
29,7 → 15,24 |
mem[i] = 0; |
return mem; |
} |
char HEX[256]; |
char hexs[]="0123456789ABCDEF"; |
/* |
void to_hex(unsigned long long num) |
{ |
int a; |
for(a=15;a>=0;a--) |
{ |
char c=num - (num & 0xfffffffffffffff0LL); |
num/=16; |
c=hexs[c]; |
HEX[a]=c; |
} |
} |
*/ |
EFI_STATUS |
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) |
{ |
69,12 → 72,11 |
EFI_FILE *FileHandle; |
BS->HandleProtocol(LoadedImage->DeviceHandle, &FileSystemProtocol, &Vol); |
Vol->OpenVolume (Vol, &CurDir); |
char FileName[1024]; |
char *OsKernelBuffer; |
int i; |
int defaultLoad; |
int imageLoad; |
UINTN Size; |
StrCpy(FileName,DevicePathToStr(LoadedImage->FilePath)); |
95,10 → 97,8 |
} |
while(LoadOptions[i]==L' ') if(LoadOptions[i++]==0) break; |
if(LoadOptions[i++]==0){ |
if(LoadOptions[i++]==0) |
StrCat(FileName,L"\\image.bin"); |
defaultLoad=1; |
} |
else{ |
CHAR16 buf[1024]; |
buf[0]='\\'; |
108,84 → 108,28 |
buf[j+1]=LoadOptions[i+j]; |
buf[j+1]=0; |
StrCat(FileName,buf); |
defaultLoad=0; |
} |
//Print(L"%s\n",FileName); |
imageLoad=1; |
#ifdef IMAGE_LINKED |
if(defaultLoad) { |
Print(L"Using Linked Image\n"); |
imageLoad=0; |
EFI_STATUS stat; |
stat=CurDir->Open(CurDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); |
if(EFI_ERROR(stat)){ |
Print(L"Error Opening Image %s\n",FileName); |
return 0; |
} |
#endif |
Size = 0x00400000; |
BS->AllocatePool(EfiLoaderData, Size, &OsKernelBuffer); |
FileHandle->Read(FileHandle, &Size, OsKernelBuffer); |
FileHandle->Close(FileHandle); |
char * HOS; |
if(imageLoad) |
{ |
Size = 0x00400000; |
if(Size<1) return 0; |
Vol->OpenVolume (Vol, &CurDir); |
EFI_STATUS stat; |
stat=CurDir->Open(CurDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); |
if(EFI_ERROR(stat)){ |
Print(L"Error Opening Image %s\n",FileName); |
return 0; |
} |
BS->AllocatePool(EfiLoaderData, Size, &OsKernelBuffer); |
FileHandle->Read(FileHandle, &Size, OsKernelBuffer); |
FileHandle->Close(FileHandle); |
HOS = OsKernelBuffer; |
if(Size<1) return 0; |
} |
#ifdef IMAGE_LINKED |
else { |
HOS = HOSimage; |
Size = HOSimagesize; |
Print(L"Image start %llX\n",(long long)HOS); |
Print(L"Image size %llX\n",(long long)Size); |
Print(L"Image &size %llX\n",(long long)&Size); |
} |
#endif |
char * HOS = OsKernelBuffer; |
int HOSSize = Size; |
rArg rSAL; |
rArg rPAL; |
//Setup AP's wake up address |
LibSalProc(0x01000000,2,0x4400200,0,0,0,0,0,&rSAL); |
//Get System Frequency |
UINT64 sys_freq; |
LibSalProc(0x01000012,0,0,0,0,0,0,0,&rSAL); |
sys_freq=rSAL.p1; |
UINT64 freq_scale; |
//Get CPU Frequency to System Frequency ratio |
LibPalProc(14,0,0,0,&rPAL); |
freq_scale=rPAL.p1; |
UINT64 sapic; |
LibGetSalIpiBlock(&sapic); |
Print (L"SAPIC:%X\n", sapic); |
//bootinfo->sapic=sapic; |
int wakeup_intno; |
wakeup_intno=0xf0; |
Print (L"WAKEUP INTNO:%X\n", wakeup_intno); |
//bootinfo->wakeup_intno=wakeup_intno; |
{ |
UINTN cookie; |
void *p=(void *)KERNEL_LOAD_ADDRESS; |
223,10 → 167,6 |
for(a=0;a<HOSSize;a++){ |
((char *)(0x4400000))[a]=HOS[a]; |
} |
bootinfo->sapic=(unsigned long *)sapic; |
bootinfo->wakeup_intno=wakeup_intno; |
bootinfo->sys_freq=sys_freq; |
bootinfo->freq_scale=freq_scale; |
//Run Kernel |
asm volatile( |
237,6 → 177,8 |
); |
//Not reached |
while(1){ |
((volatile int *)(0x80000000000b8000))[0]++; |
} |
return EFI_SUCCESS; |
} |
/branches/sparc/boot/arch/ia64/loader/boot.S |
---|
34,7 → 34,6 |
.global start |
start: |
mov ar.rsc = r0 |
# movl r8 = (VRN_KERNEL << VRN_SHIFT) ;; |
movl r1 = 0x4400000 |
58,22 → 57,6 |
mov b1 = r18 ;; |
br.call.sptk.many b0 = b1 |
.align 512 |
ap_start: |
ap_loop: |
movl r18=0x4405000;; |
mov b1 = r18 ;; |
br.call.sptk.many b0 = b1;; |
.align 1024 |
.align 4096 |
.global binfo |
binfo: |
.bss #on this line is ".bss", it cannot be seen in my mcedit :-( |
/branches/sparc/boot/arch/ia64/loader/asm.S |
---|
37,5 → 37,7 |
alloc loc0 = ar.pfs, 1, 1, 0, 0 |
movl r8 = 0x4404000;; |
mov b1 = r8 ;; |
mov r1 = in0; #Save bootinfo prt |
mov r1 = in0; |
br.call.sptk.many b0 = b1;; |
.global ofw |
ofw: |
/branches/sparc/boot/arch/ia64/loader/main.c |
---|
34,7 → 34,7 |
#include <align.h> |
#include <balloc.h> |
extern bootinfo_t binfo; |
bootinfo_t bootinfo; |
component_t components[COMPONENTS]; |
char *release = RELEASE; |
69,8 → 69,6 |
int ii; |
bootinfo_t *bootinfo=&binfo; |
//for(ii=0;ii<KERNEL_SIZE;ii++) ((char *)(0x100000))[ii] = ((char *)KERNEL_START)[ii+1]; |
94,18 → 92,19 |
components[i].name, components[i].size); |
bootinfo->taskmap.count = 0; |
bootinfo.taskmap.count = 0; |
for (i = 0; i < COMPONENTS; i++) { |
if (i > 0) { |
bootinfo->taskmap.tasks[bootinfo->taskmap.count].addr = components[i].start; |
bootinfo->taskmap.tasks[bootinfo->taskmap.count].size = components[i].size; |
bootinfo->taskmap.count++; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = components[i].start; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = components[i].size; |
bootinfo.taskmap.count++; |
} |
} |
jump_to_kernel(bootinfo); |
jump_to_kernel(&bootinfo); |
} |
/branches/sparc/boot/arch/ia64/loader/main.h |
---|
29,14 → 29,29 |
#ifndef BOOT_ia64_MAIN_H_ |
#define BOOT_ia64_MAIN_H_ |
#include <ofw.h> |
#include <ofw_tree.h> |
#include <types.h> |
#include <../../../../kernel/arch/ia64/include/bootinfo.h> |
#define CONFIG_INIT_TASKS 32 |
typedef struct { |
void *addr; |
size_t size; |
} init_task_t; |
typedef struct { |
count_t count; |
init_task_t tasks[CONFIG_INIT_TASKS]; |
} init_t; |
typedef struct { |
init_t taskmap; |
} bootinfo_t; |
extern bootinfo_t bootinfo; |
extern void start(void); |
extern void bootstrap(void); |
/branches/sparc/boot/arch/arm32/loader/Makefile |
---|
145,7 → 145,7 |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
/branches/sparc/boot/arch/ppc32/loader/Makefile |
---|
140,7 → 140,7 |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
/branches/sparc/boot/arch/amd64/Makefile.inc |
---|
80,7 → 80,7 |
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
endif |
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img |
rm arch/$(ARCH)/iso/boot/initrd.fs |
/branches/sparc/boot/arch/mips32/loader/Makefile |
---|
145,7 → 145,7 |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
/branches/sparc/boot/arch/ia32/Makefile.inc |
---|
79,7 → 79,7 |
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs |
endif |
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img |
rm arch/$(ARCH)/iso/boot/initrd.fs |
/branches/sparc/usiii.simics |
---|
9,9 → 9,9 |
if not defined mac_address {$mac_address = "10:10:10:10:10:24"} |
if not defined disk_size {$disk_size = 2128486400} |
if not defined rtc_time {$rtc_time = "2002-06-02 17:00:00 UTC"} |
if not defined num_cpus {$num_cpus = 3} |
if not defined num_cpus {$num_cpus = 2} |
if not defined megs_per_cpu {$megs_per_cpu = 256} |
if not defined cpu_class {$cpu_class = "ultrasparc-iv"} |
if not defined cpu_class {$cpu_class = "ultrasparc-iii"} |
### |
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
103,11 → 103,13 |
} |
do { |
memset(buff, 0, sizeof(buff)); |
bytes = read(fd, buff, blen); |
if (bytes > 0) { |
count += bytes; |
buff[bytes] = '\0'; |
printf("%s", buff); |
if (bytes < blen) |
buff[bytes] = '\0'; |
printf(buff); |
reads++; |
} |
} while (bytes > 0); |
/branches/sparc/uspace/app/tester/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/app/trace/trace.c |
---|
516,7 → 516,7 |
int rc; |
/* Spawn a program loader */ |
ldr = loader_spawn(path); |
ldr = loader_spawn(); |
if (ldr == NULL) |
return 0; |
/branches/sparc/uspace/app/trace/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/app/tetris/Makefile |
---|
1,5 → 1,3 |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/app/klog/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/kbd/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/fb/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/console/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/loader/main.c |
---|
247,7 → 247,7 |
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
// printf("Run statically linked program\n"); |
// printf("entry point: 0x%lx\n", prog_info.entry); |
// printf("entry point: 0x%llx\n", prog_info.entry); |
is_dyn_linked = false; |
ipc_answer_0(rid, EOK); |
return 0; |
285,7 → 285,7 |
if (is_dyn_linked == true) { |
/* Dynamically linked program */ |
printf("run dynamic linker\n"); |
printf("entry point: 0x%lx\n", interp_info.entry); |
printf("entry point: 0x%llx\n", interp_info.entry); |
close_console(); |
ipc_answer_0(rid, EOK); |
319,8 → 319,6 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
exit(0); |
case LOADER_GET_TASKID: |
loader_get_taskid(callid, &call); |
continue; |
/branches/sparc/uspace/srv/loader/Makefile |
---|
27,6 → 27,7 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
/branches/sparc/uspace/srv/loader/arch/ppc32/ppc32.s |
---|
36,5 → 36,5 |
# Jump to a program entry point |
program_run: |
mtctr %r3 |
mr %r6, %r4 # Pass pcb to the entry point in %r6 |
mr %r3, %r4 # Pass pcb to the entry point in %r3 |
bctr |
/branches/sparc/uspace/srv/vfs/Makefile |
---|
30,8 → 30,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
64,8 → 64,6 |
*/ |
static tmpfs_dentry_t *root; |
#define TMPFS_DEV 0 /**< Dummy device handle for TMPFS */ |
/* |
* Implementation of the libfs interface. |
*/ |
74,7 → 72,7 |
static void *tmpfs_match(void *, const char *); |
static void *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(void *); |
static void *tmpfs_create_node(dev_handle_t, int); |
static void *tmpfs_create_node(int); |
static bool tmpfs_link_node(void *, void *, const char *); |
static int tmpfs_unlink_node(void *, void *); |
static int tmpfs_destroy_node(void *); |
230,7 → 228,7 |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
return false; |
root = (tmpfs_dentry_t *) tmpfs_create_node(TMPFS_DEV, L_DIRECTORY); |
root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return false; |
284,7 → 282,7 |
/* nothing to do */ |
} |
void *tmpfs_create_node(dev_handle_t dev_handle, int lflag) |
void *tmpfs_create_node(int lflag) |
{ |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
/branches/sparc/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
38,12 → 38,17 |
#include "tmpfs.h" |
#include "../../vfs/vfs.h" |
#include <ipc/ipc.h> |
#include <async.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
#include <sys/types.h> |
#include <as.h> |
#include <libblock.h> |
#include <libfs.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <sys/mman.h> |
#include <byteorder.h> |
#define TMPFS_BLOCK_SIZE 1024 |
54,8 → 59,8 |
} __attribute__((packed)); |
static bool |
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos, |
tmpfs_dentry_t *parent) |
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen, |
off_t *pos, tmpfs_dentry_t *parent) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
65,8 → 70,8 |
tmpfs_dentry_t *node; |
uint32_t size; |
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry), |
TMPFS_BLOCK_SIZE) != EOK) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE)) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
79,14 → 84,14 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE); |
node = (tmpfs_dentry_t *) ops->create(L_FILE); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
100,8 → 105,8 |
} |
free(fname); |
if (block_read(dev, bufpos, buflen, pos, &size, |
sizeof(size), TMPFS_BLOCK_SIZE) != EOK) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
&size, sizeof(size), TMPFS_BLOCK_SIZE)) |
return false; |
size = uint32_t_le2host(size); |
111,8 → 116,8 |
return false; |
node->size = size; |
if (block_read(dev, bufpos, buflen, pos, node->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
node->data, size, TMPFS_BLOCK_SIZE)) |
return false; |
break; |
121,14 → 126,14 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY); |
node = (tmpfs_dentry_t *) ops->create(L_DIRECTORY); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
142,8 → 147,8 |
} |
free(fname); |
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos, |
node)) |
if (!tmpfs_restore_recursion(phone, block, bufpos, |
buflen, pos, node)) |
return false; |
break; |
158,19 → 163,32 |
bool tmpfs_restore(dev_handle_t dev) |
{ |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
int rc; |
rc = block_init(dev, TMPFS_BLOCK_SIZE); |
if (rc != EOK) |
return false; |
void *block = mmap(NULL, TMPFS_BLOCK_SIZE, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (block == NULL) |
return false; |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev); |
if (phone < 0) { |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
if (ipc_share_out_start(phone, block, AS_AREA_READ | AS_AREA_WRITE) != |
EOK) |
goto error; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = 0; |
char tag[6]; |
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE) != EOK) |
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE)) |
goto error; |
tag[5] = 0; |
177,15 → 195,17 |
if (strcmp(tag, "TMPFS") != 0) |
goto error; |
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, |
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos, |
ops->root_get(dev))) |
goto error; |
block_fini(dev); |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
return true; |
error: |
block_fini(dev); |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
/branches/sparc/uspace/srv/fs/tmpfs/Makefile |
---|
29,20 → 29,14 |
## Setup toolchain |
# |
include ../../../Makefile.config |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
## Sources |
# |
/branches/sparc/uspace/srv/fs/fat/fat_fat.c |
---|
File deleted |
/branches/sparc/uspace/srv/fs/fat/fat_dentry.c |
---|
File deleted |
/branches/sparc/uspace/srv/fs/fat/fat_dentry.h |
---|
File deleted |
/branches/sparc/uspace/srv/fs/fat/fat_fat.h |
---|
File deleted |
/branches/sparc/uspace/srv/fs/fat/fat_ops.c |
---|
36,11 → 36,8 |
*/ |
#include "fat.h" |
#include "fat_dentry.h" |
#include "fat_fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <libblock.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
53,8 → 50,10 |
#include <assert.h> |
#include <futex.h> |
#include <sys/mman.h> |
#include <align.h> |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
61,6 → 60,216 |
/** List of cached free FAT nodes. */ |
static LIST_INITIALIZE(ffn_head); |
#define FAT_NAME_LEN 8 |
#define FAT_EXT_LEN 3 |
#define FAT_PAD ' ' |
#define FAT_DENTRY_UNUSED 0x00 |
#define FAT_DENTRY_E5_ESC 0x05 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
{ |
int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) |
break; |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->name[i]; |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->ext[i]; |
} |
*buf = '\0'; |
} |
static int dev_phone = -1; /* FIXME */ |
static void *dev_buffer = NULL; /* FIXME */ |
/* TODO move somewhere else */ |
typedef struct { |
void *data; |
size_t size; |
} block_t; |
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs) |
{ |
/* FIXME */ |
block_t *b; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = offset * bs; |
assert(dev_phone != -1); |
assert(dev_buffer); |
b = malloc(sizeof(block_t)); |
if (!b) |
return NULL; |
b->data = malloc(bs); |
if (!b->data) { |
free(b); |
return NULL; |
} |
b->size = bs; |
if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos, |
b->data, bs, bs)) { |
free(b->data); |
free(b); |
return NULL; |
} |
return b; |
} |
static void block_put(block_t *block) |
{ |
/* FIXME */ |
free(block->data); |
free(block); |
} |
#define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
#define FAT_CLST_RES0 0x0000 |
#define FAT_CLST_RES1 0x0001 |
#define FAT_CLST_FIRST 0x0002 |
#define FAT_CLST_BAD 0xfff7 |
#define FAT_CLST_LAST1 0xfff8 |
#define FAT_CLST_LAST8 0xffff |
/* internally used to mark root directory's parent */ |
#define FAT_CLST_ROOTPAR FAT_CLST_RES0 |
/* internally used to mark root directory */ |
#define FAT_CLST_ROOT FAT_CLST_RES1 |
#define fat_block_get(np, off) \ |
_fat_block_get((np)->idx->dev_handle, (np)->firstc, (off)) |
static block_t * |
_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned fatcnt; |
unsigned rde; |
unsigned rds; /* root directory size */ |
unsigned sf; |
unsigned ssa; /* size of the system area */ |
unsigned clusters; |
fat_cluster_t clst = firstc; |
unsigned i; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
fatcnt = FAT_BS(bb)->fatcnt; |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); |
block_put(bb); |
rds = (sizeof(fat_dentry_t) * rde) / bps; |
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
ssa = rscnt + fatcnt * sf + rds; |
if (firstc == FAT_CLST_ROOT) { |
/* root directory special case */ |
assert(offset < rds); |
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps); |
return b; |
} |
clusters = offset / spc; |
for (i = 0; i < clusters; i++) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
assert(clst < FAT_CLST_LAST1); |
block_put(b); |
} |
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + |
offset % spc, bps); |
return b; |
} |
/** Return number of blocks allocated to a file. |
* |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster of the file. |
* |
* @return Number of blocks allocated to the file. |
*/ |
static uint16_t |
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned clusters = 0; |
fat_cluster_t clst = firstc; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
block_put(bb); |
if (firstc == FAT_CLST_RES0) { |
/* No space allocated to the file. */ |
return 0; |
} |
while (clst < FAT_CLST_LAST1) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
block_put(b); |
clusters++; |
} |
return clusters * spc; |
} |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
73,69 → 282,52 |
node->dirty = false; |
} |
static void fat_node_sync(fat_node_t *node) |
static uint16_t fat_bps_get(dev_handle_t dev_handle) |
{ |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
block_t *bb; |
uint16_t bps; |
unsigned dps; |
assert(node->dirty); |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
assert(bb != NULL); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
block_put(bb); |
bs = block_bb_get(node->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc, |
(node->idx->pdi * sizeof(fat_dentry_t)) / bps); |
return bps; |
} |
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); |
typedef enum { |
FAT_DENTRY_SKIP, |
FAT_DENTRY_LAST, |
FAT_DENTRY_VALID |
} fat_dentry_clsf_t; |
d->firstc = host2uint16_t_le(node->firstc); |
if (node->type == FAT_FILE) |
d->size = host2uint32_t_le(node->size); |
/* TODO: update other fields? (e.g time fields, attr field) */ |
b->dirty = true; /* need to sync block */ |
block_put(b); |
static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d) |
{ |
if (d->attr & FAT_ATTR_VOLLABEL) { |
/* volume label entry */ |
return FAT_DENTRY_SKIP; |
} |
if (d->name[0] == FAT_DENTRY_ERASED) { |
/* not-currently-used entry */ |
return FAT_DENTRY_SKIP; |
} |
if (d->name[0] == FAT_DENTRY_UNUSED) { |
/* never used entry */ |
return FAT_DENTRY_LAST; |
} |
if (d->name[0] == FAT_DENTRY_DOT) { |
/* |
* Most likely '.' or '..'. |
* It cannot occur in a regular file name. |
*/ |
return FAT_DENTRY_SKIP; |
} |
return FAT_DENTRY_VALID; |
} |
static fat_node_t *fat_node_get_new(void) |
static void fat_node_sync(fat_node_t *node) |
{ |
fat_node_t *nodep; |
futex_down(&ffn_futex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
fat_idx_t *idxp_tmp; |
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); |
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) { |
futex_up(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
futex_up(&ffn_futex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) |
return NULL; |
} |
fat_node_initialize(nodep); |
return nodep; |
/* TODO */ |
} |
/** Internal version of fat_node_get(). |
145,11 → 337,9 |
static void *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
fat_node_t *nodep = NULL; |
unsigned bps; |
unsigned spc; |
unsigned dps; |
if (idxp->nodep) { |
170,17 → 360,40 |
assert(idxp->pfc); |
nodep = fat_node_get_new(); |
if (!nodep) |
return NULL; |
futex_down(&ffn_futex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
fat_idx_t *idxp_tmp; |
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); |
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) { |
futex_up(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
futex_up(&ffn_futex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) |
return NULL; |
} |
fat_node_initialize(nodep); |
bs = block_bb_get(idxp->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bps = fat_bps_get(idxp->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc, |
b = _fat_block_get(idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps); |
assert(b); |
197,7 → 410,7 |
* defined for the directory entry type. We must determine the |
* size of the directory by walking the FAT. |
*/ |
nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle, |
nodep->size = bps * _fat_blcks_get(idxp->dev_handle, |
uint16_t_le2host(d->firstc)); |
} else { |
nodep->type = FAT_FILE; |
244,7 → 457,7 |
futex_up(&nodep->lock); |
} |
static void *fat_create(dev_handle_t dev_handle, int flags) |
static void *fat_create(int flags) |
{ |
return NULL; /* not supported at the moment */ |
} |
266,7 → 479,6 |
static void *fat_match(void *prnt, const char *component) |
{ |
fat_bs_t *bs; |
fat_node_t *parentp = (fat_node_t *)prnt; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
unsigned i, j; |
277,13 → 489,17 |
block_t *b; |
futex_down(&parentp->idx->lock); |
bs = block_bb_get(parentp->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
bps = fat_bps_get(parentp->idx->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
blocks = parentp->size / bps; |
blocks = parentp->size / bps + (parentp->size % bps != 0); |
for (i = 0; i < blocks; i++) { |
b = fat_block_get(bs, parentp, i); |
for (j = 0; j < dps; j++) { |
unsigned dentries; |
b = fat_block_get(parentp, i); |
dentries = (i == blocks - 1) ? |
parentp->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
326,7 → 542,6 |
} |
block_put(b); |
} |
futex_up(&parentp->idx->lock); |
return NULL; |
} |
351,7 → 566,6 |
static bool fat_has_children(void *node) |
{ |
fat_bs_t *bs; |
fat_node_t *nodep = (fat_node_t *)node; |
unsigned bps; |
unsigned dps; |
361,19 → 575,22 |
if (nodep->type != FAT_DIRECTORY) |
return false; |
futex_down(&nodep->idx->lock); |
bs = block_bb_get(nodep->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
bps = fat_bps_get(nodep->idx->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
blocks = nodep->size / bps; |
blocks = nodep->size / bps + (nodep->size % bps != 0); |
for (i = 0; i < blocks; i++) { |
unsigned dentries; |
fat_dentry_t *d; |
b = fat_block_get(bs, nodep, i); |
for (j = 0; j < dps; j++) { |
b = fat_block_get(nodep, i); |
dentries = (i == blocks - 1) ? |
nodep->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
441,50 → 658,57 |
void fat_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fat_bs_t *bs; |
block_t *bb; |
uint16_t bps; |
uint16_t rde; |
int rc; |
/* initialize libblock */ |
rc = block_init(dev_handle, BS_SIZE); |
if (rc != EOK) { |
ipc_answer_0(rid, rc); |
/* |
* For now, we don't bother to remember dev_handle, dev_phone or |
* dev_buffer in some data structure. We use global variables because we |
* know there will be at most one mount on this file system. |
* Of course, this is a huge TODO item. |
*/ |
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!dev_buffer) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* prepare the boot block */ |
rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE); |
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
if (dev_phone < 0) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, dev_phone); |
return; |
} |
rc = ipc_share_out_start(dev_phone, dev_buffer, |
AS_AREA_READ | AS_AREA_WRITE); |
if (rc != EOK) { |
block_fini(dev_handle); |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
/* get the buffer with the boot sector */ |
bs = block_bb_get(dev_handle); |
/* Read the number of root directory entries. */ |
bps = uint16_t_le2host(bs->bps); |
rde = uint16_t_le2host(bs->root_ent_max); |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
block_put(bb); |
if (bps != BS_SIZE) { |
block_fini(dev_handle); |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* Initialize the block cache */ |
rc = block_cache_init(dev_handle, bps, 0 /* XXX */); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
rc = fat_idx_init_by_dev_handle(dev_handle); |
if (rc != EOK) { |
block_fini(dev_handle); |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
492,7 → 716,7 |
/* Initialize the root node. */ |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
block_fini(dev_handle); |
munmap(dev_buffer, BS_SIZE); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
501,7 → 725,7 |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
block_fini(dev_handle); |
munmap(dev_buffer, BS_SIZE); |
free(rootp); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
539,8 → 763,7 |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
uint16_t bps; |
uint16_t bps = fat_bps_get(dev_handle); |
size_t bytes; |
block_t *b; |
558,9 → 781,6 |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
if (nodep->type == FAT_FILE) { |
/* |
* Our strategy for regular file reads is to read one block at |
567,18 → 787,11 |
* most and make use of the possibility to return less data than |
* requested. This keeps the code very simple. |
*/ |
if (pos >= nodep->size) { |
/* reading beyond the EOF */ |
bytes = 0; |
(void) ipc_data_read_finalize(callid, NULL, 0); |
} else { |
bytes = min(len, bps - pos % bps); |
bytes = min(bytes, nodep->size - pos); |
b = fat_block_get(bs, nodep, pos / bps); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} |
bytes = min(len, bps - pos % bps); |
b = fat_block_get(nodep, pos / bps); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} else { |
unsigned bnum; |
off_t spos = pos; |
599,7 → 812,7 |
while (bnum < nodep->size / bps) { |
off_t o; |
b = fat_block_get(bs, nodep, bnum); |
b = fat_block_get(nodep, bnum); |
for (o = pos % (bps / sizeof(fat_dentry_t)); |
o < bps / sizeof(fat_dentry_t); |
o++, pos++) { |
634,166 → 847,6 |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
void fat_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
size_t bytes; |
block_t *b; |
uint16_t bps; |
unsigned spc; |
unsigned bpc; /* bytes per cluster */ |
off_t boundary; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
fat_node_put(nodep); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
/* |
* In all scenarios, we will attempt to write out only one block worth |
* of data at maximum. There might be some more efficient approaches, |
* but this one greatly simplifies fat_write(). Note that we can afford |
* to do this because the client must be ready to handle the return |
* value signalizing a smaller number of bytes written. |
*/ |
bytes = min(len, bps - pos % bps); |
boundary = ROUND_UP(nodep->size, bpc); |
if (pos < boundary) { |
/* |
* This is the easier case - we are either overwriting already |
* existing contents or writing behind the EOF, but still within |
* the limits of the last cluster. The node size may grow to the |
* next block size boundary. |
*/ |
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); |
b = fat_block_get(bs, nodep, pos / bps); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
if (pos + bytes > nodep->size) { |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
} |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
return; |
} else { |
/* |
* This is the more difficult case. We must allocate new |
* clusters for the node and zero them out. |
*/ |
int status; |
unsigned nclsts; |
fat_cluster_t mcl, lcl; |
nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; |
/* create an independent chain of nclsts clusters in all FATs */ |
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); |
if (status != EOK) { |
/* could not allocate a chain of nclsts clusters */ |
fat_node_put(nodep); |
ipc_answer_0(callid, status); |
ipc_answer_0(rid, status); |
return; |
} |
/* zero fill any gaps */ |
fat_fill_gap(bs, nodep, mcl, pos); |
b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
/* |
* Append the cluster chain starting in mcl to the end of the |
* node's cluster chain. |
*/ |
fat_append_clusters(bs, nodep, mcl); |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
return; |
} |
} |
void fat_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
size_t size = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
uint16_t bps; |
uint8_t spc; |
unsigned bpc; /* bytes per cluster */ |
int rc; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
if (nodep->size == size) { |
rc = EOK; |
} else if (nodep->size < size) { |
/* |
* The standard says we have the freedom to grow the node. |
* For now, we simply return an error. |
*/ |
rc = EINVAL; |
} else if (ROUND_UP(nodep->size, bpc) == ROUND_UP(size, bpc)) { |
/* |
* The node will be shrunk, but no clusters will be deallocated. |
*/ |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} else { |
/* |
* The node will be shrunk, clusters will be deallocated. |
*/ |
if (size == 0) { |
fat_chop_clusters(bs, nodep, FAT_CLST_RES0); |
} else { |
fat_cluster_t lastc; |
(void) fat_cluster_walk(bs, dev_handle, nodep->firstc, |
&lastc, (size - 1) / bpc); |
fat_chop_clusters(bs, nodep, lastc); |
} |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} |
fat_node_put(nodep); |
ipc_answer_0(rid, rc); |
return; |
} |
/** |
* @} |
*/ |
/branches/sparc/uspace/srv/fs/fat/fat.h |
---|
33,7 → 33,6 |
#ifndef FAT_FAT_H_ |
#define FAT_FAT_H_ |
#include "fat_fat.h" |
#include <ipc/ipc.h> |
#include <libfs.h> |
#include <atomic.h> |
45,12 → 44,7 |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
typedef struct fat_bs { |
typedef struct { |
uint8_t ji[3]; /**< Jump instruction. */ |
uint8_t oem_name[8]; |
/* BIOS Parameter Block */ |
121,6 → 115,34 |
}; |
} __attribute__ ((packed)) fat_bs_t; |
#define FAT_ATTR_RDONLY (1 << 0) |
#define FAT_ATTR_VOLLABEL (1 << 3) |
#define FAT_ATTR_SUBDIR (1 << 4) |
typedef struct { |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t reserved; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
uint16_t adate; |
union { |
uint16_t eaidx; /* FAT12/FAT16 */ |
uint16_t firstc_hi; /* FAT32 */ |
}; |
uint16_t mtime; |
uint16_t mdate; |
union { |
uint16_t firstc; /* FAT12/FAT16 */ |
uint16_t firstc_lo; /* FAT32 */ |
}; |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
typedef uint16_t fat_cluster_t; |
typedef enum { |
FAT_INVALID, |
FAT_DIRECTORY, |
201,8 → 223,6 |
extern void fat_mount(ipc_callid_t, ipc_call_t *); |
extern void fat_lookup(ipc_callid_t, ipc_call_t *); |
extern void fat_read(ipc_callid_t, ipc_call_t *); |
extern void fat_write(ipc_callid_t, ipc_call_t *); |
extern void fat_truncate(ipc_callid_t, ipc_call_t *); |
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned); |
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t); |
/branches/sparc/uspace/srv/fs/fat/fat.c |
---|
110,12 → 110,6 |
case VFS_READ: |
fat_read(callid, &call); |
break; |
case VFS_WRITE: |
fat_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
fat_truncate(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
/branches/sparc/uspace/srv/fs/fat/Makefile |
---|
29,20 → 29,14 |
## Setup toolchain |
# |
include ../../../Makefile.config |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
## Sources |
# |
51,9 → 45,7 |
SOURCES = \ |
fat.c \ |
fat_ops.c \ |
fat_idx.c \ |
fat_dentry.c \ |
fat_fat.c |
fat_idx.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
/branches/sparc/uspace/srv/fs/fat/fat_idx.c |
---|
338,52 → 338,6 |
futex_up(&unused_futex); |
} |
static fat_idx_t *fat_idx_get_new_core(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
if (!fidx) |
return NULL; |
if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
return NULL; |
} |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = FAT_CLST_RES0; /* no parent yet */ |
fidx->pdi = 0; |
fidx->nodep = NULL; |
return fidx; |
} |
fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
futex_down(&used_futex); |
fidx = fat_idx_get_new_core(dev_handle); |
if (!fidx) { |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
[UIH_INDEX_KEY] = fidx->index, |
}; |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
return fidx; |
} |
fat_idx_t * |
fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
{ |
400,11 → 354,16 |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
} else { |
fidx = fat_idx_get_new_core(dev_handle); |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
if (!fidx) { |
futex_up(&used_futex); |
return NULL; |
} |
if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
411,8 → 370,13 |
[UIH_INDEX_KEY] = fidx->index, |
}; |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = pfc; |
fidx->pdi = pdi; |
fidx->nodep = NULL; |
hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
/branches/sparc/uspace/srv/rd/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/ns/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/devmap/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/srv/pci/Makefile |
---|
29,8 → 29,6 |
## Setup toolchain |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
/branches/sparc/uspace/lib/libblock/libblock.h |
---|
File deleted |
/branches/sparc/uspace/lib/libblock/Makefile |
---|
File deleted |
/branches/sparc/uspace/lib/libblock/libblock.c |
---|
File deleted |
/branches/sparc/uspace/lib/libfs/Makefile |
---|
30,8 → 30,6 |
## Common compiler flags |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
/branches/sparc/uspace/lib/libfs/libfs.c |
---|
36,6 → 36,7 |
#include "libfs.h" |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/rd/rd.h" |
#include <errno.h> |
#include <async.h> |
#include <ipc/ipc.h> |
191,7 → 192,7 |
} |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(dev_handle, lflag); |
nodep = ops->create(lflag); |
else |
nodep = ops->node_get(dev_handle, |
index); |
262,7 → 263,7 |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(dev_handle, lflag); |
nodep = ops->create(lflag); |
else |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
330,5 → 331,62 |
ops->node_put(tmp); |
} |
/** Read data from a block device. |
* |
* @param phone Phone to be used to communicate with the device. |
* @param buffer Communication buffer shared with the device. |
* @param bufpos Pointer to the first unread valid offset within the |
* communication buffer. |
* @param buflen Pointer to the number of unread bytes that are ready in |
* the communication buffer. |
* @param pos Device position to be read. |
* @param dst Destination buffer. |
* @param size Size of the destination buffer. |
* @param block_size Block size to be used for the transfer. |
* |
* @return True on success, false on failure. |
*/ |
bool libfs_blockread(int phone, void *buffer, off_t *bufpos, size_t *buflen, |
off_t *pos, void *dst, size_t size, size_t block_size) |
{ |
off_t offset = 0; |
size_t left = size; |
while (left > 0) { |
size_t rd; |
if (*bufpos + left < *buflen) |
rd = left; |
else |
rd = *buflen - *bufpos; |
if (rd > 0) { |
/* |
* Copy the contents of the communication buffer to the |
* destination buffer. |
*/ |
memcpy(dst + offset, buffer + *bufpos, rd); |
offset += rd; |
*bufpos += rd; |
*pos += rd; |
left -= rd; |
} |
if (*bufpos == *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(phone, RD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return false; |
*bufpos = 0; |
*buflen = block_size; |
} |
} |
return true; |
} |
/** @} |
*/ |
/branches/sparc/uspace/lib/libfs/libfs.h |
---|
45,7 → 45,7 |
void * (* match)(void *, const char *); |
void * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(void *); |
void * (* create)(dev_handle_t, int); |
void * (* create)(int); |
int (* destroy)(void *); |
bool (* link)(void *, void *, const char *); |
int (* unlink)(void *, void *); |
69,6 → 69,9 |
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/** @} |
/branches/sparc/uspace/lib/softfloat/Makefile |
---|
29,8 → 29,6 |
## Common compiler flags |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
/branches/sparc/uspace/lib/softint/Makefile |
---|
29,8 → 29,6 |
## Common compiler flags |
# |
include ../../Makefile.config |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
/branches/sparc/uspace/lib/libc/include/loader/loader.h |
---|
44,7 → 44,7 |
int phone_id; |
} loader_t; |
extern loader_t *loader_spawn(char *name); |
extern loader_t *loader_spawn(void); |
extern int loader_get_task_id(loader_t *, task_id_t *); |
extern int loader_set_pathname(loader_t *, const char *); |
extern int loader_set_args(loader_t *, char *const []); |
/branches/sparc/uspace/lib/libc/include/byteorder.h |
---|
52,14 → 52,6 |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
70,14 → 62,6 |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
/branches/sparc/uspace/lib/libc/include/errno.h |
---|
46,7 → 46,6 |
#define EBADF (-262) |
#define ERANGE (-263) |
#define EXDEV (-264) |
#define EIO (-265) |
#endif |
/branches/sparc/uspace/lib/libc/include/align.h |
---|
35,28 → 35,21 |
#ifndef LIBC_ALIGN_H_ |
#define LIBC_ALIGN_H_ |
/** Align to the nearest lower address which is a power of two. |
/** Align to the nearest lower address. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1)) |
/** Align to the nearest higher address which is a power of two. |
/** Align to the nearest higher address. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(s, a) ((long)((s) + ((a) - 1)) & ~((long) (a) - 1)) |
/** Round up to the nearest higher boundary. |
* |
* @param n Number to be aligned. |
* @param b Boundary, arbitrary unsigned number. |
*/ |
#define ROUND_UP(n, b) (((n) / (b) + ((n) % (b) != 0)) * (b)) |
#endif |
/** @} |
/branches/sparc/uspace/lib/libc/generic/task.c |
---|
64,7 → 64,7 |
int rc; |
/* Spawn a program loader. */ |
ldr = loader_spawn(path); |
ldr = loader_spawn(); |
if (ldr == NULL) |
return 0; |
/branches/sparc/uspace/lib/libc/generic/loader.c |
---|
46,11 → 46,10 |
/** Connect to a new program loader. |
* |
* Spawns a new program loader task and returns the connection structure. |
* @param name Symbolic name to set on the newly created task. |
* @return Pointer to the loader connection structure (should be |
* de-allocated using free() after use). |
*/ |
loader_t *loader_spawn(char *name) |
loader_t *loader_spawn(void) |
{ |
int phone_id, rc; |
loader_t *ldr; |
58,8 → 57,7 |
/* |
* Ask kernel to spawn a new loader task. |
*/ |
rc = __SYSCALL3(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id, |
(sysarg_t) name, strlen(name)); |
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id); |
if (rc != 0) |
return NULL; |
/branches/sparc/uspace/lib/libc/generic/thread.c |
---|
108,8 → 108,8 |
uarg->uspace_thread_arg = arg; |
uarg->uspace_uarg = uarg; |
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) strlen(name), (sysarg_t) tid); |
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) tid); |
if (rc) { |
/* |
/branches/sparc/uspace/lib/libc/Makefile |
---|
29,8 → 29,6 |
## Common compiler flags |
# |
include ../../Makefile.config |
LIBC_PREFIX = $(shell pwd) |
SOFTINT_PREFIX = ../softint |
CONSOLE_PREFIX = ../../srv/console |
/branches/sparc/uspace/lib/libc/arch/ppc32/src/entry.s |
---|
34,12 → 34,11 |
## User-space task entry point |
# |
# r6 contains the PCB pointer |
# r3 contains the PCB pointer |
# |
__entry: |
# Pass the PCB pointer to __main() as the first argument. |
# The first argument is passed in r3. |
mr %r3, %r6 |
# Since the first argument is passed in r3, no operation is needed. |
bl __main |
bl __exit |
/branches/sparc/uspace/Makefile |
---|
34,7 → 34,6 |
DIRS = \ |
lib/libc \ |
lib/libfs \ |
lib/libblock \ |
lib/softint \ |
lib/softfloat \ |
srv/ns \ |
92,7 → 91,7 |
-rm Makefile.config |
$(CLEANS): |
-$(MAKE) -C $(basename $@) clean |
-$(MAKE) -C $(basename $@) clean ARCH=$(ARCH) |
$(BUILDS): |
$(MAKE) -C $(basename $@) all |
$(MAKE) -C $(basename $@) all ARCH=$(ARCH) COMPILER=$(COMPILER) |
/branches/sparc/tools/mkfat.py |
---|
34,275 → 34,7 |
import os |
import random |
import xstruct |
import array |
exclude_names = set(['.svn']) |
def align_up(size, alignment): |
"Return size aligned up to alignment" |
if (size % alignment == 0): |
return size |
return (((size / alignment) + 1) * alignment) |
def subtree_size(root, cluster_size, dirent_size): |
"Recursive directory walk and calculate size" |
size = 0 |
files = 2 |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
size += align_up(os.path.getsize(canon), cluster_size) |
files += 1 |
if (os.path.isdir(canon) and (not name in exclude_names)): |
size += subtree_size(canon, cluster_size, dirent_size) |
files += 1 |
return size + align_up(files * dirent_size, cluster_size) |
def root_entries(root): |
"Return number of root directory entries" |
return len(os.listdir(root)) |
def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters): |
"Store the contents of a file" |
size = os.path.getsize(path) |
prev = -1 |
first = 0 |
inf = file(path, "r") |
rd = 0; |
while (rd < size): |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
if (prev != -1): |
fat[prev] = empty_cluster |
else: |
first = empty_cluster |
prev = empty_cluster |
data = inf.read(cluster_size); |
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) |
outf.write(data) |
rd += len(data) |
inf.close() |
return first, size |
def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster): |
"Store the contents of a directory" |
length = len(directory) |
size = length * dirent_size |
prev = -1 |
first = 0 |
i = 0 |
rd = 0; |
while (rd < size): |
if (prev != -1): |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
fat[prev] = empty_cluster |
else: |
first = empty_cluster |
prev = empty_cluster |
data = '' |
data_len = 0 |
while ((i < length) and (data_len < cluster_size)): |
if (i == 0): |
directory[i].cluster = empty_cluster |
data += directory[i].pack() |
data_len += dirent_size |
i += 1 |
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) |
outf.write(data) |
rd += len(data) |
return first, size |
DIR_ENTRY = """little: |
char name[8] /* file name */ |
char ext[3] /* file extension */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
DOT_DIR_ENTRY = """little: |
uint8_t signature /* 0x2e signature */ |
char name[7] /* empty */ |
char ext[3] /* empty */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
DOTDOT_DIR_ENTRY = """little: |
uint8_t signature[2] /* 0x2e signature */ |
char name[6] /* empty */ |
char ext[3] /* empty */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
def mangle_fname(name): |
# FIXME: filter illegal characters |
parts = name.split('.') |
if (len(parts) > 0): |
fname = parts[0] |
else: |
fname = '' |
return (fname + ' ').upper()[0:8] |
def mangle_ext(name): |
# FIXME: filter illegal characters |
parts = name.split('.') |
if (len(parts) > 1): |
ext = parts[1] |
else: |
ext = '' |
return (ext + ' ').upper()[0:3] |
def create_dirent(name, directory, cluster, size): |
dir_entry = xstruct.create(DIR_ENTRY) |
dir_entry.name = mangle_fname(name) |
dir_entry.ext = mangle_ext(name) |
if (directory): |
dir_entry.attr = 0x30 |
else: |
dir_entry.attr = 0x20 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = cluster |
if (directory): |
dir_entry.size = 0 |
else: |
dir_entry.size = size |
return dir_entry |
def create_dot_dirent(empty_cluster): |
dir_entry = xstruct.create(DOT_DIR_ENTRY) |
dir_entry.signature = 0x2e |
dir_entry.name = ' ' |
dir_entry.ext = ' ' |
dir_entry.attr = 0x10 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = empty_cluster |
dir_entry.size = 0 |
return dir_entry |
def create_dotdot_dirent(parent_cluster): |
dir_entry = xstruct.create(DOTDOT_DIR_ENTRY) |
dir_entry.signature = [0x2e, 0x2e] |
dir_entry.name = ' ' |
dir_entry.ext = ' ' |
dir_entry.attr = 0x10 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = parent_cluster |
dir_entry.size = 0 |
return dir_entry |
def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster): |
"Recursive directory walk" |
directory = [] |
if (not head): |
# Directory cluster preallocation |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
directory.append(create_dot_dirent(empty_cluster)) |
directory.append(create_dotdot_dirent(parent_cluster)) |
else: |
empty_cluster = 0 |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters) |
directory.append(create_dirent(name, False, rv[0], rv[1])) |
if (os.path.isdir(canon) and (not name in exclude_names)): |
rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster) |
directory.append(create_dirent(name, True, rv[0], rv[1])) |
if (head): |
outf.seek(root_start) |
for dir_entry in directory: |
outf.write(dir_entry.pack()) |
else: |
return write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster) |
BOOT_SECTOR = """little: |
uint8_t jmp[3] /* jump instruction */ |
char oem[8] /* OEM string */ |
330,14 → 62,6 |
uint8_t boot_signature[2] /* boot signature */ |
""" |
EMPTY_SECTOR = """little: |
padding[512] /* empty sector data */ |
""" |
FAT_ENTRY = """little: |
uint16_t next /* FAT16 entry */ |
""" |
def usage(prname): |
"Print usage syntax" |
print prname + " <PATH> <IMAGE>" |
352,59 → 76,27 |
print "<PATH> must be a directory" |
return |
fat16_clusters = 4096 |
sector_size = 512 |
cluster_size = 4096 |
dirent_size = 32 |
fatent_size = 2 |
fat_count = 2 |
reserved_clusters = 2 |
# Make sure the filesystem is large enought for FAT16 |
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size |
while (size / cluster_size < fat16_clusters): |
if (cluster_size > sector_size): |
cluster_size /= 2 |
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size |
else: |
size = fat16_clusters * cluster_size + reserved_clusters * cluster_size |
root_size = align_up(root_entries(path) * dirent_size, cluster_size) |
fat_size = align_up(align_up(size, cluster_size) / cluster_size * fatent_size, sector_size) |
sectors = (cluster_size + fat_count * fat_size + root_size + size) / sector_size |
root_start = cluster_size + fat_count * fat_size |
data_start = root_start + root_size |
outf = file(sys.argv[2], "w") |
boot_sector = xstruct.create(BOOT_SECTOR) |
boot_sector.jmp = [0xEB, 0x3C, 0x90] |
boot_sector.oem = "MSDOS5.0" |
boot_sector.sector = sector_size |
boot_sector.cluster = cluster_size / sector_size |
boot_sector.reserved = cluster_size / sector_size |
boot_sector.fats = fat_count |
boot_sector.rootdir = root_size / dirent_size |
if (sectors <= 65535): |
boot_sector.sectors = sectors |
else: |
boot_sector.sectors = 0 |
boot_sector.sector = 512 |
boot_sector.cluster = 8 # 4096 bytes per cluster |
boot_sector.reserved = 1 |
boot_sector.fats = 2 |
boot_sector.rootdir = 224 # FIXME: root directory should be sector aligned |
boot_sector.sectors = 0 # FIXME |
boot_sector.descriptor = 0xF8 |
boot_sector.fat_sectors = fat_size / sector_size |
boot_sector.track_sectors = 63 |
boot_sector.heads = 6 |
boot_sector.fat_sectors = 0 # FIXME |
boot_sector.track_sectors = 0 # FIXME |
boot_sector.heads = 0 # FIXME |
boot_sector.hidden = 0 |
if (sectors > 65535): |
boot_sector.sectors_big = sectors |
else: |
boot_sector.sectors_big = 0 |
boot_sector.sectors_big = 0 # FIXME |
boot_sector.drive = 0x80 |
boot_sector.drive = 0 |
boot_sector.extboot_signature = 0x29 |
boot_sector.serial = random.randint(0, 0x7fffffff) |
boot_sector.serial = random.randint(0, 0xFFFFFFFF) |
boot_sector.label = "HELENOS" |
boot_sector.fstype = "FAT16 " |
boot_sector.boot_signature = [0x55, 0xAA] |
411,39 → 103,6 |
outf.write(boot_sector.pack()) |
empty_sector = xstruct.create(EMPTY_SECTOR) |
# Reserved sectors |
for i in range(1, cluster_size / sector_size): |
outf.write(empty_sector.pack()) |
# FAT tables |
for i in range(0, fat_count): |
for j in range(0, fat_size / sector_size): |
outf.write(empty_sector.pack()) |
# Root directory |
for i in range(0, root_size / sector_size): |
outf.write(empty_sector.pack()) |
# Data |
for i in range(0, size / sector_size): |
outf.write(empty_sector.pack()) |
fat = array.array('L', [0] * (fat_size / fatent_size)) |
fat[0] = 0xfff8 |
fat[1] = 0xffff |
recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) |
# Store FAT |
fat_entry = xstruct.create(FAT_ENTRY) |
for i in range(0, fat_count): |
outf.seek(cluster_size + i * fat_size) |
for j in range(0, fat_size / fatent_size): |
fat_entry.next = fat[j] |
outf.write(fat_entry.pack()) |
outf.close() |
if __name__ == '__main__': |
/branches/sparc/tools/mktmpfs.py |
---|
34,8 → 34,6 |
import os |
import xstruct |
exclude_names = set(['.svn']) |
HEADER = """little: |
char tag[5] /* 'TMPFS' */ |
""" |
72,7 → 70,7 |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
if (os.path.isfile(canon)): |
size = os.path.getsize(canon) |
dentry = xstruct.create(DENTRY_FILE % len(name)) |
91,7 → 89,7 |
rd += len(data) |
inf.close() |
if (os.path.isdir(canon) and (not name in exclude_names)): |
if (os.path.isdir(canon)): |
dentry = xstruct.create(DENTRY_DIRECTORY % len(name)) |
dentry.kind = TMPFS_DIRECTORY |
dentry.fname_len = len(name) |
/branches/sparc/tools/mkfat.sh |
---|
0,0 → 1,73 |
#!/bin/bash |
# |
# Copyright (c) 2008 Jakub Jermar |
# 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. |
# |
MFORMAT=`which mformat` |
MCOPY=`which mcopy` |
if [ `which mformat` == "" ]; then |
echo "Please install mtools." |
exit 1 |
fi |
if [ `which mcopy` == "" ]; then |
echo "Please install mtools." |
exit 1 |
fi |
if [ $# -ne 2 ]; then |
echo "Usage: $0 <PATH> <IMAGE>" |
exit 1 |
fi |
if [ ! -d $1 ]; then |
echo "Usage: $0 <PATH> <IMAGE>" |
exit 1 |
fi |
BPS=512 |
SPC=4 |
FAT16_MIN_SEC=$((4085 * $SPC)) |
HEADS=2 |
TRACKS=16 |
BYTES=`du -sb $1 | cut -f 1` |
SECTORS=$(($BYTES / $BPS)) |
SPTPH=$((($SECTORS + $FAT16_MIN_SEC) / ($HEADS * $TRACKS))) |
# Format the image as FAT16 |
$MFORMAT -h $HEADS -t $TRACKS -s $SPTPH -M $BPS -c $SPC -v "FAT16HORD" -B /dev/zero -C -i $2 :: |
if [ $? -ne 0 ]; then |
echo "$MFORMAT failed: $?" |
exit $? |
fi |
# Copy the subtree to the image |
$MCOPY -vspQmi $2 $1/* :: |
exit $? |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |