From b008dd33c17488774b8332eedf4d0566f92e17e7 Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:54:56 +0800 Subject: [PATCH 01/19] Create a --- lab8/a | 1 + 1 file changed, 1 insertion(+) create mode 100644 lab8/a diff --git a/lab8/a b/lab8/a new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lab8/a @@ -0,0 +1 @@ + From c308a758e76c4302c4eaff79ddd916cc575d679e Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:56:32 +0800 Subject: [PATCH 02/19] Create a --- lab8/kernel/a | 1 + 1 file changed, 1 insertion(+) create mode 100644 lab8/kernel/a diff --git a/lab8/kernel/a b/lab8/kernel/a new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lab8/kernel/a @@ -0,0 +1 @@ + From 7cf792fa756983909b7ee91f49a0717a292a9693 Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:57:20 +0800 Subject: [PATCH 03/19] Add files via upload --- lab8/kernel/src/boot.S | 83 ++ lab8/kernel/src/cpio.c | 45 + lab8/kernel/src/dev_framebuffer.c | 124 +++ lab8/kernel/src/dev_uart.c | 49 ++ lab8/kernel/src/dtb.c | 152 ++++ lab8/kernel/src/entry.S | 196 +++++ lab8/kernel/src/exception.c | 93 ++ lab8/kernel/src/fat32.c | 1309 +++++++++++++++++++++++++++++ lab8/kernel/src/initramfs.c | 163 ++++ lab8/kernel/src/irqtask.c | 65 ++ lab8/kernel/src/link.ld | 27 + lab8/kernel/src/main.c | 42 + lab8/kernel/src/mbox.c | 23 + lab8/kernel/src/memory.c | 380 +++++++++ lab8/kernel/src/mmu.c | 166 ++++ lab8/kernel/src/sched.S | 59 ++ lab8/kernel/src/sched.c | 179 ++++ lab8/kernel/src/sdhost.c | 243 ++++++ lab8/kernel/src/shell.c | 220 +++++ lab8/kernel/src/signal.c | 68 ++ lab8/kernel/src/string.c | 313 +++++++ lab8/kernel/src/syscall.c | 418 +++++++++ lab8/kernel/src/timer.c | 163 ++++ lab8/kernel/src/tmpfs.c | 212 +++++ lab8/kernel/src/uart1.c | 172 ++++ lab8/kernel/src/vfs.c | 343 ++++++++ 26 files changed, 5307 insertions(+) create mode 100644 lab8/kernel/src/boot.S create mode 100644 lab8/kernel/src/cpio.c create mode 100644 lab8/kernel/src/dev_framebuffer.c create mode 100644 lab8/kernel/src/dev_uart.c create mode 100644 lab8/kernel/src/dtb.c create mode 100644 lab8/kernel/src/entry.S create mode 100644 lab8/kernel/src/exception.c create mode 100644 lab8/kernel/src/fat32.c create mode 100644 lab8/kernel/src/initramfs.c create mode 100644 lab8/kernel/src/irqtask.c create mode 100644 lab8/kernel/src/link.ld create mode 100644 lab8/kernel/src/main.c create mode 100644 lab8/kernel/src/mbox.c create mode 100644 lab8/kernel/src/memory.c create mode 100644 lab8/kernel/src/mmu.c create mode 100644 lab8/kernel/src/sched.S create mode 100644 lab8/kernel/src/sched.c create mode 100644 lab8/kernel/src/sdhost.c create mode 100644 lab8/kernel/src/shell.c create mode 100644 lab8/kernel/src/signal.c create mode 100644 lab8/kernel/src/string.c create mode 100644 lab8/kernel/src/syscall.c create mode 100644 lab8/kernel/src/timer.c create mode 100644 lab8/kernel/src/tmpfs.c create mode 100644 lab8/kernel/src/uart1.c create mode 100644 lab8/kernel/src/vfs.c diff --git a/lab8/kernel/src/boot.S b/lab8/kernel/src/boot.S new file mode 100644 index 000000000..06acf6ee9 --- /dev/null +++ b/lab8/kernel/src/boot.S @@ -0,0 +1,83 @@ +#include "mmu.h" + +.section ".text.boot" + +.global _start + +_start: + // Switch from EL2 to EL1 . + bl from_el2_to_el1 + +set_mmu_configuration: + // set paging configuration (up : 0xffff000000000000 low : 0x0000000000000000) + ldr x4, = TCR_CONFIG_DEFAULT + msr tcr_el1, x4 + + // Set Used Memory Attributes + ldr x4, =((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) + msr mair_el1, x4 + + // set and enable MMU + ldr x4, = MMU_PGD_ADDR // PGD's page frame at 0x1000 + ldr x1, = MMU_PUD_ADDR // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x4] // [MMU_PGD_ADDR] = MMU_PUD_ADDR | BOOT_PGD_ATTR + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 // [MMU_PUD_ADDR] = 0x00000000 | BOOT_PUD_ATTR + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 // [MMU_PUD_ADDR + 8] = 0x40000000 | BOOT_PUD_ATTR + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x4 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x4 // also load PGD to the upper translation based register. + + mov sp, 0x3c000000 // temp stack + bl set_2M_kernel_mmu + + mrs x2, sctlr_el1 // sctlr_el1: Provides top level control of the system, including its memory system, at EL1 and EL0. + orr x2 , x2, 1 // sctlr_el1[0]: EL1&0 stage 1 address translation enabled/disabled. + msr sctlr_el1, x2 + + // indirect branch to the upper virtual address + ldr x2, =set_exception_vector_table + br x2 + +set_exception_vector_table: + adr x1, exception_vector_table + msr vbar_el1, x1 + +setup_stack: + // set top of stack at 0xffff00003c000000 (last usable memory) + ldr x3, =_stack_top + mov sp, x3 + +setup_bss: + ldr x1, =__bss_start + ldr w2, =__bss_size +init_bss: + cbz w2, run_main + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, init_bss + +run_main: + ldr x1, =dtb_ptr + str x0, [x1], #8 + bl main // branch and update lr with "main" + +proc_hang: + wfe // waiting in low-power state + b proc_hang + +from_el2_to_el1: + mov x1, (1 << 31) // hcr_el2: Execution state control for EL2 + msr hcr_el2, x1 // RW[31]: 0b1 The processor execution environment for EL1 is AArch64 + mov x1, 0x3c5 // spsr_el2: Holds the saved process state when an exception is taken to EL2. + msr spsr_el2, x1 // (1)[1111] 00 (2)[0101] -> (1) EL2-PSTATE.DAIF Disabled (2) Exception level = EL1h + msr elr_el2, lr // elr_el2: When taking an exception to EL2, holds the address to return to. + eret // eret: Perform an exception return. EL2 -> EL1 diff --git a/lab8/kernel/src/cpio.c b/lab8/kernel/src/cpio.c new file mode 100644 index 000000000..352dee86f --- /dev/null +++ b/lab8/kernel/src/cpio.c @@ -0,0 +1,45 @@ +#include "cpio.h" +#include "dtb.h" +#include "string.h" + +void* CPIO_DEFAULT_START; +void* CPIO_DEFAULT_END; + +static unsigned int parse_hex_str(char *s, unsigned int max_len) +{ + unsigned int r = 0; + for (unsigned int i = 0; i < max_len; i++) { + r *= 16; + if (s[i] >= '0' && s[i] <= '9') r += s[i] - '0'; + else if (s[i] >= 'a' && s[i] <= 'f') r += s[i] - 'a' + 10; + else if (s[i] >= 'A' && s[i] <= 'F') r += s[i] - 'A' + 10; + else return r; + } + return r; +} + +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, char **pathname, unsigned int *filesize, char **data, struct cpio_newc_header **next_header_pointer) +{ + if (strncmp(this_header_pointer->c_magic, CPIO_NEWC_HEADER_MAGIC, sizeof(this_header_pointer->c_magic)) != 0) return -1; + + *filesize = parse_hex_str(this_header_pointer->c_filesize,8); + *pathname = ((char *)this_header_pointer) + sizeof(struct cpio_newc_header); + + unsigned int pathname_length = parse_hex_str(this_header_pointer->c_namesize,8); + unsigned int offset = pathname_length + sizeof(struct cpio_newc_header); + offset = offset % 4 == 0 ? offset:(offset+4-offset%4); + *data = (char *)this_header_pointer+offset; + + if(*filesize==0) + { + *next_header_pointer = (struct cpio_newc_header*)*data; + } + else + { + offset = *filesize; + *next_header_pointer = (struct cpio_newc_header*)(*data + (offset%4==0?offset:(offset+4-offset%4))); + } + if(strncmp(*pathname,"TRAILER!!!", sizeof("TRAILER!!!"))==0) *next_header_pointer = 0; + + return 0; +} diff --git a/lab8/kernel/src/dev_framebuffer.c b/lab8/kernel/src/dev_framebuffer.c new file mode 100644 index 000000000..9385d0fdf --- /dev/null +++ b/lab8/kernel/src/dev_framebuffer.c @@ -0,0 +1,124 @@ +#include "vfs.h" +#include "dev_framebuffer.h" +#include "uart1.h" +#include "memory.h" +#include "mbox.h" +#include "string.h" +#include "exception.h" + +#define MBOX_CH_PROP 8 + +//The following code is for mailbox initialize used in lab7. +unsigned int width, height, pitch, isrgb; /* dimensions and channel order */ +unsigned char *lfb; /* raw frame buffer address */ + +struct file_operations dev_framebuffer_operations = {dev_framebuffer_write, (void *)dev_framebuffer_op_deny, dev_framebuffer_open, dev_framebuffer_close, dev_framebuffer_lseek64, (void *)dev_framebuffer_op_deny}; + +int init_dev_framebuffer() +{ + //The following code is for mailbox initialize used in lab7. + pt[0] = 35 * 4; + pt[1] = MBOX_TAG_REQUEST_CODE; + + pt[2] = 0x48003; // set phy wh + pt[3] = 8; + pt[4] = 8; + pt[5] = 1024; // FrameBufferInfo.width + pt[6] = 768; // FrameBufferInfo.height + + pt[7] = 0x48004; // set virt wh + pt[8] = 8; + pt[9] = 8; + pt[10] = 1024; // FrameBufferInfo.virtual_width + pt[11] = 768; // FrameBufferInfo.virtual_height + + pt[12] = 0x48009; // set virt offset + pt[13] = 8; + pt[14] = 8; + pt[15] = 0; // FrameBufferInfo.x_offset + pt[16] = 0; // FrameBufferInfo.y.offset + + pt[17] = 0x48005; // set depth + pt[18] = 4; + pt[19] = 4; + pt[20] = 32; // FrameBufferInfo.depth + + pt[21] = 0x48006; // set pixel order + pt[22] = 4; + pt[23] = 4; + pt[24] = 1; // RGB, not BGR preferably + + pt[25] = 0x40001; // get framebuffer, gets alignment on request + pt[26] = 8; + pt[27] = 8; + pt[28] = 4096; // FrameBufferInfo.pointer + pt[29] = 0; // FrameBufferInfo.size + + pt[30] = 0x40008; // get pitch + pt[31] = 4; + pt[32] = 4; + pt[33] = 0; // FrameBufferInfo.pitch + + pt[34] = MBOX_TAG_LAST_BYTE; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)) && pt[20] == 32 && pt[28] != 0) + { + pt[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = pt[5]; // get actual physical width + height = pt[6]; // get actual physical height + pitch = pt[33]; // get number of bytes per line + isrgb = pt[24]; // get the actual channel order + lfb = PHYS_TO_VIRT((void *)((unsigned long)pt[28])); + } + else + { + uart_puts("Unable to set screen resolution to 1024x768x32\n"); + } + + return register_dev(&dev_framebuffer_operations); +} + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len) +{ + lock(); + if (len + file->f_pos > pitch * height) + { + uart_puts("????\r\n"); + len = pitch * height - file->f_pos; + } + memcpy(lfb + file->f_pos, buf, len); + file->f_pos += len; + unlock(); + return len; +} + +int dev_framebuffer_open(struct vnode *file_node, struct file **target) +{ + (*target)->f_pos = 0; + (*target)->vnode = file_node; + (*target)->f_ops = &dev_framebuffer_operations; + return 0; +} + +int dev_framebuffer_close(struct file *file) +{ + kfree(file); + return 0; +} + +long dev_framebuffer_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +int dev_framebuffer_op_deny() +{ + return -1; +} diff --git a/lab8/kernel/src/dev_uart.c b/lab8/kernel/src/dev_uart.c new file mode 100644 index 000000000..2aade4967 --- /dev/null +++ b/lab8/kernel/src/dev_uart.c @@ -0,0 +1,49 @@ +#include "vfs.h" +#include "dev_uart.h" +#include "uart1.h" +#include "memory.h" + +struct file_operations dev_file_operations = {dev_uart_write, dev_uart_read, dev_uart_open, dev_uart_close, (void *)dev_uart_op_deny, (void *)dev_uart_op_deny}; + +int init_dev_uart() +{ + return register_dev(&dev_file_operations); +} + +int dev_uart_write(struct file *file, const void *buf, size_t len) +{ + const char *cbuf = buf; + for (int i = 0; i < len;i++) + { + uart_async_putc(cbuf[i]); + } + return len; +} + +int dev_uart_read(struct file *file, void *buf, size_t len) +{ + char *cbuf = buf; + for (int i = 0; i < len; i++) + { + cbuf[i] = uart_async_getc(); + } + return len; +} + +int dev_uart_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = &dev_file_operations; + return 0; +} + +int dev_uart_close(struct file *file) +{ + kfree(file); + return 0; +} + +int dev_uart_op_deny() +{ + return -1; +} diff --git a/lab8/kernel/src/dtb.c b/lab8/kernel/src/dtb.c new file mode 100644 index 000000000..57d6eb9f3 --- /dev/null +++ b/lab8/kernel/src/dtb.c @@ -0,0 +1,152 @@ +#include "bcm2837/rpi_mmu.h" +#include "dtb.h" +#include "uart1.h" +#include "string.h" +#include "cpio.h" +#include "memory.h" + +char* dtb_ptr; + +//stored as big endian +struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +// memory reservation block - https://zhuanlan.zhihu.com/p/144863497 +struct fdt_reserve_entry { + uint64_t address; + uint64_t size; +}; + +uint32_t uint32_endian_big2lttle(uint32_t data) +{ + char* r = (char*)&data; + return (r[3]<<0) | (r[2]<<8) | (r[1]<<16) | (r[0]<<24); +} + +uint64_t uint64_endian_big2lttle(uint64_t data) +{ + char *r = (char *)&data; + return ((unsigned long long)r[7] << 0) | ((unsigned long long)r[6] << 8) | ((unsigned long long)r[5] << 16) | ((unsigned long long)r[4] << 24) | ((unsigned long long)r[3] << 32) | ((unsigned long long)r[2] << 40) | ((unsigned long long)r[1] << 48) | ((unsigned long long)r[0] << 56); +} + +void traverse_device_tree(void *dtb_ptr, dtb_callback callback) +{ + struct fdt_header* header = dtb_ptr; + if(uint32_endian_big2lttle(header->magic) != 0xD00DFEED) + { + uart_puts("traverse_device_tree : wrong magic in traverse_device_tree"); + return; + } + // https://abcamus.github.io/2016/12/28/uboot%E8%AE%BE%E5%A4%87%E6%A0%91-%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B/ + // https://blog.csdn.net/wangdapao12138/article/details/82934127 + uint32_t struct_size = uint32_endian_big2lttle(header->size_dt_struct); + char* dt_struct_ptr = (char*)((char*)header + uint32_endian_big2lttle(header->off_dt_struct)); + char* dt_strings_ptr = (char*)((char*)header + uint32_endian_big2lttle(header->off_dt_strings)); + + char* end = (char*)dt_struct_ptr + struct_size; + char* pointer = dt_struct_ptr; + + while(pointer < end) + { + uint32_t token_type = uint32_endian_big2lttle(*(uint32_t*)pointer); + + pointer += 4; + if(token_type == FDT_BEGIN_NODE) + { + callback(token_type, pointer, 0, 0); + pointer += strlen(pointer); + pointer += 4 - (unsigned long long) pointer % 4; //alignment 4 byte + }else if(token_type == FDT_END_NODE) + { + callback(token_type, 0, 0, 0); + }else if(token_type == FDT_PROP) + { + uint32_t len = uint32_endian_big2lttle(*(uint32_t*)pointer); + pointer += 4; + char* name = (char*)dt_strings_ptr + uint32_endian_big2lttle(*(uint32_t*)pointer); + pointer += 4; + callback(token_type, name, pointer, len); + pointer += len; + if((unsigned long long)pointer % 4 != 0) pointer += 4 - (unsigned long long)pointer%4; //alignment 4 byte + }else if(token_type == FDT_NOP) + { + callback(token_type, 0, 0, 0); + }else if(token_type == FDT_END) + { + callback(token_type, 0, 0, 0); + }else + { + uart_puts("error type:%x\n",token_type); + return; + } + } +} + +void dtb_callback_show_tree(uint32_t node_type, char *name, void *data, uint32_t name_size) +{ + static int level = 0; + if(node_type==FDT_BEGIN_NODE) + { + for(int i=0;imagic) != 0xD00DFEED) + { + uart_puts("traverse_device_tree : wrong magic in traverse_device_tree"); + return; + } + + // off_mem_rsvmap stores all of reserve memory map with address and size + char *dt_mem_rsvmap_ptr = (char *)((char *)header + uint32_endian_big2lttle(header->off_mem_rsvmap)); + struct fdt_reserve_entry *reverse_entry = (struct fdt_reserve_entry *)dt_mem_rsvmap_ptr; + + // reserve memory which is defined by dtb + while (reverse_entry->address != 0 || reverse_entry->size != 0) + { + unsigned long long start = PHYS_TO_VIRT(uint64_endian_big2lttle(reverse_entry->address)); + unsigned long long end = uint64_endian_big2lttle(reverse_entry->size) + start; + memory_reserve(start, end); + reverse_entry++; + } + + // reserve device tree itself + memory_reserve((unsigned long long)dtb_ptr, (unsigned long long)dtb_ptr + uint32_endian_big2lttle(header->totalsize)); +} diff --git a/lab8/kernel/src/entry.S b/lab8/kernel/src/entry.S new file mode 100644 index 000000000..76d4126d6 --- /dev/null +++ b/lab8/kernel/src/entry.S @@ -0,0 +1,196 @@ +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 9 + stp x0, x1, [sp ,16 * 0] // store pair of registers + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // information for nested interrupt + mrs x0, spsr_el1 + str x0, [sp, 16 * 15 + 8] + mrs x0, elr_el1 + str x0, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 16 + 8] + ldp x0, x1, [sp, 16 * 0] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + // information for nested interrupt + ldr x0, [sp, 16 * 15 + 8] + msr spsr_el1,x0 + ldr x0, [sp, 16 * 16] + msr elr_el1, x0 + ldr x0, [sp, 16 * 16 + 8] + msr sp_el0, x0 + ldp x0, x1, [sp ,16 * 0] // restore x0 instead of elr_el1 + add sp, sp, 32 * 9 +.endm + + +.macro ventry label + .align 7 // entry should be aligned to 0x80 (2^7) + b \label +.endm + +.align 11 // vector table should be aligned to 0x800 (2^11) +.global exception_vector_table + +// exception_vector_table definition +// https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L367 +exception_vector_table: + //Exception from the current EL while using SP_EL0 + ventry el1t_sync_invalid // Synchronous EL1t + ventry el1t_irq_invalid // IRQ EL1t + ventry el1t_fiq_invalid // FIQ EL1t + ventry el1t_error_invalid // Error EL1t + + //Exception from the current EL while using SP_ELx + ventry el1h_sync // Synchronous EL1h + ventry el1h_irq // IRQ EL1h + ventry el1h_fiq_invalid // FIQ EL1h + ventry el1h_error_invalid // Error EL1h + + //Exception from a lower EL and at least one lower EL is AArch64 + ventry el0_sync_64 // Synchronous 64-bit EL0 + ventry el0_irq_64 // IRQ 64-bit EL0 + ventry el0_fiq_invalid_64 // FIQ 64-bit EL0 + ventry el0_error_invalid_64 // Error 64-bit EL0 + + //Exception from a lower EL and at least all lower EL are AArch32 + ventry el0_sync_invalid_32 // Synchronous 32-bit EL0 + ventry el0_irq_invalid_32 // IRQ 32-bit EL0 + ventry el0_fiq_invalid_32 // FIQ 32-bit EL0 + ventry el0_error_invalid_32 // Error 32-bit EL0 + + +el1t_sync_invalid: + save_all + mov x0,0 + bl invalid_exception_router + load_all + eret +el1t_irq_invalid: + save_all + mov x0,1 + bl invalid_exception_router + load_all + eret +el1t_fiq_invalid: + save_all + mov x0,2 + bl invalid_exception_router + load_all + eret +el1t_error_invalid: + save_all + mov x0,3 + bl invalid_exception_router + load_all + eret + + +el1h_sync: + save_all + mov x0,4 + bl invalid_exception_router + load_all + eret +el1h_irq: + save_all + mov x0, sp // trapframe + bl irq_router + load_all + eret +el1h_fiq_invalid: + save_all + mov x0,6 + bl invalid_exception_router + load_all + eret +el1h_error_invalid: + save_all + mov x0,7 + bl invalid_exception_router + load_all + eret + +el0_sync_64: + save_all + mov x0, sp // trapframe + bl sync_64_router + load_all + eret +el0_irq_64: + save_all + mov x0, sp // trapframe + bl irq_router + load_all + eret +el0_fiq_invalid_64: + save_all + mov x0,10 + bl invalid_exception_router + load_all + eret +el0_error_invalid_64: + save_all + mov x0,11 + bl invalid_exception_router + load_all + eret + + +el0_sync_invalid_32: + save_all + mov x0,12 + bl invalid_exception_router + load_all + eret +el0_irq_invalid_32: + save_all + mov x0,13 + bl invalid_exception_router + load_all + eret +el0_fiq_invalid_32: + save_all + mov x0,14 + bl invalid_exception_router + load_all + eret +el0_error_invalid_32: + save_all + mov x0,15 + bl invalid_exception_router + load_all + eret diff --git a/lab8/kernel/src/exception.c b/lab8/kernel/src/exception.c new file mode 100644 index 000000000..4b80e0825 --- /dev/null +++ b/lab8/kernel/src/exception.c @@ -0,0 +1,93 @@ +#include "bcm2837/rpi_uart1.h" +#include "uart1.h" +#include "exception.h" +#include "timer.h" +#include "irqtask.h" +#include "syscall.h" +#include "sched.h" +#include "signal.h" +#include "mmu.h" + +void sync_64_router(trapframe_t* tpf) +{ + unsigned long long esr_el1; + __asm__ __volatile__("mrs %0, esr_el1\n\t": "=r"(esr_el1)); + // esr_el1: Holds syndrome information for an exception taken to EL1. + esr_el1_t *esr = (esr_el1_t *)&esr_el1; + if (esr->ec == MEMFAIL_DATA_ABORT_LOWER || esr->ec == MEMFAIL_INST_ABORT_LOWER) + { + mmu_memfail_abort_handle(esr); + return; + } + + el1_interrupt_enable(); + unsigned long long syscall_no = tpf->x8; + if (syscall_no == 0) { getpid(tpf); } + else if(syscall_no == 1) { uartread(tpf,(char *) tpf->x0, tpf->x1); } + else if (syscall_no == 2) { uartwrite(tpf,(char *) tpf->x0, tpf->x1); } + else if (syscall_no == 3) { exec(tpf,(char *) tpf->x0, (char **)tpf->x1); } + else if (syscall_no == 4) { fork(tpf); } + else if (syscall_no == 5) { exit(tpf,tpf->x0); } + else if (syscall_no == 6) { syscall_mbox_call(tpf,(unsigned char)tpf->x0, (unsigned int *)tpf->x1); } + else if (syscall_no == 7) { kill(tpf, (int)tpf->x0); } + else if (syscall_no == 8) { signal_register(tpf->x0, (void (*)())tpf->x1); } + else if (syscall_no == 9) { signal_kill(tpf->x0, tpf->x1); } + else if (syscall_no == 10) { mmap(tpf,(void *)tpf->x0,tpf->x1,tpf->x2,tpf->x3,tpf->x4,tpf->x5); } + else if (syscall_no == 11) { open(tpf, (char*)tpf->x0, tpf->x1); } + else if (syscall_no == 12) { close(tpf, tpf->x0); } + else if (syscall_no == 13) { write(tpf, tpf->x0, (char *)tpf->x1, tpf->x2); } + else if (syscall_no == 14) { read(tpf, tpf->x0, (char *)tpf->x1, tpf->x2); } + else if (syscall_no == 15) { mkdir(tpf, (char *)tpf->x0, tpf->x1); } + else if (syscall_no == 16) { mount(tpf, (char *)tpf->x0, (char *)tpf->x1, (char *)tpf->x2, tpf->x3, (void*)tpf->x4); } + else if (syscall_no == 17) { chdir(tpf, (char *)tpf->x0); } + else if (syscall_no == 18) { lseek64(tpf, tpf->x0, tpf->x1, tpf->x2); } + else if (syscall_no == 19) { ioctl(tpf, tpf->x0, tpf->x1, (void*)tpf->x2); } + else if (syscall_no == 20) { sync(tpf); } + else if (syscall_no == 50) { sigreturn(tpf); } + el1_interrupt_disable(); +} + +void irq_router(trapframe_t* tpf) +{ + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) { + if (*AUX_MU_IIR_REG & (1 << 1)) // can write + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + irqtask_run_preemptive(); + } + else if (*AUX_MU_IIR_REG & (0b10 << 1)) // can read + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + irqtask_run_preemptive(); + } + } else if(*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + irqtask_run_preemptive(); + core_timer_enable(); + el1_interrupt_disable(); + if (run_queue->next->next != run_queue) schedule(); + } + if ((tpf->spsr_el1 & 0b1100) == 0) { check_signal(tpf); } + el1_interrupt_disable(); +} + +void invalid_exception_router(unsigned long long x0){ + // TBD +} + +static unsigned long long lock_count = 0; +void lock() +{ + el1_interrupt_disable(); + lock_count++; +} + +void unlock() +{ + lock_count--; + if (lock_count == 0) + el1_interrupt_enable(); +} diff --git a/lab8/kernel/src/fat32.c b/lab8/kernel/src/fat32.c new file mode 100644 index 000000000..cd26a5ce3 --- /dev/null +++ b/lab8/kernel/src/fat32.c @@ -0,0 +1,1309 @@ +#include "fat32.h" +#include "memory.h" +#include "sdhost.h" +#include "string.h" +#include "list.h" +#include +#include "uart1.h" +#include "exception.h" + +struct list_head mounts; // Store all new mountpoints that probably need to be sync'd + +struct vnode_operations fat32_v_ops = { + fat32_lookup, fat32_create, fat32_mkdir, + fat32_isdir, fat32_getname, fat32_getsize +}; + +struct file_operations fat32_f_ops = { + fat32_write, fat32_read, fat32_open, + fat32_close, fat32_lseek64, +}; + +int register_fat32() +{ + struct filesystem fs; + fs.name = "fat32"; + fs.setup_mount = fat32_mount; + fs.sync = fat32_sync; + INIT_LIST_HEAD(&mounts); + return register_filesystem(&fs); +} + +/* filesystem methods */ +int fat32_mount(struct filesystem *fs, struct mount *mount) +{ + struct partition_t *partition; + struct fat_info_t *fat; + struct fat_dir_t *dir; + struct fat32_inode *data; + struct vnode *oldnode, *node; + struct fat_mount_t *newmount; + unsigned int lba; + unsigned char buf[BLOCK_SIZE]; + + // Read partition table from MBR, which is at first block + readblock(0, buf); + // MBR format + // 000 ~ 1BD: Code area + // 1BE ~ 1FD: Master Partition Table + // 1FE ~ 1FF: Boot Record Signature + + // https://lexra.pixnet.net/blog/post/303910876 + partition = (struct partition_t *)&buf[0x1be]; + // check Boot Record Signature, constants + if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) + { + return -1; + } + // https://en.wikipedia.org/wiki/Partition_type + if (partition[0].type != 0xb && partition[0].type != 0xc) // check Partition type, only FAT32 + { + return -1; + } + lba = partition[0].lba; + readblock(partition[0].lba, buf); + + node = kmalloc(sizeof(struct vnode)); + data = kmalloc(sizeof(struct fat32_inode)); + fat = kmalloc(sizeof(struct fat_info_t)); + dir = kmalloc(sizeof(struct fat_dir_t)); + newmount = kmalloc(sizeof(struct fat_mount_t)); + + memcpy((void *)&fat->bs, (void *)buf, sizeof(fat->bs)); + + // According to FAT fs design, FAT Region is after reserved sectors + // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system + fat->fat_lba = lba + fat->bs.reserved_sector_cnt; + fat->cluster_lba = fat->fat_lba + fat->bs.fat_cnt * fat->bs.sector_per_fat32; + + INIT_LIST_HEAD(&dir->list); + + // oldnode should attach mount the fs + oldnode = mount->root; + + node->mount = oldnode->mount; + node->v_ops = oldnode->v_ops; + node->f_ops = oldnode->f_ops; + node->parent = oldnode->parent; + node->internal = oldnode->internal; + + data->node = node; + data->fat = fat; + data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 + data->type = FAT_DIR; + data->dir = dir; + + oldnode->mount = mount; + oldnode->v_ops = &fat32_v_ops; + oldnode->f_ops = &fat32_f_ops; + oldnode->internal = data; + + lock(); + list_add(&newmount->list, &mounts); + unlock(); + newmount->mount = mount; + + return 0; +} + +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) return -1; + if (!_lookup_cache(dir_node, target, component_name)) return 0; + return _lookup_fat32(dir_node, target, component_name); +} + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) return -1; + if (!fat32_lookup(dir_node, target, component_name)) return -1; + *target = _create_vnode(dir_node, component_name, FAT_FILE, -1, 0); + return 0; +} + +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) return -1; + if (!fat32_lookup(dir_node, target, component_name)) return -1; + *target = _create_vnode(dir_node, component_name, FAT_DIR, -1, 0); + return 0; +} + +int fat32_isdir(struct vnode *dir_node) +{ + return (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) ? 1 : 0; +} + +int fat32_getname(struct vnode *dir_node, const char **name) +{ + *name = ((struct fat32_inode *)dir_node->internal)->name; + return 0; +} + +int fat32_getsize(struct vnode *dir_node) +{ + if (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) return 0; + return ((struct fat32_inode *)dir_node->internal)->file->size; +} + +/* file_operations methods */ +int fat32_write(struct file *file, const void *buf, size_t len) +{ + struct fat32_inode *data; + int filesize; + int ret; + + if (fat32_isdir(file->vnode)) return -1; + if (!len) return len; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + ret = _writefile(buf, data, file->f_pos, len); + if (ret <= 0) { + return ret; + } + + file->f_pos += ret; + if (file->f_pos > filesize) { + data->file->size = file->f_pos; + } + + return ret; +} + +int fat32_read(struct file *file, void *buf, size_t len) +{ + struct fat32_inode *data; + int filesize; + int ret; + + if (fat32_isdir(file->vnode)) return -1; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + if (file->f_pos + len > filesize) { + len = filesize - file->f_pos; + } + if (!len) return len; + + ret = _readfile(buf, data, file->f_pos, len); + if (ret <= 0) return ret; + + file->f_pos += ret; + return ret; +} + +int fat32_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_pos = 0; + (*target)->f_ops = file_node->f_ops; + return 0; +} + +int fat32_close(struct file *file) +{ + file->vnode = NULL; + file->f_pos = 0; + file->f_ops = NULL; + return 0; +} + +long fat32_lseek64(struct file *file, long offset, int whence) +{ + int filesize; + int base; + + if (!fat32_isdir(file->vnode)) return -1; + + filesize = fat32_getsize(file->vnode); + + if (filesize < 0) return -1; + + switch (whence) + { + case SEEK_SET: + base = 0; + break; + case SEEK_CUR: + base = file->f_pos; + break; + case SEEK_END: + base = filesize; + break; + default: + return -1; + } + + if (base + offset > filesize) + { + return -1; + } + file->f_pos = base + offset; + + return 0; +} + +int fat32_sync(struct filesystem *fs) +{ + struct fat_mount_t *entry; + + list_for_each_entry(entry, &mounts, list) + { + _sync_dir(entry->mount->root); + } + + return 0; +} + +// ------------------------------------------------------------------------ +// Utils +// + +unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id) +{ + struct cluster_entry_t *ce; + unsigned int idx; + unsigned char buf[BLOCK_SIZE]; + + if (cluster_id >= INVALID_CID) + { + return cluster_id; + } + + // Get fat allocation table and its cluster entry in Data region + fat_lba += cluster_id / CLUSTER_ENTRY_PER_BLOCK; + idx = cluster_id % CLUSTER_ENTRY_PER_BLOCK; + + readblock(fat_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[idx]); + + return ce->val; +} + +unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid) +{ + struct cluster_entry_t *ce; + unsigned int fat_lba; + unsigned int cid; + int found; + unsigned char buf[BLOCK_SIZE]; + + fat_lba = fat->fat_lba; + cid = 0; + // find unused cluster by clusters -> fats + while (fat_lba < fat->cluster_lba) { + found = 0; + readblock(fat_lba, buf); + + for (int i = 0; i < CLUSTER_ENTRY_PER_BLOCK; ++i) { + ce = &(((struct cluster_entry_t *)buf)[i]); + + if (!ce->val) { + found = 1; + break; + } + + ++cid; + } + + if (found) { + break; + } + fat_lba += 1; + } + // Only called if prev_cid is larger than 0xfffffff8, realloc ce; + if (found && prev_cid) { + unsigned int target_lba; + unsigned int target_idx; + + target_lba = fat_lba + prev_cid / CLUSTER_ENTRY_PER_BLOCK; + target_idx = prev_cid % CLUSTER_ENTRY_PER_BLOCK; + readblock(target_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[target_idx]); + ce->val = cid; + writeblock(target_lba, buf); + } + + if (!found) { + uart_sendline("fat32 alloc_cluster: No space!"); + return -1; + } + + return cid; +} + +/* vnode_operations methods */ +struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size) +{ + struct vnode *node; + struct fat32_inode *info, *data; + char *buf; + int len; + + info = parent->internal; + len = strlen(name); + + buf = kmalloc(len + 1); + node = kmalloc(sizeof(struct vnode)); + data = kmalloc(sizeof(struct fat32_inode)); + + strcpy(buf, name); + + data->name = buf; + data->node = node; + data->fat = info->fat; + data->cid = cid; + data->type = type; + + if (type == FAT_DIR) { + struct fat_dir_t *dir; + dir = kmalloc(sizeof(struct fat_dir_t)); + INIT_LIST_HEAD(&dir->list); + data->dir = dir; + } else { + struct fat_file_t *file; + file = kmalloc(sizeof(struct fat_file_t)); + INIT_LIST_HEAD(&file->list); + file->size = size; + data->file = file; + } + + node->mount = parent->mount; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->parent = parent; + node->internal = data; + + // attach to parent's dir_t or file_t list + list_add(&data->list, &info->dir->list); + + return node; +} + +int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct fat32_inode *data, *entry; + struct fat_dir_t *dir; + int found; + + data = dir_node->internal; + dir = data->dir; + found = 0; + + list_for_each_entry(entry, &dir->list, list) { + if (!strcasecmp(component_name, entry->name)) { // same as strcmp, but tr [:lower:] + found = 1; + break; + } + } + if (!found) { + return -1; + } + *target = entry->node; + return 0; +} + +struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba) +{ + struct dir_t *dir; + struct fat32_inode *data; + struct fat_info_t *fat; + struct filename_t name; + unsigned int cid; + int found, dirend, lfn; + + data = dir_node->internal; + fat = data->fat; + cid = data->cid; + + found = 0; + dirend = 0; + + memset(&name, 0, sizeof(struct filename_t)); + + while (1) { + int lba; + + lba = fat->cluster_lba + (cid - 2) * fat->bs.sector_per_cluster; // cluster start from #2 + readblock(lba, buf); + + // only called by sync, to update buffer + if (buflba) { + *buflba = lba; + } + + for (int i = 0; i < DIR_PER_BLOCK; ++i) { + unsigned char len; + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * i]); + + if (dir->name[0] == 0) { + dirend = 1; + break; + } + + if ((dir->attr & ATTR_LFN) == ATTR_LFN) { + struct long_dir_t *ldir; + int n; + + lfn = 1; + + ldir = (struct long_dir_t *)dir; + n = (dir->name[0] & 0x3f) - 1; // every lfn entry has 16 bytes + // update filename_t if it is LFN + for (int i = 0; ldir->name1[i] != 0xff && i < 10; i += 2) { + name.part[n].name[i / 2] = ldir->name1[i]; // LDIR_Name1 1th ~ 5th + } + for (int i = 0; ldir->name2[i] != 0xff && i < 12; i += 2) { + name.part[n].name[5 + i / 2] = ldir->name2[i]; // LDIR_Name2 6th ~ 11th + } + for (int i = 0; ldir->name3[i] != 0xff && i < 4; i += 2) { + name.part[n].name[11 + i / 2] = ldir->name3[i]; // LDIR_Name3 12th ~ 13th + } + + continue; + } + + if (lfn == 1) { + if (!strcasecmp(component_name, (void *)name.fullname)) { + found = 1; + break; + } + + lfn = 0; + memset(&name, 0, sizeof(struct filename_t)); + continue; + } + + lfn = 0; + len = 8; + + // SFN lookup + while (len) { + if (dir->name[len - 1] != 0x20) { + break; + } + len -= 1; + } + + memcpy((void *)name.fullname, (void *)dir->name, len); + name.fullname[len] = 0; + + len = 3; + + while (len) { + if (dir->name[8 + len - 1] != 0x20) { + break; + } + len -= 1; + } + + if (len >= 0) { + strcat((void *)name.fullname, "."); + strncat((void *)name.fullname, (void *)&dir->name[8], len); + } + + if (!strcasecmp(component_name, (void *)name.fullname)) { + found = 1; + break; + } + + memset(&name, 0, sizeof(struct filename_t)); + } + + if (found) { + break; + } + + if (dirend) { + break; + } + + // try next cluster and lookup again + cid = get_next_cluster(fat->fat_lba, cid); + + if (cid >= INVALID_CID) { + break; + } + } + + if (!found) { + return NULL; + } + + return dir; +} + +int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct vnode *node; + struct dir_t *dir; + unsigned int type, cid; + unsigned char buf[BLOCK_SIZE]; + + dir = __lookup_fat32(dir_node, component_name, buf, NULL); + + if (!dir) { + return -1; + } + + if (!(dir->attr & ATTR_FILE_DIR_MASK)) { + return -1; + } + + cid = (dir->ch << 16) | dir->cl; // upper part of cluster id + lower part of cluster id + + if (dir->attr & ATTR_ARCHIVE) { + type = FAT_FILE; + } else { + type = FAT_DIR; + } + + node = _create_vnode(dir_node, component_name, type, cid, dir->size); + + *target = node; + + return 0; +} + + +int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + head = &data->file->list; + + if (list_empty(head)) { + return -1; + } + + list_for_each_entry(entry, head, list) { + *block = entry; + if (foid == entry->oid) { // offset match + return 0; + } + } + + return -1; +} + +int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // block is from cache + if (*block) { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) { // offset match + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } else { + curoid = 0; + curcid = fcid; + } + + // create new block in cache + while (1) { + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 1; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } +} + +int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int wsize; + + // if cache block is not updated yet, read from sdcard + if (!block->bufIsUpdated) { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + return wsize; +} + +int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int wsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + // read the address from sdcard and write it + if (cid >= INVALID_CID) { + memset(block->buf, 0, BLOCK_SIZE); + } else { + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + } + + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + block->isDirty = 1; // wait for sync + + list_add_tail(&block->list, head); + + return wsize; +} + +int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _writefile_seek_cache(data, foid, &block); + + if (ret < 0) { + ret = _writefile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) { + return 0; + } + + // Write + while (len) { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) { + // cache has the blocks to be written + ret = _writefile_cache(data, bckoff, buf, bufoff, len, block); + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } else { + // Read block from sdcard, create cache, then write it + cid = get_next_cluster(data->fat->fat_lba, cid); + ret = _writefile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + + +int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + // check the cache list + head = &data->file->list; + + // if cache is none, return not found + if (list_empty(head)) { + return -1; + } + + // find that offset in cache + list_for_each_entry(entry, head, list) { + *block = entry; + if (foid == entry->oid) { + return 0; + } + } + + return -1; +} + +int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // if block found in cache, change to that offset in fat32 + if (*block) { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) { + return -1; + } + } else { + curoid = 0; + curcid = fcid; + } + + while (1) { + // add new offset block to cache + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 0; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) { + return -1; + } + } +} + +int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int rsize; + + if (!block->bufIsUpdated) { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + // if the size is overflow, resize it + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + return rsize; +} + +int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int rsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + // read from fat32 + readblock(lba, block->buf); + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + + list_add_tail(&block->list, head); + + return rsize; +} + +int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _readfile_seek_cache(data, foid, &block); + if (ret < 0) { + ret = _readfile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) { + return 0; + } + + // Read + while (len) { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) { + // cache found + ret = _readfile_cache(data, bckoff, buf, bufoff, len, block); + + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } else { + // Read block from sdcard, create cache + cid = get_next_cluster(data->fat->fat_lba, cid); + + if (cid >= INVALID_CID) { + break; + } + + ret = _readfile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + + +void _do_sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + struct dir_t *dir; + struct long_dir_t *ldir; + unsigned int cid; + int lba, idx, lfnidx; + unsigned char buf[BLOCK_SIZE]; + + data = dirnode->internal; + head = &data->dir->list; + cid = data->cid; + idx = 0; + lfnidx = 1; + + if (cid >= INVALID_CID) { + uart_sendline("fat32 _do_sync_dir: invalid dirnode->data->cid"); + } + + // get the buf from dirnode's offset + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + list_for_each_entry(entry, head, list) { + struct dir_t *origindir; + const char *name; + const char *ext; + int lfn, namelen, extpos, i, buflba; + unsigned char lookupbuf[BLOCK_SIZE]; + + name = entry->name; + + // If entry is a old file, update its size + origindir = __lookup_fat32(dirnode, name, lookupbuf, &buflba); + + if (origindir) { + if (entry->type == FAT_FILE) { + origindir->size = entry->file->size; + writeblock(buflba, lookupbuf); + } + continue; + } + + // Else if entry is a new file + ext = NULL; + extpos = -1; + + do { + + namelen = strlen(name); + if (namelen >= 13) { + lfn = 1; + break; + } + for (i = 0; i < namelen; ++i) { + // get idx of extension name + if (name[namelen - 1 - i] == '.') { + break; + } + } + if (i < namelen) { + ext = &name[namelen - i]; + extpos = namelen - 1 - i; + } + if (i >= 4) { + lfn = 1; + break; + } + if (namelen - 1 - i > 8) { + // SFN: 8.3 + lfn = 1; + break; + } + + lfn = 0; + } while(0); + + // Seek idx to the end of dir + while (1) { + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + if (dir->name[0] == 0) { + break; + } + + idx += 1; + + if (idx >= 16) { // if idx is over Directory Entry, create a new one + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + readblock(lba, buf); + idx = 0; + } + } + + // Write LFN + if (lfn) { + int ord; + int first; + + ord = ((namelen - 1) / 13) + 1; + first = 0x40; // LAST_LONG_ENTRY flag in LFN LDIR_Ord + + for (; ord > 0; --ord) { + int end; + ldir = (struct long_dir_t *)(&buf[sizeof(struct long_dir_t) * idx]); + + ldir->order = first | ord; + ldir->attr = ATTR_LFN; + ldir->type = 0; + // TODO: Calculate checksum, SFN + LFN + ldir->checksum = 0; + ldir->fstcluslo = 0; + + first = 0; + end = 0; + + for (i = 0; i < 10; i += 2) { + if (end) { // padding 0xff if filename end + ldir->name1[i] = 0xff; + ldir->name1[i + 1] = 0xff; + } else { + ldir->name1[i] = name[(ord - 1) * 13 + i / 2]; + ldir->name1[i + 1] = 0; + if (ldir->name1[i] == 0) { + end = 1; + } + } + } + for (i = 0; i < 12; i += 2) { + if (end) { + ldir->name2[i] = 0xff; + ldir->name2[i + 1] = 0xff; + } else { + ldir->name2[i] = name[(ord - 1) * 13 + 5 + i / 2]; + ldir->name2[i + 1] = 0; + if (ldir->name2[i] == 0) { + end = 1; + } + } + } + for (i = 0; i < 4; i += 2) { + if (end) { + ldir->name3[i] = 0xff; + ldir->name3[i + 1] = 0xff; + } else { + ldir->name3[i] = name[(ord - 1) * 13 + 11 + i / 2]; + ldir->name3[i + 1] = 0; + if (ldir->name3[i] == 0) { + end = 1; + } + } + } + + idx += 1; + + if (idx >= 16) { + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + idx = 0; + } + } + } + + // Write SFN + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + // TODO: Set these properties properly + dir->ntres = 0; + dir->crttimetenth = 0; + dir->crttime = 0; + dir->crtdate = 0; + dir->lstaccdate = 0; + dir->wrttime = 0; + dir->wrtdate = 0; + + if (entry->type == FAT_DIR) { + dir->attr = ATTR_DIRECTORY; + dir->size = 0; + } else { + dir->attr = ATTR_ARCHIVE; + dir->size = entry->file->size; + } + + if (entry->cid >= INVALID_CID) { + entry->cid = alloc_cluster(data->fat, 0); + } + + dir->ch = (entry->cid >> 16) & 0xffff; + dir->cl = entry->cid & 0xffff; + + if (lfn) { + int lfni; + + // Creating SFN body + // TODO: handle lfnidx + for (i = 7, lfni = lfnidx; i >= 0 && lfni;) { + dir->name[i--] = '0' + lfni % 10; + lfni /= 10; + } + + lfnidx++; + // numeric-tail: ~n (1 <= n <= 6) + dir->name[i--] = '~'; + + // TODO: handle letter case + memcpy((void *)dir->name, name, i + 1); + } else { + // TODO: handle letter case + for (i = 0; i != extpos && name[i]; ++i) { + dir->name[i] = name[i]; + } + + for (; i < 8; ++i) { + dir->name[i] = ' '; // in SFN, each part is padded with space + } + } + + // SFN format: 8.3 + // TODO: handle letter case + for (i = 0; i < 3 && ext[i]; ++i) { + dir->name[8 + i] = ext[i]; + } + + for (; i < 3; ++i) { + dir->name[8 + i] = ' '; + } + + idx += 1; + + if (idx >= 16) { + int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + // TODO: Cache data block of directory + readblock(lba, buf); + + idx = 0; + } + } + + if (idx) { + writeblock(lba, buf); + } +} + +void _do_sync_file(struct vnode *filenode) +{ + struct fat_file_block_t *entry; + struct fat32_inode *data; + struct list_head *head; + unsigned int cid; + + data = filenode->internal; + head = &data->file->list; + cid = data->cid; + + if (cid >= INVALID_CID) { + //uart_sendline("fat32 _do_sync_file: invalid cid"); + return; + } + + list_for_each_entry(entry, head, list) { + int lba; + + if (entry->oid == 0) { + // cache is valid but not sync'd, just an informational warning + if (!(entry->cid >= INVALID_CID) && data->cid != entry->cid) { + uart_sendline("_do_sync_file: cid isn't sync"); + } + + entry->cid = data->cid; + } + + if (entry->cid >= INVALID_CID) { + entry->cid = alloc_cluster(data->fat, cid); + } + + // if the file is sync'd, pass + if (!entry->isDirty) { + continue; + } + + // cache buf is not updated, initialize it to avoid error + if (!entry->bufIsUpdated) { + memset(entry->buf, 0, BLOCK_SIZE); + entry->bufIsUpdated = 1; + } + + // sync to fat32 fs + lba = data->fat->cluster_lba + (entry->cid - 2) * data->fat->bs.sector_per_cluster; + writeblock(lba, entry->buf); + + entry->isDirty = 0; + + cid = entry->cid; + } +} + +void _sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + + // Init: dirnode is mounted fs + data = dirnode->internal; + head = &data->dir->list; + + _do_sync_dir(dirnode); + + list_for_each_entry(entry, head, list) { + if (entry->type == FAT_DIR) { + _sync_dir(entry->node); // recursive to next dirnode + } else { + _do_sync_file(entry->node); + } + } +} diff --git a/lab8/kernel/src/initramfs.c b/lab8/kernel/src/initramfs.c new file mode 100644 index 000000000..701518ba4 --- /dev/null +++ b/lab8/kernel/src/initramfs.c @@ -0,0 +1,163 @@ +#include "initramfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "cpio.h" +#include "uart1.h" + +struct file_operations initramfs_file_operations = {initramfs_write, initramfs_read, initramfs_open, initramfs_close, initramfs_lseek64,initramfs_getsize}; +struct vnode_operations initramfs_vnode_operations = {initramfs_lookup, initramfs_create, initramfs_mkdir}; + +int register_initramfs() +{ + struct filesystem fs; + fs.name = "initramfs"; + fs.setup_mount = initramfs_setup_mount; + fs.sync = initramfs_sync; + return register_filesystem(&fs); +} + +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = initramfs_create_vnode(0, dir_t); + struct initramfs_inode *ramdir_inode = _mount->root->internal; + + // add all file in initramfs to filesystem + char *filepath; + char *filedata; + unsigned int filesize; + struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + int idx = 0; + + while (header_pointer != 0) + { + int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + //if parse header error + if (error) + { + uart_sendline("%s", "error\r\n"); + break; + } + + //if this is not TRAILER!!! (last of file) + if (header_pointer != 0) + { + // only support file (no dir) + struct vnode * filevnode = initramfs_create_vnode(0, file_t); + struct initramfs_inode *fileinode = filevnode->internal; + fileinode->data = filedata; + fileinode->datasize = filesize; + fileinode->name = filepath; + ramdir_inode->entry[idx++] = filevnode; + } + } + + return 0; +} + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &initramfs_file_operations; + v->v_ops = &initramfs_vnode_operations; + v->mount = _mount; + struct initramfs_inode *inode = kmalloc(sizeof(struct initramfs_inode)); + memset(inode, 0, sizeof(struct initramfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// file operations +int initramfs_write(struct file *file, const void *buf, size_t len) +{ + // read-only + return -1; +} + +int initramfs_read(struct file *file, void *buf, size_t len) +{ + struct initramfs_inode *inode = file->vnode->internal; + + if (len + file->f_pos > inode->datasize) + { + memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); + file->f_pos += inode->datasize - file->f_pos; + return inode->datasize - file->f_pos; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int initramfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +int initramfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long initramfs_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +// vnode operations +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct initramfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode)break; + struct initramfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +int initramfs_sync(struct filesystem *fs) +{ + return 0; +} + +long initramfs_getsize(struct vnode *vd) +{ + struct initramfs_inode *inode = vd->internal; + return inode->datasize; +} diff --git a/lab8/kernel/src/irqtask.c b/lab8/kernel/src/irqtask.c new file mode 100644 index 000000000..fb78201e6 --- /dev/null +++ b/lab8/kernel/src/irqtask.c @@ -0,0 +1,65 @@ +#include "irqtask.h" +#include "exception.h" +#include "memory.h" +#include "uart1.h" + +int curr_task_priority = 9999; +struct list_head *task_list; + +void irqtask_init_list() +{ + task_list = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(task_list); +} + +void irqtask_add(void *task_function,unsigned long long priority){ + + irqtask_t *the_task = kmalloc(sizeof(irqtask_t)); //need to kfree by task runner + the_task->priority = priority; + the_task->task_function = task_function; + + lock(); + struct list_head *curr; + list_for_each(curr, task_list) + { + if (((irqtask_t *)curr)->priority > the_task->priority) + { + list_add(&the_task->listhead, curr->prev); + break; + } + } + if (list_is_head(curr, task_list)) list_add_tail(&(the_task->listhead), task_list); // for the time is the biggest + unlock(); +} + +void irqtask_run_preemptive(){ + while (1) + { + lock(); + if (list_empty(task_list)) + { + unlock(); + break; + } + + irqtask_t *the_task = (irqtask_t *)task_list->next; + if (curr_task_priority <= the_task->priority) + { + unlock(); + break; + } + list_del_entry((struct list_head *)the_task); + int prev_task_priority = curr_task_priority; + curr_task_priority = the_task->priority; + + unlock(); + irqtask_run(the_task); + curr_task_priority = prev_task_priority; + kfree(the_task); + } +} + +void irqtask_run(irqtask_t *the_task) +{ + ((void (*)())the_task->task_function)(); +} diff --git a/lab8/kernel/src/link.ld b/lab8/kernel/src/link.ld new file mode 100644 index 000000000..ee5b2083e --- /dev/null +++ b/lab8/kernel/src/link.ld @@ -0,0 +1,27 @@ +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _kernel_start = .; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + PROVIDE(_data = .); + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + _kernel_end = .; + _heap_start = .; + + . = 0xffff00002c000000; + _stack_end = .; + . = 0xffff00003c000000; + _stack_top = .; + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} +__bss_size = (__bss_end - __bss_start) >> 3; diff --git a/lab8/kernel/src/main.c b/lab8/kernel/src/main.c new file mode 100644 index 000000000..e44684fd8 --- /dev/null +++ b/lab8/kernel/src/main.c @@ -0,0 +1,42 @@ +#include "uart1.h" +#include "shell.h" +#include "dtb.h" +#include "memory.h" +#include "exception.h" +#include "irqtask.h" +#include "timer.h" +#include "sched.h" +#include "vfs.h" + +void main(char* arg){ + char input_buffer[CMD_MAX_LEN]; + + dtb_ptr = PHYS_TO_VIRT(arg); + traverse_device_tree(dtb_ptr, dtb_callback_initramfs); // get initramfs location from dtb + + init_allocator(); + + uart_init(); + irqtask_init_list(); + timer_list_init(); + + init_thread_sched(); + + init_rootfs(); + + uart_interrupt_enable(); + el1_interrupt_enable(); // enable interrupt in EL1 -> EL1 + core_timer_enable(); + +#if DEBUG + cli_cmd_read(input_buffer); // Wait for input, Windows cannot attach to SERIAL from two processes. +#endif + + cli_print_banner(); + while(1){ + cli_cmd_clear(input_buffer, CMD_MAX_LEN); + uart_puts("# "); + cli_cmd_read(input_buffer); + cli_cmd_exec(input_buffer); + } +} diff --git a/lab8/kernel/src/mbox.c b/lab8/kernel/src/mbox.c new file mode 100644 index 000000000..530412d28 --- /dev/null +++ b/lab8/kernel/src/mbox.c @@ -0,0 +1,23 @@ +#include "bcm2837/rpi_mbox.h" +#include "mbox.h" + +/* Aligned to 16-byte boundary while we have 28-bits for VC */ +volatile unsigned int __attribute__((aligned(16))) pt[36]; + +int mbox_call( mbox_channel_type channel, unsigned int value ) +{ + // Add channel to lower 4 bit + value &= ~(0xF); + value |= channel; + while ( (*MBOX_STATUS & BCM_ARM_VC_MS_FULL) != 0 ) {} + // Write to Register + *MBOX_WRITE = value; + while(1) { + while ( *MBOX_STATUS & BCM_ARM_VC_MS_EMPTY ) {} + // Read from Register + if (value == *MBOX_READ) + return pt[1] == MBOX_REQUEST_SUCCEED; + } + return 0; +} + diff --git a/lab8/kernel/src/memory.c b/lab8/kernel/src/memory.c new file mode 100644 index 000000000..8c455652d --- /dev/null +++ b/lab8/kernel/src/memory.c @@ -0,0 +1,380 @@ +#include "memory.h" +#include "list.h" +#include "uart1.h" +#include "exception.h" +#include "dtb.h" +#include "cpio.h" +#include "mmu.h" + +extern char _heap_start; +static char* htop_ptr = &_heap_start; + +extern char _kernel_start; +extern char _kernel_end; +extern char _stack_end; +extern char _stack_top; + +#ifdef DEBUG + #define memory_sendline(fmt, args ...) uart_sendline(fmt, ##args) +#else + #define memory_sendline(fmt, args ...) (void)0 +#endif + +// ------ Lab2 ------ +void* s_allocator(unsigned int size) { + // -> htop_ptr + // htop_ptr + 0x02: heap_block size + // htop_ptr + 0x10 ~ htop_ptr + 0x10 * k: + // { heap_block } + // -> htop_ptr + + // 0x10 for heap_block header + char* r = htop_ptr + 0x10; + // size paddling to multiple of 0x10 + size = 0x10 + size - size % 0x10; + *(unsigned int*)(r - 0x8) = size; + htop_ptr += size; + return r; +} + +void s_free(void* ptr) { + // TBD +} + +// ------ Lab4 ------ +static frame_t* frame_array; // store memory's statement and page's corresponding index +static list_head_t frame_freelist[FRAME_MAX_IDX]; // store available block for page +static list_head_t cache_list[CACHE_MAX_IDX]; // store available block for cache + +void init_allocator() +{ + frame_array = s_allocator(BUDDY_MEMORY_PAGE_COUNT * sizeof(frame_t)); + + // init frame_array + for (int i = 0; i < BUDDY_MEMORY_PAGE_COUNT; i++) + { + if (i % (1 << FRAME_IDX_FINAL) == 0) + { + frame_array[i].val = FRAME_IDX_FINAL; + frame_array[i].used = FRAME_FREE; + } + } + + //init frame freelist + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&frame_freelist[i]); + } + + //init cache list + for (int i = CACHE_IDX_0; i<= CACHE_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&cache_list[i]); + } + + for (int i = 0; i < BUDDY_MEMORY_PAGE_COUNT; i++) + { + // init listhead for each frame + INIT_LIST_HEAD(&frame_array[i].listhead); + frame_array[i].idx = i; + frame_array[i].cache_order = CACHE_NONE; + + // add init frame (FRAME_IDX_FINAL) into freelist + if (i % (1 << FRAME_IDX_FINAL) == 0) + { + list_add(&frame_array[i].listhead, &frame_freelist[FRAME_IDX_FINAL]); + } + } + + /* Startup reserving the following region: + Spin tables for multicore boot (0x0000 - 0x1000) + Devicetree (Optional, if you have implement it) + Kernel image in the physical memory + Your simple allocator (startup allocator) (Stack + Heap in my case) + Initramfs + */ + memory_sendline("\r\n* Startup Allocation *\r\n"); + memory_sendline("buddy system: usable memory region: 0x%x ~ 0x%x\n", BUDDY_MEMORY_BASE, BUDDY_MEMORY_BASE + BUDDY_MEMORY_PAGE_COUNT * PAGESIZE); + dtb_find_and_store_reserved_memory(); // find spin tables in dtb + memory_reserve(PHYS_TO_VIRT(MMU_PGD_ADDR), PHYS_TO_VIRT(MMU_PTE_ADDR+0x2000)); // // PGD's page frame at 0x1000 // PUD's page frame at 0x2000 PMD 0x3000-0x5000 + memory_reserve((unsigned long long)&_kernel_start, (unsigned long long)&_kernel_end); // kernel + memory_reserve((unsigned long long)&_stack_end, (unsigned long long)&_stack_top); // heap & stack -> simple allocator + memory_reserve((unsigned long long)CPIO_DEFAULT_START, (unsigned long long)CPIO_DEFAULT_END); +} + +void* page_malloc(unsigned int size) +{ + memory_sendline(" [+] Allocate page - size : %d(0x%x)\r\n", size, size); + memory_sendline(" Before\r\n"); + dump_page_info(); + int val; + // turn size into minimum 4KB * 2**val + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + + if (size <= (PAGESIZE << i)) + { + val = i; + memory_sendline(" block size = 0x%x\n", PAGESIZE << i); + break; + } + + if ( i == FRAME_IDX_FINAL) + { + memory_sendline("[!] request size exceeded for page_malloc!!!!\r\n"); + return (void*)0; + } + + } + + // find the smallest larger frame in freelist + int target_val; + for (target_val = val; target_val <= FRAME_IDX_FINAL; target_val++) + { + // freelist does not have 2**i order frame, going for next order + if (!list_empty(&frame_freelist[target_val])) + break; + } + if (target_val > FRAME_IDX_FINAL) + { + memory_sendline("[!] No available frame in freelist, page_malloc ERROR!!!!\r\n"); + return (void*)0; + } + + // get the available frame from freelist + frame_t *target_frame_ptr = (frame_t*)frame_freelist[target_val].next; + list_del_entry((struct list_head *)target_frame_ptr); + + // Release redundant memory block to separate into pieces + for (int j = target_val; j > val; j--) // ex: 10000 -> 01111 + { + release_redundant(target_frame_ptr); + } + + // Allocate it + target_frame_ptr->used = FRAME_ALLOCATED; + memory_sendline(" physical address : 0x%x\n", BUDDY_MEMORY_BASE + (PAGESIZE*(target_frame_ptr->idx))); + memory_sendline(" After\r\n"); + dump_page_info(); + + return (void *) BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx)); +} + +void page_free(void* ptr) +{ + frame_t *target_frame_ptr = &frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12]; // PAGESIZE * Available Region -> 0x1000 * 0x10000000 // SPEC #1, #2 + memory_sendline(" [+] Free page: 0x%x, val = %d\r\n",ptr, target_frame_ptr->val); + memory_sendline(" Before\r\n"); + dump_page_info(); + target_frame_ptr->used = FRAME_FREE; + frame_t* temp; + while ((temp = coalesce(target_frame_ptr)) != (frame_t *)-1)target_frame_ptr = temp; + list_add(&target_frame_ptr->listhead, &frame_freelist[target_frame_ptr->val]); + memory_sendline(" After\r\n"); + dump_page_info(); +} + +frame_t* release_redundant(frame_t *frame) +{ + // order -1 -> add its buddy to free list (frame itself will be used in master function) + frame->val -= 1; + frame_t *buddyptr = get_buddy(frame); + buddyptr->val = frame->val; + list_add(&buddyptr->listhead, &frame_freelist[buddyptr->val]); + return frame; +} + +frame_t* get_buddy(frame_t *frame) +{ + // XOR(idx, order) + return &frame_array[frame->idx ^ (1 << frame->val)]; +} + +frame_t* coalesce(frame_t *frame_ptr) +{ + frame_t *buddy = get_buddy(frame_ptr); + // frame is the boundary + if (frame_ptr->val == FRAME_IDX_FINAL) + return (frame_t*)-1; + + // Order must be the same: 2**i + 2**i = 2**(i+1) + if (frame_ptr->val != buddy->val) + return (frame_t*)-1; + + // buddy is in used + if (buddy->used == FRAME_ALLOCATED) + return (frame_t*)-1; + + list_del_entry((struct list_head *)buddy); + frame_ptr->val += 1; + buddy->val += 1; + memory_sendline(" coalesce detected, merging 0x%x, 0x%x, -> val = %d\r\n", frame_ptr->idx, buddy->idx, frame_ptr->val); + return buddy < frame_ptr ? buddy : frame_ptr; +} + +void dump_page_info(){ + unsigned int exp2 = 1; + memory_sendline(" ----------------- [ Number of Available Page Blocks ] -----------------\r\n | "); + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + memory_sendline("%4dKB(%1d) ", 4*exp2, i); + exp2 *= 2; + } + memory_sendline("|\r\n | "); + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + memory_sendline(" %4d ", list_size(&frame_freelist[i])); + memory_sendline("|\r\n"); +} + +void dump_cache_info() +{ + unsigned int exp2 = 1; + memory_sendline(" -- [ Number of Available Cache Blocks ] --\r\n | "); + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + memory_sendline("%4dB(%1d) ", 32*exp2, i); + exp2 *= 2; + } + memory_sendline("|\r\n | "); + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + memory_sendline(" %5d ", list_size(&cache_list[i])); + memory_sendline("|\r\n"); +} + +void page2caches(int order) +{ + // make caches from a smallest-size page + char *page = page_malloc(PAGESIZE); + frame_t *pageframe_ptr = &frame_array[((unsigned long long)page - BUDDY_MEMORY_BASE) >> 12]; + pageframe_ptr->cache_order = order; + + // split page into a lot of caches and push them into cache_list + int cachesize = (32 << order); + for (int i = 0; i < PAGESIZE; i += cachesize) + { + list_head_t *c = (list_head_t *)(page + i); + list_add(c, &cache_list[order]); + } +} + +void* cache_malloc(unsigned int size) +{ + memory_sendline("[+] Allocate cache - size : %d(0x%x)\r\n", size, size); + memory_sendline(" Before\r\n"); + dump_cache_info(); + + // turn size into cache order: 32B * 2**order + int order; + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + if (size <= (32 << i)) { order = i; break; } + } + + // if no available cache in list, assign one page for it + if (list_empty(&cache_list[order])) + { + page2caches(order); + } + + list_head_t* r = cache_list[order].next; + list_del_entry(r); + memory_sendline(" physical address : 0x%x\n", r); + memory_sendline(" After\r\n"); + dump_cache_info(); + return r; +} + +void cache_free(void *ptr) +{ + list_head_t *c = (list_head_t *)ptr; + frame_t *pageframe_ptr = &frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12]; + memory_sendline("[+] Free cache: 0x%x, val = %d\r\n",ptr, pageframe_ptr->cache_order); + memory_sendline(" Before\r\n"); + dump_cache_info(); + list_add(c, &cache_list[pageframe_ptr->cache_order]); + memory_sendline(" After\r\n"); + dump_cache_info(); +} + +void *kmalloc(unsigned int size) +{ + lock(); + memory_sendline("\n\n"); + memory_sendline("================================\r\n"); + memory_sendline("[+] Request kmalloc size: %d\r\n", size); + memory_sendline("================================\r\n"); + // if size is larger than cache size, go for page + if (size > (32 << CACHE_IDX_FINAL)) + { + void *r = page_malloc(size); + unlock(); + return r; + } + // go for cache + void *r = cache_malloc(size); + unlock(); + return r; +} + +void kfree(void *ptr) +{ + lock(); + memory_sendline("\n\n"); + memory_sendline("==========================\r\n"); + memory_sendline("[+] Request kfree 0x%x\r\n", ptr); + memory_sendline("==========================\r\n"); + // If no cache assigned, go for page + if ((unsigned long long)ptr % PAGESIZE == 0 && frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12].cache_order == CACHE_NONE) + { + page_free(ptr); + unlock(); + return; + } + // go for cache + cache_free(ptr); + unlock(); +} + +void memory_reserve(unsigned long long start, unsigned long long end) +{ + start -= start % PAGESIZE; // floor (align 0x1000) + end = end % PAGESIZE ? end + PAGESIZE - (end % PAGESIZE) : end; // ceiling (align 0x1000) + + uart_sendline("Reserved Memory: "); + uart_sendline("start 0x%x ~ ", start); + uart_sendline("end 0x%x\r\n",end); + + // delete page from free list + for (int order = FRAME_IDX_FINAL; order >= 0; order--) + { + list_head_t *pos; + list_for_each(pos, &frame_freelist[order]) + { + unsigned long long pagestart = ((frame_t *)pos)->idx * PAGESIZE + BUDDY_MEMORY_BASE; + unsigned long long pageend = pagestart + (PAGESIZE << order); + + if (start <= pagestart && end >= pageend) // if page all in reserved memory -> delete it from freelist + { + ((frame_t *)pos)->used = FRAME_ALLOCATED; + memory_sendline(" [!] Reserved page in 0x%x - 0x%x\n", pagestart, pageend); + memory_sendline(" Before\n"); + dump_page_info(); + list_del_entry(pos); + memory_sendline(" Remove usable block for reserved memory: order %d\r\n", order); + memory_sendline(" After\n"); + dump_page_info(); + } + else if (start >= pageend || end <= pagestart) // no intersection + { + continue; + } + else // partial intersection, separate the page into smaller size. + { + list_del_entry(pos); + list_head_t *temppos = pos -> prev; + list_add(&release_redundant((frame_t *)pos)->listhead, &frame_freelist[order - 1]); + pos = temppos; + } + } + } +} diff --git a/lab8/kernel/src/mmu.c b/lab8/kernel/src/mmu.c new file mode 100644 index 000000000..d6a9942bc --- /dev/null +++ b/lab8/kernel/src/mmu.c @@ -0,0 +1,166 @@ +#include "bcm2837/rpi_mmu.h" +#include "mmu.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" + +void* set_2M_kernel_mmu(void* x0) +{ + // Turn + // Two-level Translation (1GB) - in boot.S + // to + // Three-level Translation (2MB) - set PUD point to new table + unsigned long *pud_table = (unsigned long *) MMU_PUD_ADDR; + + unsigned long *pte_table1 = (unsigned long *) MMU_PTE_ADDR; + unsigned long *pte_table2 = (unsigned long *)(MMU_PTE_ADDR + 0x1000L); + for (int i = 0; i < 512; i++) + { + unsigned long addr = 0x200000L * i; + if ( addr >= PERIPHERAL_END ) + { + pte_table1[i] = ( 0x00000000 + addr ) + BOOT_PTE_ATTR_nGnRnE; + continue; + } + pte_table1[i] = (0x00000000 + addr ) | BOOT_PTE_ATTR_NOCACHE; // 0 * 2MB // No definition for 3-level attribute, use nocache. + pte_table2[i] = (0x40000000 + addr ) | BOOT_PTE_ATTR_NOCACHE; // 512 * 2MB + } + + // set PUD + pud_table[0] = (unsigned long) pte_table1 | BOOT_PUD_ATTR; + pud_table[1] = (unsigned long) pte_table2 | BOOT_PUD_ATTR; + + return x0; +} + +void map_one_page(size_t *virt_pgd_p, size_t va, size_t pa, size_t flag) +{ + size_t *table_p = virt_pgd_p; + for (int level = 0; level < 4; level++) + { + unsigned int idx = (va >> (39 - level * 9)) & 0x1ff; // p.14, 9-bit only + + if (level == 3) + { + table_p[idx] = pa; + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_KNX | flag; // el0 only + return; + } + + if(!table_p[idx]) + { + size_t* newtable_p =kmalloc(0x1000); // create a table + memset(newtable_p, 0, 0x1000); + table_p[idx] = VIRT_TO_PHYS((size_t)newtable_p); // point to that table + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + table_p = (size_t*)PHYS_TO_VIRT((size_t)(table_p[idx] & ENTRY_ADDR_MASK)); // PAGE_SIZE + } +} + + +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced) +{ + size = size % 0x1000 ? size + (0x1000 - size % 0x1000) : size; + vm_area_struct_t* new_area = kmalloc(sizeof(vm_area_struct_t)); + new_area->rwx = rwx; + new_area->area_size = size; + new_area->virt_addr = va; + new_area->phys_addr = pa; + new_area->is_alloced = is_alloced; + list_add_tail((list_head_t *)new_area, &t->vma_list); +} + +void mmu_del_vma(struct thread *t) +{ + list_head_t *pos = t->vma_list.next; + vm_area_struct_t *vma; + while(pos != &t->vma_list){ + vma = (vm_area_struct_t *)pos; + if (vma->is_alloced) + kfree((void*)PHYS_TO_VIRT(vma->phys_addr)); + list_head_t* next_pos = pos->next; + kfree(pos); + pos = next_pos; + } +} + +void mmu_map_pages(size_t *virt_pgd_p, size_t va, size_t size, size_t pa, size_t flag) +{ + pa = pa - (pa % 0x1000); // align + for (size_t s = 0; s < size; s+=0x1000) + { + map_one_page(virt_pgd_p, va + s, pa + s, flag); + } +} + +void mmu_free_page_tables(size_t *page_table, int level) +{ + size_t *table_virt = (size_t*)PHYS_TO_VIRT((char*)page_table); + for (int i = 0; i < 512; i++) + { + if (table_virt[i] != 0) + { + size_t *next_table = (size_t*)(table_virt[i] & ENTRY_ADDR_MASK); + if (table_virt[i] & PD_TABLE) + { + if(level!=2)mmu_free_page_tables(next_table, level + 1); + table_virt[i] = 0L; + kfree(PHYS_TO_VIRT((char *)next_table)); + } + } + } +} + +void mmu_memfail_abort_handle(esr_el1_t* esr_el1) +{ + unsigned long long far_el1; + __asm__ __volatile__("mrs %0, FAR_EL1\n\t": "=r"(far_el1)); + + list_head_t *pos; + vm_area_struct_t *vma; + vm_area_struct_t *the_area_ptr = 0; + list_for_each(pos, &curr_thread->vma_list) + { + vma = (vm_area_struct_t *)pos; + if (vma->virt_addr <= far_el1 && vma->virt_addr + vma->area_size >= far_el1) + { + the_area_ptr = vma; + break; + } + } + // area is not part of process's address space + if (!the_area_ptr) + { + uart_sendline("[Segmentation fault]: Kill Process\r\n"); + thread_exit(); + return; + } + + // For translation fault, only map one page frame for the fault address + if ((esr_el1->iss & 0x3f) == TF_LEVEL0 || + (esr_el1->iss & 0x3f) == TF_LEVEL1 || + (esr_el1->iss & 0x3f) == TF_LEVEL2 || + (esr_el1->iss & 0x3f) == TF_LEVEL3) + { + //uart_sendline("[Translation fault]: 0x%x\r\n",far_el1); // far_el1: Fault address register. + // Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment fault and Watchpoint exceptions that are taken to EL1. + + size_t addr_offset = (far_el1 - the_area_ptr->virt_addr); + addr_offset = (addr_offset % 0x1000) == 0 ? addr_offset : addr_offset - (addr_offset % 0x1000); + + size_t flag = 0; + if(!(the_area_ptr->rwx & (0b1 << 2))) flag |= PD_UNX; // 4: executable + if(!(the_area_ptr->rwx & (0b1 << 1))) flag |= PD_RDONLY; // 2: writable + if( the_area_ptr->rwx & (0b1 << 0) ) flag |= PD_UK_ACCESS; // 1: readable / accessible + map_one_page(PHYS_TO_VIRT(curr_thread->context.pgd), the_area_ptr->virt_addr + addr_offset, the_area_ptr->phys_addr + addr_offset, flag); + } + else + { + // For other Fault (permisson ...etc) + uart_sendline("[Segmentation fault]: Kill Process\r\n"); + thread_exit(); + } + +} diff --git a/lab8/kernel/src/sched.S b/lab8/kernel/src/sched.S new file mode 100644 index 000000000..6b7d930c3 --- /dev/null +++ b/lab8/kernel/src/sched.S @@ -0,0 +1,59 @@ +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + //mrs x9, ttbr0_el1 + //str x9, [x0, 16 * 6 + 8] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldp x9, x0, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + + dsb ish // ensure write has completed, lock for context switch + msr ttbr0_el1, x0 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries in stage 1, el1 and inner shareable + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global store_context +store_context: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + ret + +.global load_context +load_context: + ldp x19, x20, [x0, 16 * 0] + ldp x21, x22, [x0, 16 * 1] + ldp x23, x24, [x0, 16 * 2] + ldp x25, x26, [x0, 16 * 3] + ldp x27, x28, [x0, 16 * 4] + ldp fp, lr, [x0, 16 * 5] + ldr x9, [x0, 16 * 6] + mov sp, x9 + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret diff --git a/lab8/kernel/src/sched.c b/lab8/kernel/src/sched.c new file mode 100644 index 000000000..016f92c8c --- /dev/null +++ b/lab8/kernel/src/sched.c @@ -0,0 +1,179 @@ +#include "sched.h" +#include "exception.h" +#include "memory.h" +#include "timer.h" +#include "uart1.h" +#include "signal.h" +#include "mmu.h" +#include "string.h" + +thread_t *curr_thread; +list_head_t *run_queue; +list_head_t *wait_queue; +thread_t threads[PIDMAX + 1]; + +void init_thread_sched() +{ + lock(); + run_queue = kmalloc(sizeof(list_head_t)); + wait_queue = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(run_queue); + INIT_LIST_HEAD(wait_queue); + + //init pids + for (int i = 0; i <= PIDMAX; i++) + { + threads[i].isused = 0; + threads[i].pid = i; + threads[i].iszombie = 0; + } + + thread_t* idlethread = thread_create(idle,0x1000); + curr_thread = idlethread; + asm volatile("msr tpidr_el1, %0" ::"r" (&idlethread->context)); + unlock(); +} + +void idle(){ + while(1) + { + kill_zombies(); //reclaim threads marked as DEAD + schedule(); //switch to next thread in run queue + } +} + +void schedule(){ + lock(); + do{ + curr_thread = (thread_t *)curr_thread->listhead.next; + } while (list_is_head(&curr_thread->listhead, run_queue) || curr_thread->iszombie); + unlock(); + switch_to(get_current(), &curr_thread->context); +} + +void kill_zombies(){ + lock(); + list_head_t *curr; + thread_t *t; + list_for_each(curr,run_queue) + { + t = (thread_t *)curr; + if (t->iszombie) + { + list_del_entry(curr); + mmu_free_page_tables(t->context.pgd,0); + mmu_del_vma(t); + for(int i = 0; i < MAX_FD;i++) + { + if (t->file_descriptors_table[i]) + vfs_close(t->file_descriptors_table[i]); + } + kfree(t->kernel_stack_alloced_ptr); + kfree(PHYS_TO_VIRT(t->context.pgd)); + t->iszombie = 0; + t->isused = 0; + } + } + unlock(); +} + +int thread_exec(char *data, unsigned int filesize) +{ + thread_t *t = thread_create(data, filesize); + + mmu_add_vma(t, USER_KERNEL_BASE, t->datasize, (size_t)VIRT_TO_PHYS(t->data) , 0b111, 1); + mmu_add_vma(t, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)VIRT_TO_PHYS(t->stack_alloced_ptr), 0b111, 1); + mmu_add_vma(t, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0); + mmu_add_vma(t, USER_SIGNAL_WRAPPER_VA, 0x2000, (size_t)VIRT_TO_PHYS(signal_handler_wrapper), 0b101, 0); + + t->context.pgd = VIRT_TO_PHYS(t->context.pgd); + t->context.sp = USER_STACK_BASE; + t->context.fp = USER_STACK_BASE; + t->context.lr = USER_KERNEL_BASE; + + //copy file into data + for (int i = 0; i < filesize;i++) + { + t->data[i] = data[i]; + } + + //disable echo when going to userspace + curr_thread = t; + + vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[0]); // stdin + vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[1]); // stdout + vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[2]); // stderr + + //disable echo when going to userspace + add_timer(schedule_timer, 1, "", 0); + // eret to exception level 0 + asm("msr tpidr_el1, %0\n\t" + "msr elr_el1, %1\n\t" + "msr spsr_el1, xzr\n\t" // enable interrupt in EL0. You can do it by setting spsr_el1 to 0 before returning to EL0. + "msr sp_el0, %2\n\t" + "mov sp, %3\n\t" + "dsb ish\n\t" // ensure write has completed + "msr ttbr0_el1, %4\n\t" + "tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t" // clear pipeline" + "eret\n\t" ::"r"(&t->context),"r"(t->context.lr), "r"(t->context.sp), "r"(t->kernel_stack_alloced_ptr + KSTACK_SIZE), "r"(t->context.pgd)); + + return 0; +} + + +//malloc a kstack and a userstack +thread_t *thread_create(void *start, unsigned int filesize) +{ + lock(); + + thread_t *r; + for (int i = 0; i <= PIDMAX; i++) + { + if (!threads[i].isused) + { + r = &threads[i]; + break; + } + } + INIT_LIST_HEAD(&r->vma_list); + r->iszombie = 0; + r->isused = 1; + r->context.lr = (unsigned long long)start; + r->stack_alloced_ptr = kmalloc(USTACK_SIZE); + r->kernel_stack_alloced_ptr = kmalloc(KSTACK_SIZE); + r->signal_is_checking = 0; + r->data = kmalloc(filesize); + r->datasize = filesize; + r->context.sp = (unsigned long long)r->kernel_stack_alloced_ptr + KSTACK_SIZE; + r->context.fp = r->context.sp; + strcpy(r->curr_working_dir, "/"); + + r->context.pgd = kmalloc(0x1000); + memset(r->context.pgd, 0, 0x1000); + + //initial signal handler with signal_default_handler (kill thread) + for (int i = 0; i < SIGNAL_MAX; i++) + { + r->signal_handler[i] = signal_default_handler; + r->sigcount[i] = 0; + } + + list_add(&r->listhead, run_queue); + unlock(); + return r; +} + +void thread_exit(){ + lock(); + curr_thread->iszombie = 1; + unlock(); + schedule(); +} + +void schedule_timer(char* notuse){ + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t": "=r"(cntfrq_el0)); //tick frequency + add_timer(schedule_timer, cntfrq_el0 >> 5, "", 1); +} diff --git a/lab8/kernel/src/sdhost.c b/lab8/kernel/src/sdhost.c new file mode 100644 index 000000000..ba0ed32b8 --- /dev/null +++ b/lab8/kernel/src/sdhost.c @@ -0,0 +1,243 @@ +// mmio +#define KVA 0xffff000000000000 +#define MMIO_BASE (KVA + 0x3f000000) + +// SD card command +#define GO_IDLE_STATE 0 +#define SEND_OP_CMD 1 +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 +#define SELECT_CARD 7 +#define SEND_IF_COND 8 + #define VOLTAGE_CHECK_PATTERN 0x1aa +#define STOP_TRANSMISSION 12 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define WRITE_SINGLE_BLOCK 24 +#define SD_APP_OP_COND 41 + #define SDCARD_3_3V (1 << 21) + #define SDCARD_ISHCS (1 << 30) + #define SDCARD_READY (1 << 31) +#define APP_CMD 55 + +// gpio +#define GPIO_BASE (MMIO_BASE + 0x200000) +#define GPIO_GPFSEL4 (GPIO_BASE + 0x10) +#define GPIO_GPFSEL5 (GPIO_BASE + 0x14) +#define GPIO_GPPUD (GPIO_BASE + 0x94) +#define GPIO_GPPUDCLK1 (GPIO_BASE + 0x9c) + +// sdhost +#define SDHOST_BASE (MMIO_BASE + 0x202000) +#define SDHOST_CMD (SDHOST_BASE + 0) + #define SDHOST_READ 0x40 + #define SDHOST_WRITE 0x80 + #define SDHOST_LONG_RESPONSE 0x200 + #define SDHOST_NO_REPONSE 0x400 + #define SDHOST_BUSY 0x800 + #define SDHOST_NEW_CMD 0x8000 +#define SDHOST_ARG (SDHOST_BASE + 0x4) +#define SDHOST_TOUT (SDHOST_BASE + 0x8) + #define SDHOST_TOUT_DEFAULT 0xf00000 +#define SDHOST_CDIV (SDHOST_BASE + 0xc) + #define SDHOST_CDIV_MAXDIV 0x7ff + #define SDHOST_CDIV_DEFAULT 0x148 +#define SDHOST_RESP0 (SDHOST_BASE + 0x10) +#define SDHOST_RESP1 (SDHOST_BASE + 0x14) +#define SDHOST_RESP2 (SDHOST_BASE + 0x18) +#define SDHOST_RESP3 (SDHOST_BASE + 0x1c) +#define SDHOST_HSTS (SDHOST_BASE + 0x20) + #define SDHOST_HSTS_MASK (0x7f8) + #define SDHOST_HSTS_ERR_MASK (0xf8) + #define SDHOST_HSTS_DATA (1 << 0) +#define SDHOST_PWR (SDHOST_BASE + 0x30) +#define SDHOST_DBG (SDHOST_BASE + 0x34) + #define SDHOST_DBG_FSM_DATA 1 + #define SDHOST_DBG_FSM_MASK 0xf + #define SDHOST_DBG_MASK (0x1f << 14 | 0x1f << 9) + #define SDHOST_DBG_FIFO (0x4 << 14 | 0x4 << 9) +#define SDHOST_CFG (SDHOST_BASE + 0x38) + #define SDHOST_CFG_DATA_EN (1 << 4) + #define SDHOST_CFG_SLOW (1 << 3) + #define SDHOST_CFG_INTBUS (1 << 1) +#define SDHOST_SIZE (SDHOST_BASE + 0x3c) +#define SDHOST_DATA (SDHOST_BASE + 0x40) +#define SDHOST_CNT (SDHOST_BASE + 0x50) + +// helper +#define set(io_addr, val) \ + asm volatile("str %w1, [%0]" ::"r"(io_addr), "r"(val) : "memory"); + +#define get(io_addr, val) \ + asm volatile("ldr %w0, [%1]" : "=r"(val) : "r"(io_addr) : "memory"); + +static inline void delay(unsigned long tick) { + while (tick--) { + asm volatile("nop"); + } +} + +static int is_hcs; // high capcacity(SDHC) + +static void pin_setup() { + set(GPIO_GPFSEL4, 0x24000000); + set(GPIO_GPFSEL5, 0x924); + set(GPIO_GPPUD, 0); + delay(15000); + set(GPIO_GPPUDCLK1, 0xffffffff); + delay(15000); + set(GPIO_GPPUDCLK1, 0); +} + +static void sdhost_setup() { + unsigned int tmp; + set(SDHOST_PWR, 0); + set(SDHOST_CMD, 0); + set(SDHOST_ARG, 0); + set(SDHOST_TOUT, SDHOST_TOUT_DEFAULT); + set(SDHOST_CDIV, 0); + set(SDHOST_HSTS, SDHOST_HSTS_MASK); + set(SDHOST_CFG, 0); + set(SDHOST_CNT, 0); + set(SDHOST_SIZE, 0); + get(SDHOST_DBG, tmp); + tmp &= ~SDHOST_DBG_MASK; + tmp |= SDHOST_DBG_FIFO; + set(SDHOST_DBG, tmp); + delay(250000); + set(SDHOST_PWR, 1); + delay(250000); + set(SDHOST_CFG, SDHOST_CFG_SLOW | SDHOST_CFG_INTBUS | SDHOST_CFG_DATA_EN); + set(SDHOST_CDIV, SDHOST_CDIV_DEFAULT); +} + +static int wait_sd() { + int cnt = 1000000; + unsigned int cmd; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_CMD, cmd); + --cnt; + } while (cmd & SDHOST_NEW_CMD); + return 0; +} + +static int sd_cmd(unsigned cmd, unsigned int arg) { + set(SDHOST_ARG, arg); + set(SDHOST_CMD, cmd | SDHOST_NEW_CMD); + return wait_sd(); +} + +static int sdcard_setup() { + unsigned int tmp; + sd_cmd(GO_IDLE_STATE | SDHOST_NO_REPONSE, 0); + sd_cmd(SEND_IF_COND, VOLTAGE_CHECK_PATTERN); + get(SDHOST_RESP0, tmp); + if (tmp != VOLTAGE_CHECK_PATTERN) { + return -1; + } + while (1) { + if (sd_cmd(APP_CMD, 0) == -1) { + // MMC card or invalid card status + // currently not support + continue; + } + sd_cmd(SD_APP_OP_COND, SDCARD_3_3V | SDCARD_ISHCS); + get(SDHOST_RESP0, tmp); + if (tmp & SDCARD_READY) { + break; + } + delay(1000000); + } + + is_hcs = tmp & SDCARD_ISHCS; + sd_cmd(ALL_SEND_CID | SDHOST_LONG_RESPONSE, 0); + sd_cmd(SEND_RELATIVE_ADDR, 0); + get(SDHOST_RESP0, tmp); + sd_cmd(SELECT_CARD, tmp); + sd_cmd(SET_BLOCKLEN, 512); + return 0; +} + +static int wait_fifo() { + int cnt = 1000000; + unsigned int hsts; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_HSTS, hsts); + --cnt; + } while ((hsts & SDHOST_HSTS_DATA) == 0); + return 0; +} + +static void set_block(int size, int cnt) { + set(SDHOST_SIZE, size); + set(SDHOST_CNT, cnt); +} + +static void wait_finish() { + unsigned int dbg; + do { + get(SDHOST_DBG, dbg); + } while ((dbg & SDHOST_DBG_FSM_MASK) != SDHOST_HSTS_DATA); +} + +void readblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(READ_SINGLE_BLOCK | SDHOST_READ, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + get(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void writeblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(WRITE_SINGLE_BLOCK | SDHOST_WRITE, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + set(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void sd_init() { + pin_setup(); + sdhost_setup(); + sdcard_setup(); +} diff --git a/lab8/kernel/src/shell.c b/lab8/kernel/src/shell.c new file mode 100644 index 000000000..35fffdde8 --- /dev/null +++ b/lab8/kernel/src/shell.c @@ -0,0 +1,220 @@ +#include +#include "shell.h" +#include "uart1.h" +#include "mbox.h" +#include "power.h" +#include "cpio.h" +#include "string.h" +#include "dtb.h" +#include "memory.h" +#include "timer.h" +#include "sched.h" + +#define CLI_MAX_CMD 9 + +extern int uart_recv_echo_flag; +extern char* dtb_ptr; +extern void* CPIO_DEFAULT_START; + +struct CLI_CMDS cmd_list[CLI_MAX_CMD]= +{ + {.command="cat", .help="concatenate files and print on the standard output"}, + {.command="dtb", .help="show device tree"}, + {.command="exec", .help="execute a command, replacing current image with a new image"}, + {.command="hello", .help="print Hello World!"}, + {.command="help", .help="print all available commands"}, + {.command="info", .help="get device information via mailbox"}, + {.command="ls", .help="list directory contents"}, + {.command="setTimeout", .help="setTimeout [MESSAGE] [SECONDS]"}, + {.command="reboot", .help="reboot the device"} +}; + +void cli_cmd_clear(char* buffer, int length) +{ + for(int i=0; i= CMD_MAX_LEN ) break; + c = uart_async_getc(); + if ( c == '\n') break; + buffer[idx++] = c; + } +} + +void cli_cmd_exec(char* buffer) +{ + if (!buffer) return; + + char* cmd = buffer; + char* argvs = str_SepbySpace(buffer); + + if (strcmp(cmd, "cat") == 0) { + do_cmd_cat(argvs); + } else if (strcmp(cmd, "dtb") == 0){ + do_cmd_dtb(); + } else if (strcmp(cmd, "exec") == 0){ + do_cmd_exec(argvs); + } else if (strcmp(cmd, "hello") == 0) { + do_cmd_hello(); + } else if (strcmp(cmd, "help") == 0) { + do_cmd_help(); + } else if (strcmp(cmd, "info") == 0) { + do_cmd_info(); + } else if (strcmp(cmd, "ls") == 0) { + do_cmd_ls(argvs); + } else if (strcmp(cmd, "setTimeout") == 0) { + char* sec = str_SepbySpace(argvs); + do_cmd_setTimeout(argvs, sec); + } else if (strcmp(cmd, "reboot") == 0) { + do_cmd_reboot(); + } +} + +void cli_print_banner() +{ + //uart_puts("\r\n"); + //uart_puts("=======================================\r\n"); + //uart_puts(" Welcome to NYCU-OSC 2023 Lab8 Shell \r\n"); + //uart_puts("=======================================\r\n"); + uart_puts("Lab8:\r\n"); +} + +void do_cmd_cat(char* filepath) +{ + char* c_filepath; + char* c_filedata; + unsigned int c_filesize; + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; + + while(header_ptr!=0) + { + int error = cpio_newc_parse_header(header_ptr, &c_filepath, &c_filesize, &c_filedata, &header_ptr); + if(error) break; + if(strcmp(c_filepath, filepath)==0) + { + uart_puts("%s", c_filedata); + break; + } + if(header_ptr==0) uart_puts("cat: %s: No such file or directory\n", filepath); + } +} + +void do_cmd_dtb() +{ + traverse_device_tree(dtb_ptr, dtb_callback_show_tree); +} + +void do_cmd_help() +{ + for(int i = 0; i < CLI_MAX_CMD; i++) + { + uart_puts(cmd_list[i].command); + uart_puts("\t\t\t: "); + uart_puts(cmd_list[i].help); + uart_puts("\r\n"); + } +} + +void do_cmd_exec(char* filepath) +{ + char* c_filepath; + char* c_filedata; + unsigned int c_filesize; + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; + + while(header_ptr!=0) + { + int error = cpio_newc_parse_header(header_ptr, &c_filepath, &c_filesize, &c_filedata, &header_ptr); + if(error) break; + + if(strcmp(c_filepath, filepath)==0) + { + uart_recv_echo_flag = 0; // syscall.img has different mechanism on uart I/O. + thread_exec(c_filedata, c_filesize); + } + if(header_ptr==0) uart_puts("cat: %s: No such file or directory\n", filepath); + } + +} + +void do_cmd_hello() +{ + uart_puts("Hello World!\r\n"); +} + +void do_cmd_info() +{ + // print hw revision + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_BOARD_REVISION; + pt[3] = 4; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)) ) { + uart_puts("Hardware Revision\t: "); + uart_2hex(pt[6]); + uart_2hex(pt[5]); + uart_puts("\r\n"); + } + // print arm memory + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_ARM_MEMORY; + pt[3] = 8; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)) ) { + uart_puts("ARM Memory Base Address\t: "); + uart_2hex(pt[5]); + uart_puts("\r\n"); + uart_puts("ARM Memory Size\t\t: "); + uart_2hex(pt[6]); + uart_puts("\r\n"); + } +} + +void do_cmd_ls(char* workdir) +{ + char* c_filepath; + char* c_filedata; + unsigned int c_filesize; + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; + + while(header_ptr!=0) + { + int error = cpio_newc_parse_header(header_ptr, &c_filepath, &c_filesize, &c_filedata, &header_ptr); + if(error) break; + if(header_ptr!=0) uart_puts("%s\n", c_filepath); + } +} + +void do_cmd_setTimeout(char* msg, char* sec) +{ + add_timer(uart_sendline,atoi(sec),msg,0); +} + +void do_cmd_reboot() +{ + uart_puts("Reboot in 5 seconds ...\r\n\r\n"); + volatile unsigned int* rst_addr = (unsigned int*)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x20; + volatile unsigned int* wdg_addr = (unsigned int*)PM_WDOG; + *wdg_addr = PM_PASSWORD | 5; +} + diff --git a/lab8/kernel/src/signal.c b/lab8/kernel/src/signal.c new file mode 100644 index 000000000..d98309abe --- /dev/null +++ b/lab8/kernel/src/signal.c @@ -0,0 +1,68 @@ +#include "signal.h" +#include "sched.h" +#include "syscall.h" +#include "memory.h" +#include "mmu.h" + +void check_signal(trapframe_t *tpf) +{ + lock(); + if(curr_thread->signal_is_checking) + { + unlock(); + return; + } + //prevent nested running signal handler + curr_thread->signal_is_checking = 1; + unlock(); + for (int i = 0; i <= SIGNAL_MAX; i++) + { + store_context(&curr_thread->signal_saved_context); + if(curr_thread->sigcount[i]>0) + { + lock(); + curr_thread->sigcount[i]--; + unlock(); + run_signal(tpf,i); + } + } + lock(); + curr_thread->signal_is_checking = 0; + unlock(); +} + +void run_signal(trapframe_t* tpf,int signal) +{ + curr_thread->curr_signal_handler = curr_thread->signal_handler[signal]; + + //run default handler in kernel + if (curr_thread->curr_signal_handler == signal_default_handler) + { + signal_default_handler(); + return; + } + + asm("msr elr_el1, %0\n\t" + "msr sp_el0, %1\n\t" + "msr spsr_el1, %2\n\t" + "mov x0, %3\n\t" + "eret\n\t" + :: "r"(USER_SIGNAL_WRAPPER_VA + ((size_t)signal_handler_wrapper % 0x1000)), + "r"(tpf->sp_el0), + "r"(tpf->spsr_el1), + "r"(curr_thread->curr_signal_handler)); +} + +void signal_handler_wrapper() +{ + //elr_el1 set to function -> call function by x0 + //system call sigreturn + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void signal_default_handler() +{ + kill(0,curr_thread->pid); +} diff --git a/lab8/kernel/src/string.c b/lab8/kernel/src/string.c new file mode 100644 index 000000000..b746dfb5a --- /dev/null +++ b/lab8/kernel/src/string.c @@ -0,0 +1,313 @@ +#include "string.h" +#include + +unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args) +{ + long int arg; + int len, sign, i; + char *p, *orig=dst, tmpstr[19]; + + // failsafes + if(dst==(void*)0 || fmt==(void*)0) { + return 0; + } + + // main loop + arg = 0; + while(*fmt) { + if(dst-orig > VSPRINT_MAX_BUF_SIZE-0x10) + { + return -1; + } + // argument access + if(*fmt=='%') { + fmt++; + // literal % + if(*fmt=='%') { + goto put; + } + len=0; + // size modifier + while(*fmt>='0' && *fmt<='9') { + len *= 10; + len += *fmt-'0'; + fmt++; + } + // skip long modifier + if(*fmt=='l') { + fmt++; + } + // character + if(*fmt=='c') { + arg = __builtin_va_arg(args, int); + *dst++ = (char)arg; + fmt++; + continue; + } else + // decimal number + if(*fmt=='d') { + arg = __builtin_va_arg(args, int); + // check input + sign=0; + if((int)arg<0) { + arg*=-1; + sign++; + } + if(arg>99999999999999999L) { + arg=99999999999999999L; + } + // convert to string + i=18; + tmpstr[i]=0; + do { + tmpstr[--i]='0'+(arg%10); + arg/=10; + } while(arg!=0 && i>0); + if(sign) { + tmpstr[--i]='-'; + } + if(len>0 && len<18) { + while(i>18-len) { + tmpstr[--i]=' '; + } + } + p=&tmpstr[i]; + goto copystring; + } else + if(*fmt=='x') { + arg = __builtin_va_arg(args, long int); + i=16; + tmpstr[i]=0; + do { + char n=arg & 0xf; + tmpstr[--i]=n+(n>9?0x37:0x30); + arg>>=4; + } while(arg!=0 && i>0); + if(len>0 && len<=16) { + while(i>16-len) { + tmpstr[--i]='0'; + } + } + p=&tmpstr[i]; + goto copystring; + } else + if(*fmt=='s') { + p = __builtin_va_arg(args, char*); +copystring: if(p==(void*)0) { + p="(null)"; + } + while(*p) { + *dst++ = *p++; + } + } + } else { +put: *dst++ = *fmt; + } + fmt++; + } + *dst=0; + return dst-orig; +} + +unsigned int sprintf(char *dst, char* fmt, ...) +{ + __builtin_va_list args; + __builtin_va_start(args, fmt); + unsigned int r = vsprintf(dst,fmt,args); + __builtin_va_end(args); + return r; +} + +unsigned long long strlen(const char *str) +{ + size_t count = 0; + while((unsigned char)*str++)count++; + return count; +} + +char *strncat(char *dest, const char *src, int n) +{ + char *t; + + t = dest; + + while (*t) { + t++; + } + + while (n > 0 && *src) { + *t = *src; + t++; + src++; + n--; + } + + *t = '\0'; + + return dest; +} + +char* strcat (char *dest, const char *src) +{ + strcpy (dest + strlen (dest), src); + return dest; +} + +int strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + + while (1) { + c1 = *s1++; + c2 = *s2++; + + if (!c1 || !c2) { + break; + } + + if ('A' <= c1 && c1 <= 'Z') { + c1 |= 0x20; + } + + if ('A' <= c2 && c2 <= 'Z') { + c2 |= 0x20; + } + + if (c1 != c2) { + break; + } + } + + return c1 - c2; +} + +int strcmp(const char* p1, const char* p2) +{ + const unsigned char *s1 = (const unsigned char*) p1; + const unsigned char *s2 = (const unsigned char*) p2; + unsigned char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if ( c1 == '\0' ) return c1 - c2; + } while ( c1 == c2 ); + return c1 - c2; +} + +int strncmp (const char *s1, const char *s2, unsigned long long n) +{ + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + return c1 - c2; +} + +char* memcpy(void *dest, const void *src, unsigned long long len) +{ + char *d = dest; + const char *s = src; + while (len--) + *d++ = *s++; + return dest; +} + +char* strcpy (char *dest, const char *src) +{ + return memcpy (dest, src, strlen (src) + 1); +} + +void *memset(void *s, int c, size_t n) +{ + char *start = s; + for (size_t i = 0; i < n; i++) + { + start[i] = c; + } + + return s; +} + +char* strchr (register const char *s, int c) +{ + do { + if (*s == c) + { + return (char*)s; + } + } while (*s++); + return (0); +} + +char* str_SepbySpace(char* head) +{ + char* end; + while(1){ + if(*head == '\0') + { + end = head; + break; + } + if(*head == ' ') + { + *head = '\0'; + end = head + 1; + break; + } + head++; + } + return end; +} + +// A simple atoi() function +int atoi(char* str) +{ + // Initialize result + int res = 0; + + // Iterate through all characters + // of input string and update result + // take ASCII character of corresponding digit and + // subtract the code from '0' to get numerical + // value and multiply res by 10 to shuffle + // digits left to update running total + for (int i = 0; str[i] != '\0'; ++i) + { + if(str[i] > '9' || str[i] < '0')return res; + res = res * 10 + str[i] - '0'; + } + + // return result. + return res; +} diff --git a/lab8/kernel/src/syscall.c b/lab8/kernel/src/syscall.c new file mode 100644 index 000000000..acfa404ef --- /dev/null +++ b/lab8/kernel/src/syscall.c @@ -0,0 +1,418 @@ +#include "syscall.h" +#include "cpio.h" +#include "sched.h" +#include "stddef.h" +#include "uart1.h" +#include "exception.h" +#include "memory.h" +#include "mbox.h" +#include "signal.h" +#include "mmu.h" +#include "string.h" +#include "dev_framebuffer.h" + +int getpid(trapframe_t* tpf) +{ + tpf->x0 = curr_thread->pid; + return curr_thread->pid; +} + +size_t uartread(trapframe_t *tpf,char buf[], size_t size) +{ + int i = 0; + for (int i = 0; i < size;i++) + { + buf[i] = uart_async_getc(); + } + tpf->x0 = i; + return i; +} + +size_t uartwrite(trapframe_t *tpf,const char buf[], size_t size) +{ + int i = 0; + for (int i = 0; i < size; i++) + { + uart_async_putc(buf[i]); + } + tpf->x0 = i; + return i; +} + +//In this lab, you won’t have to deal with argument passing +int exec(trapframe_t *tpf,const char *name, char *const argv[]) +{ + mmu_del_vma(curr_thread); + INIT_LIST_HEAD(&curr_thread->vma_list); + + // use virtual file system + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, name); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + struct vnode *target_file; + vfs_lookup(abs_path,&target_file); + curr_thread->datasize = target_file->f_ops->getsize(target_file); + + curr_thread->data = kmalloc(curr_thread->datasize); + curr_thread->stack_alloced_ptr = kmalloc(USTACK_SIZE); + + asm("dsb ish\n\t"); // ensure write has completed + mmu_free_page_tables(curr_thread->context.pgd, 0); + memset(PHYS_TO_VIRT(curr_thread->context.pgd), 0, 0x1000); + asm("tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t"); // clear pipeline + + mmu_add_vma(curr_thread, USER_KERNEL_BASE, curr_thread->datasize, (size_t)VIRT_TO_PHYS(curr_thread->data) , 0b111, 1); + mmu_add_vma(curr_thread, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)VIRT_TO_PHYS(curr_thread->stack_alloced_ptr), 0b111, 1); + mmu_add_vma(curr_thread, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0); + mmu_add_vma(curr_thread, USER_SIGNAL_WRAPPER_VA, 0x2000, (size_t)VIRT_TO_PHYS(signal_handler_wrapper), 0b101, 0); + + //memcpy(curr_thread->data, new_data, curr_thread->datasize); + struct file *f; + vfs_open(abs_path, 0, &f); + vfs_read(f, curr_thread->data, curr_thread->datasize); + vfs_close(f); + + for (int i = 0; i <= SIGNAL_MAX; i++) + { + curr_thread->signal_handler[i] = signal_default_handler; + } + + + tpf->elr_el1 = USER_KERNEL_BASE; + tpf->sp_el0 = USER_STACK_BASE; + tpf->x0 = 0; + return 0; +} + +int fork(trapframe_t *tpf) +{ + lock(); + thread_t *newt = thread_create(curr_thread->data,curr_thread->datasize); + + //copy signal handler + for (int i = 0; i <= SIGNAL_MAX;i++) + { + newt->signal_handler[i] = curr_thread->signal_handler[i]; + } + + for (int i = 0; i <= MAX_FD; i++) + { + if (curr_thread->file_descriptors_table[i]) + { + newt->file_descriptors_table[i] = kmalloc(sizeof(struct file)); + *newt->file_descriptors_table[i] = *curr_thread->file_descriptors_table[i]; + } + } + + list_head_t *pos; + vm_area_struct_t *vma; + list_for_each(pos, &curr_thread->vma_list){ + // ignore device and signal wrapper + vma = (vm_area_struct_t *)pos; + if (vma->virt_addr == USER_SIGNAL_WRAPPER_VA || vma->virt_addr == PERIPHERAL_START) + { + continue; + } + char *new_alloc = kmalloc(vma->area_size); + mmu_add_vma(newt, vma->virt_addr, vma->area_size, (size_t)VIRT_TO_PHYS(new_alloc), vma->rwx, 1); + memcpy(new_alloc, (void*)PHYS_TO_VIRT(vma->phys_addr), vma->area_size); + } + mmu_add_vma(newt, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0); + mmu_add_vma(newt, USER_SIGNAL_WRAPPER_VA, 0x2000, (size_t)VIRT_TO_PHYS(signal_handler_wrapper), 0b101, 0); + + int parent_pid = curr_thread->pid; + + //copy stack into new process + for (int i = 0; i < KSTACK_SIZE; i++) + { + newt->kernel_stack_alloced_ptr[i] = curr_thread->kernel_stack_alloced_ptr[i]; + } + + store_context(get_current()); + //for child + if( parent_pid != curr_thread->pid) + { + goto child; + } + + void *temp_pgd = newt->context.pgd; + newt->context = curr_thread->context; + newt->context.pgd = VIRT_TO_PHYS(temp_pgd); + newt->context.fp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move fp + newt->context.sp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move kernel sp + + unlock(); + + tpf->x0 = newt->pid; + return newt->pid; + +child: + tpf->x0 = 0; + return 0; +} + +void exit(trapframe_t *tpf, int status) +{ + thread_exit(); +} + +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox_user) +{ + lock(); + + unsigned int size_of_mbox = mbox_user[0]; + memcpy((char *)pt, mbox_user, size_of_mbox); + mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)); + memcpy(mbox_user, (char *)pt, size_of_mbox); + + tpf->x0 = 8; + unlock(); + return 0; +} + +void kill(trapframe_t *tpf,int pid) +{ + lock(); + if (pid >= PIDMAX || pid < 0 || !threads[pid].isused) + { + unlock(); + return; + } + threads[pid].iszombie = 1; + unlock(); + schedule(); +} + +void signal_register(int signal, void (*handler)()) +{ + if (signal > SIGNAL_MAX || signal < 0)return; + + curr_thread->signal_handler[signal] = handler; +} + +void signal_kill(int pid, int signal) +{ + if (pid > PIDMAX || pid < 0 || !threads[pid].isused)return; + + lock(); + threads[pid].sigcount[signal]++; + unlock(); +} + +//only need to implement the anonymous page mapping in this Lab. +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset) +{ + // Ignore flags as we have demand pages + + // Req #3 Page size round up + len = len % 0x1000 ? len + (0x1000 - len % 0x1000) : len; + addr = (unsigned long)addr % 0x1000 ? addr + (0x1000 - (unsigned long)addr % 0x1000) : addr; + + // Req #2 check if overlap + list_head_t *pos; + vm_area_struct_t *vma; + vm_area_struct_t *the_area_ptr = 0; + list_for_each(pos, &curr_thread->vma_list) + { + vma = (vm_area_struct_t *)pos; + // Detect existing vma overlapped + if ( ! (vma->virt_addr >= (unsigned long)(addr + len) || vma->virt_addr + vma->area_size <= (unsigned long)addr ) ) + { + the_area_ptr = vma; + break; + } + } + // take as a hint to decide new region's start address + if (the_area_ptr) + { + tpf->x0 = (unsigned long) mmap(tpf, (void *)(the_area_ptr->virt_addr + the_area_ptr->area_size), len, prot, flags, fd, file_offset); + return (void *)tpf->x0; + } + // create new valid region, map and set the page attributes (prot) + mmu_add_vma(curr_thread, (unsigned long)addr, len, VIRT_TO_PHYS((unsigned long)kmalloc(len)), prot, 1); + tpf->x0 = (unsigned long)addr; + return (void*)tpf->x0; +} + + +int open(trapframe_t *tpf, const char *pathname, int flags) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + for (int i = 0; i < MAX_FD; i++) + { + if(!curr_thread->file_descriptors_table[i]) + { + if(vfs_open(abs_path, flags, &curr_thread->file_descriptors_table[i])!=0) + { + break; + } + + tpf->x0 = i; + return i; + } + } + + tpf->x0 = -1; + return -1; +} + +int close(trapframe_t *tpf, int fd) +{ + if(curr_thread->file_descriptors_table[fd]) + { + vfs_close(curr_thread->file_descriptors_table[fd]); + curr_thread->file_descriptors_table[fd] = 0; + tpf->x0 = 0; + return 0; + } + + tpf->x0 = -1; + return -1; +} + +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count) +{ + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_write(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + + tpf->x0 = -1; + return tpf->x0; +} + +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count) +{ + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_read(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + + tpf->x0 = -1; + return tpf->x0; +} + +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + tpf->x0 = vfs_mkdir(abs_path); + return tpf->x0; +} + +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, target); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + tpf->x0 = vfs_mount(abs_path,filesystem); + return tpf->x0; +} + +int chdir(trapframe_t *tpf, const char *path) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, path); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + strcpy(curr_thread->curr_working_dir, abs_path); + + return 0; +} + +long lseek64(trapframe_t *tpf, int fd, long offset, int whence) +{ + if(whence == SEEK_SET) + { + curr_thread->file_descriptors_table[fd]->f_pos = offset; + tpf->x0 = offset; + } + else + { + tpf->x0 = -1; + } + + return tpf->x0; +} +extern unsigned int height; +extern unsigned int isrgb; +extern unsigned int pitch; +extern unsigned int width; +int ioctl(trapframe_t *tpf, int fb, unsigned long request, void *info) +{ + if(request == 0) + { + struct framebuffer_info *fb_info = info; + fb_info->height = height; + fb_info->isrgb = isrgb; + fb_info->pitch = pitch; + fb_info->width = width; + } + + tpf->x0 = 0; + return tpf->x0; +} + +int sync(trapframe_t *tpf) +{ + for (int i = 0; i < MAX_FS_REG;i++) + { + if(!reg_fs[i].name) continue; + vfs_sync(®_fs[i]); + } + tpf->x0 = 0; + return tpf->x0; +} + +void sigreturn(trapframe_t *tpf) +{ + //unsigned long signal_ustack = tpf->sp_el0 % USTACK_SIZE == 0 ? tpf->sp_el0 - USTACK_SIZE : tpf->sp_el0 & (~(USTACK_SIZE - 1)); + //kfree((char*)signal_ustack); + load_context(&curr_thread->signal_saved_context); +} + + + + +char* get_file_start(char *thefilepath) +{ + char *filepath; + char *filedata; + unsigned int filesize; + struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + + while (header_pointer != 0) + { + int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + if (error) break; + if (strcmp(thefilepath, filepath) == 0) return filedata; + if (header_pointer == 0) uart_puts("execfile: %s: No such file or directory\r\n", thefilepath); + } + return 0; +} + +unsigned int get_file_size(char *thefilepath) +{ + char *filepath; + char *filedata; + unsigned int filesize; + struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + + while (header_pointer != 0) + { + int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + if (error) break; + if (strcmp(thefilepath, filepath) == 0) return filesize; + if (header_pointer == 0) uart_puts("execfile: %s: No such file or directory\r\n", thefilepath); + } + return 0; +} + diff --git a/lab8/kernel/src/timer.c b/lab8/kernel/src/timer.c new file mode 100644 index 000000000..d5e369ff6 --- /dev/null +++ b/lab8/kernel/src/timer.c @@ -0,0 +1,163 @@ +#include "timer.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" +#include "exception.h" + +#define STR(x) #x +#define XSTR(s) STR(s) + +struct list_head *timer_event_list; + +void timer_list_init() +{ + unsigned long long tmp; + asm volatile("mrs %0, cntkctl_el1": "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0":: "r"(tmp)); + + timer_event_list = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(timer_event_list); +} + +void core_timer_enable() +{ + __asm__ __volatile__( + "mov x1, 1\n\t" + "msr cntp_ctl_el0, x1\n\t" // enable + + "mov x2, 2\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // unmask timer interrupt + :::"x1","x2"); +} + +void core_timer_disable() +{ + __asm__ __volatile__( + "mov x2, 0\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // unmask timer interrupt + :::"x1","x2"); +} + +void timer_event_callback(timer_event_t *timer_event) +{ + ((void (*)(char *))timer_event->callback)(timer_event->args); // call the callback store in event + list_del_entry((struct list_head *)timer_event); // delete the event + kfree(timer_event->args); // kfree the arg space + kfree(timer_event); + + //set interrupt to next time_event if existing + if (!list_empty(timer_event_list)) + { + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + } + else + { + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + } +} + +void core_timer_handler() +{ + lock(); + //disable_interrupt(); + if (list_empty(timer_event_list)) + { + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + unlock(); + return; + } + + timer_event_callback((timer_event_t *)timer_event_list->next); // do callback and set new interrupt + unlock(); +} + +// give a string argument to callback timeout after seconds +void add_timer(void *callback, unsigned long long timeout, char *args, int bytick) +{ + timer_event_t *the_timer_event = kmalloc(sizeof(timer_event_t)); //need to kfree by event handler + + // store argument string into timer_event + the_timer_event->args = kmalloc(strlen(args) + 1); + strcpy(the_timer_event->args, args); + + if(bytick == 0) + { + the_timer_event->interrupt_time = get_tick_plus_s(timeout); // store interrupt time into timer_event + }else + { + the_timer_event->interrupt_time = get_tick_plus_s(0) + timeout; + } + + the_timer_event->callback = callback; + + // add the timer_event into timer_event_list (sorted) + struct list_head *curr; + + lock(); + list_for_each(curr, timer_event_list) + { + if (((timer_event_t *)curr)->interrupt_time > the_timer_event->interrupt_time) + { + list_add(&the_timer_event->listhead, curr->prev); // add this timer at the place just before the bigger one (sorted) + break; + } + } + + if (list_is_head(curr, timer_event_list)) + { + list_add_tail(&the_timer_event->listhead, timer_event_list); // for the time is the biggest + } + + + // set interrupt to first event + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + unlock(); +} + + +// get cpu tick add some second +unsigned long long get_tick_plus_s(unsigned long long second) +{ + + unsigned long long cntpct_el0 = 0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" + : "=r"(cntpct_el0)); //tick now + + unsigned long long cntfrq_el0 = 0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" + : "=r"(cntfrq_el0)); //tick frequency + + return (cntpct_el0 + cntfrq_el0 * second); +} + +// set timer interrupt time to [expired_time] seconds after now (relatively) +void set_core_timer_interrupt(unsigned long long expired_time) +{ + __asm__ __volatile__( + "mrs x1, cntfrq_el0\n\t" //cntfrq_el0 -> relative time + "mul x1, x1, %0\n\t" + "msr cntp_tval_el0, x1\n\t" // set expired time + :: "r"(expired_time):"x1"); +} + +// directly set timer interrupt time to a cpu tick (directly) +void set_core_timer_interrupt_by_tick(unsigned long long tick) +{ + __asm__ __volatile__( + "msr cntp_cval_el0, %0\n\t" //cntp_cval_el0 -> absolute time + :: "r"(tick)); +} + +int timer_list_get_size() +{ + int r = 0; + struct list_head *curr; + list_for_each(curr, timer_event_list) + { + r++; + } + return r; +} diff --git a/lab8/kernel/src/tmpfs.c b/lab8/kernel/src/tmpfs.c new file mode 100644 index 000000000..a0f571c27 --- /dev/null +++ b/lab8/kernel/src/tmpfs.c @@ -0,0 +1,212 @@ +#include "tmpfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "uart1.h" + +struct file_operations tmpfs_file_operations = {tmpfs_write,tmpfs_read,tmpfs_open,tmpfs_close,tmpfs_lseek64,tmpfs_getsize}; +struct vnode_operations tmpfs_vnode_operations = {tmpfs_lookup,tmpfs_create,tmpfs_mkdir}; + +int register_tmpfs() +{ + struct filesystem fs; + fs.name = "tmpfs"; + fs.setup_mount = tmpfs_setup_mount; + fs.sync = tmpfs_sync; + return register_filesystem(&fs); +} + +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = tmpfs_create_vnode(0,dir_t); + return 0; +} + +struct vnode* tmpfs_create_vnode(struct mount* _mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &tmpfs_file_operations; + v->v_ops = &tmpfs_vnode_operations; + v->mount = 0; + struct tmpfs_inode* inode = kmalloc(sizeof(struct tmpfs_inode)); + memset(inode, 0, sizeof(struct tmpfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// file operations +int tmpfs_write(struct file *file, const void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // write from f_pos + memcpy(inode->data + file->f_pos, buf, len); + // update f_pos and size + file->f_pos += len; + if(inode->datasize < file->f_pos) inode->datasize = file->f_pos; + return len; +} + +int tmpfs_read(struct file *file, void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // if buffer overflow, shrink the request read length + // read from f_pos + if(len+file->f_pos > inode->datasize) + { + len = inode->datasize - file->f_pos; + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += inode->datasize - file->f_pos; + return len; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int tmpfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +int tmpfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long tmpfs_lseek64(struct file *file, long offset, int whence) +{ + if(whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + + +// vnode operations +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + // BFS search tree + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if(!vnode) break; + struct tmpfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + + +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + if(inode->type!=dir_t) + { + uart_sendline("tmpfs create not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) break; + struct tmpfs_inode *child_inode = inode->entry[child_idx]->internal; + if (strcmp(child_inode->name,component_name)==0) + { + uart_sendline("tmpfs create file exists\r\n"); + return -1; + } + } + + if (child_idx > MAX_DIR_ENTRY) + { + uart_sendline("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendline("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode *_vnode = tmpfs_create_vnode(0, file_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + + if (inode->type != dir_t) + { + uart_sendline("tmpfs mkdir not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + } + + if(child_idx > MAX_DIR_ENTRY) + { + uart_sendline("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendline("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode* _vnode = tmpfs_create_vnode(0, dir_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +long tmpfs_getsize(struct vnode* vd) +{ + struct tmpfs_inode *inode = vd->internal; + return inode->datasize; +} + +int tmpfs_sync(struct filesystem *fs) +{ + return 0; +} diff --git a/lab8/kernel/src/uart1.c b/lab8/kernel/src/uart1.c new file mode 100644 index 000000000..c2cf5fff3 --- /dev/null +++ b/lab8/kernel/src/uart1.c @@ -0,0 +1,172 @@ +#include "bcm2837/rpi_gpio.h" +#include "bcm2837/rpi_uart1.h" +#include "bcm2837/rpi_irq.h" +#include "uart1.h" +#include "exception.h" +#include "string.h" + +//implement first in first out buffer with a read index and a write index +char uart_tx_buffer[VSPRINT_MAX_BUF_SIZE]={}; +unsigned int uart_tx_buffer_widx = 0; //write index +unsigned int uart_tx_buffer_ridx = 0; //read index +char uart_rx_buffer[VSPRINT_MAX_BUF_SIZE]={}; +unsigned int uart_rx_buffer_widx = 0; +unsigned int uart_rx_buffer_ridx = 0; + +int uart_recv_echo_flag = 1; + +void uart_init() +{ + register unsigned int r; + + /* initialize UART */ + *AUX_ENABLES |= 1; // enable UART1 + *AUX_MU_CNTL_REG = 0; // disable TX/RX + + /* configure UART */ + *AUX_MU_IER_REG = 0; // disable interrupt + *AUX_MU_LCR_REG = 3; // 8 bit data size + *AUX_MU_MCR_REG = 0; // disable flow control + *AUX_MU_BAUD_REG = 270; // 115200 baud rate + *AUX_MU_IIR_REG = 0xC6; // disable FIFO + + /* map UART1 to GPIO pins */ + r = *GPFSEL1; + r &= ~(7<<12); // clean gpio14 + r |= 2<<12; // set gpio14 to alt5 + r &= ~(7<<15); // clean gpio15 + r |= 2<<15; // set gpio15 to alt5 + *GPFSEL1 = r; + + /* enable pin 14, 15 - ref: Page 101 */ + *GPPUD = 0; + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1<<14)|(1<<15); + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; + + *AUX_MU_CNTL_REG = 3; // enable TX/RX +} + +char uart_recv() { + char r; + while(!(*AUX_MU_LSR_REG & 0x01)){}; + r = (char)(*AUX_MU_IO_REG); + if(uart_recv_echo_flag){ + uart_send(r); + if(r =='\r') {uart_send('\r');uart_send('\n');} + } + return r=='\r'?'\n':r; +} + +void uart_send(char c) { + while(!(*AUX_MU_LSR_REG & 0x20)){}; + *AUX_MU_IO_REG = c; +} + +void uart_2hex(unsigned int d) { + unsigned int n; + int c; + for(c=28;c>=0;c-=4) { + n=(d>>c)&0xF; + n+=n>9?0x37:0x30; + uart_send(n); + } +} + +int uart_sendline(char* fmt, ...) { + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[VSPRINT_MAX_BUF_SIZE]; + + char *str = (char*)buf; + int count = vsprintf(str,fmt,args); + + while(*str) { + if(*str=='\n') + uart_send('\r'); + uart_send(*str++); + } + __builtin_va_end(args); + return count; +} + + +// uart_async_getc read from buffer +// uart_r_irq_handler write to buffer then output +char uart_async_getc() { + *AUX_MU_IER_REG |=1; // enable read interrupt + // do while if buffer empty + while (uart_rx_buffer_ridx == uart_rx_buffer_widx) *AUX_MU_IER_REG |=1; // enable read interrupt + lock(); + char r = uart_rx_buffer[uart_rx_buffer_ridx++]; + if (uart_rx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) uart_rx_buffer_ridx = 0; + unlock(); + return r; +} + + +// uart_async_putc writes to buffer +// uart_w_irq_handler read from buffer then output +void uart_async_putc(char c) { + // if buffer full, wait for uart_w_irq_handler + while( (uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx ) *AUX_MU_IER_REG |=2; // enable write interrupt + lock(); + uart_tx_buffer[uart_tx_buffer_widx++] = c; + if(uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_widx=0; // cycle pointer + unlock(); + *AUX_MU_IER_REG |=2; // enable write interrupt +} + +int uart_puts(char* fmt, ...) { + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[VSPRINT_MAX_BUF_SIZE]; + + char *str = (char*)buf; + int count = vsprintf(str,fmt,args); + + while(*str) { + if(*str=='\n') + uart_async_putc('\r'); + uart_async_putc(*str++); + } + __builtin_va_end(args); + return count; +} + +// AUX_MU_IER_REG -> BCM2837-ARM-Peripherals.pdf - Pg.12 +void uart_interrupt_enable(){ + *AUX_MU_IER_REG |=1; // enable read interrupt + *AUX_MU_IER_REG |=2; // enable write interrupt + *ENABLE_IRQS_1 |= 1 << 29; // Pg.112 +} + +void uart_interrupt_disable(){ + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + *AUX_MU_IER_REG &= ~(2); // disable write interrupt +} + + +void uart_r_irq_handler(){ + if((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + return; + } + uart_rx_buffer[uart_rx_buffer_widx++] = uart_recv(); + if(uart_rx_buffer_widx>=VSPRINT_MAX_BUF_SIZE) uart_rx_buffer_widx=0; + *AUX_MU_IER_REG |=1; +} + +void uart_w_irq_handler(){ + if(uart_tx_buffer_ridx == uart_tx_buffer_widx) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + return; // buffer empty + } + uart_send(uart_tx_buffer[uart_tx_buffer_ridx++]); + if(uart_tx_buffer_ridx>=VSPRINT_MAX_BUF_SIZE) uart_tx_buffer_ridx=0; + *AUX_MU_IER_REG |=2; // enable write interrupt +} + diff --git a/lab8/kernel/src/vfs.c b/lab8/kernel/src/vfs.c new file mode 100644 index 000000000..fff02c0ca --- /dev/null +++ b/lab8/kernel/src/vfs.c @@ -0,0 +1,343 @@ +#include "vfs.h" +#include "tmpfs.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "initramfs.h" +#include "dev_uart.h" +#include "dev_framebuffer.h" +#include "sdhost.h" +#include "fat32.h" + +struct mount *rootfs; +struct filesystem reg_fs[MAX_FS_REG]; +struct file_operations reg_dev[MAX_DEV_REG]; + +int register_filesystem(struct filesystem *fs) +{ + for (int i = 0; i < MAX_FS_REG;i++) + { + if(!reg_fs[i].name) + { + reg_fs[i].name = fs->name; + reg_fs[i].setup_mount = fs->setup_mount; + reg_fs[i].sync = fs->sync; + return i; + } + } + return -1; +} + +int register_dev(struct file_operations *fo) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (!reg_dev[i].open) + { + // return unique id for the assigned device + reg_dev[i] = *fo; + return i; + } + } + return -1; +} + +struct filesystem* find_filesystem(const char* fs_name) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (strcmp(reg_fs[i].name,fs_name)==0) + { + return ®_fs[i]; + } + } + return 0; +} + + + +int vfs_open(const char *pathname, int flags, struct file **target) +{ + // 1. Lookup pathname + // 3. Create a new file if O_CREAT is specified in flags and vnode not found + struct vnode *node; + if (vfs_lookup(pathname, &node) != 0 && (flags & O_CREAT)) + { + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if(pathname[i]=='/') + { + last_slash_idx = i; + } + } + + char dirname[MAX_PATH_NAME+1]; + strcpy(dirname, pathname); + dirname[last_slash_idx] = 0; + if (vfs_lookup(dirname,&node)!=0) + { + uart_sendline("cannot ocreate no dir name\r\n"); + return -1; + } + node->v_ops->create(node, &node, pathname+last_slash_idx+1); + *target = kmalloc(sizeof(struct file)); + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + else // 2. Create a new file handle for this vnode if found. + { + *target = kmalloc(sizeof(struct file)); + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + + // lookup error code shows if file exist or not or other error occurs + // 4. Return error code if fails + return -1; +} + +int vfs_close(struct file *file) +{ + // 1. release the file handle + // 2. Return error code if fails + file->f_ops->close(file); + return 0; +} + +int vfs_write(struct file *file, const void *buf, size_t len) +{ + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file->f_ops->write(file,buf,len); +} + +int vfs_read(struct file *file, void *buf, size_t len) +{ + // 1. read min(len, readable size) byte to buf from the opened file. + // 2. block if nothing to read for FIFO type + // 2. return read size or error code if an error occurs. + return file->f_ops->read(file, buf, len); +} + +int vfs_mkdir(const char *pathname) +{ + char dirname[MAX_PATH_NAME] = {}; // before add folder + char newdirname[MAX_PATH_NAME] = {}; // after add folder + + // search for last directory + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + last_slash_idx = i; + } + } + + memcpy(dirname, pathname, last_slash_idx); + strcpy(newdirname, pathname + last_slash_idx + 1); + + // create new directory if upper directory is found + struct vnode *node; + if(vfs_lookup(dirname,&node)==0) + { + node->v_ops->mkdir(node,&node,newdirname); + return 0; + } + + uart_sendline("vfs_mkdir cannot find pathname"); + return -1; +} + +int vfs_mount(const char *target, const char *filesystem) +{ + struct vnode *dirnode; + // search for the target filesystem + struct filesystem *fs = find_filesystem(filesystem); + if(!fs) + { + uart_sendline("vfs_mount cannot find filesystem\r\n"); + return -1; + } + // get its upper directory, if no, create new mountpoint + if(vfs_lookup(target, &dirnode)==-1) + { + uart_sendline("vfs_mount cannot find dir\r\n"); + return -1; + }else + { + dirnode->mount = kmalloc(sizeof(struct mount)); + fs->setup_mount(fs, dirnode->mount); + } + return 0; +} + +int vfs_lookup(const char *pathname, struct vnode **target) +{ + int is_fat = 0; + if (pathname[1]=='b' && pathname[2]=='o' && pathname[3]=='o' && pathname[4]=='t') + is_fat = 1; + // if no path input, return root + if(strlen(pathname)==0) + { + *target = rootfs->root; + return 0; + } + + struct vnode *dirnode = rootfs->root; + char component_name[MAX_FILE_NAME+1] = {}; + int c_idx = 0; + // deal with directory + for (int i = 1; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + dirnode = dirnode->mount->root; + if(is_fat) break; + } + c_idx = 0; + } + else + { + component_name[c_idx++] = pathname[i]; + } + } + + // deal with file + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + if(is_fat) break; + dirnode = dirnode->mount->root; + } + // return file's vnode + *target = dirnode; + + return 0; +} + +// for device operations only +int vfs_mknod(char* pathname, int id) +{ + struct file* f = kmalloc(sizeof(struct file)); + // create leaf and its file operations + vfs_open(pathname, O_CREAT, &f); + f->vnode->f_ops = ®_dev[id]; + vfs_close(f); + return 0; +} + +int vfs_sync(struct filesystem *fs) +{ + return fs->sync(fs); +} + +void init_rootfs() +{ + // sd_init + sd_init(); + + // tmpfs + int idx = register_tmpfs(); + rootfs = kmalloc(sizeof(struct mount)); + reg_fs[idx].setup_mount(®_fs[idx], rootfs); + + // initramfs + vfs_mkdir("/initramfs"); + register_initramfs(); + vfs_mount("/initramfs","initramfs"); + + // fat32 + vfs_mkdir("/boot"); + register_fat32(); + vfs_mount("/boot", "fat32"); + + // dev_fs + vfs_mkdir("/dev"); + int uart_id = init_dev_uart(); + vfs_mknod("/dev/uart", uart_id); + int framebuffer_id = init_dev_framebuffer(); + vfs_mknod("/dev/framebuffer", framebuffer_id); +} + +void vfs_test() +{ + // test read/write + vfs_mkdir("/lll"); + vfs_mkdir("/lll/ddd"); + // test mount + vfs_mount("/lll/ddd", "tmpfs"); + + struct file* testfilew; + struct file *testfiler; + char testbufw[0x30] = "ABCDEABBBBBBDDDDDDDDDDD"; + char testbufr[0x30] = {}; + vfs_open("/lll/ddd/ggg", O_CREAT, &testfilew); + vfs_open("/lll/ddd/ggg", O_CREAT, &testfiler); + vfs_write(testfilew, testbufw, 10); + vfs_read(testfiler, testbufr, 10); + uart_sendline("%s",testbufr); + + struct file *testfile_initramfs; + vfs_open("/initramfs/get_simpleexec.sh", O_CREAT, &testfile_initramfs); + vfs_read(testfile_initramfs, testbufr, 30); + uart_sendline("%s", testbufr); +} + +char *get_absolute_path(char *path, char *curr_working_dir) +{ + // if relative path -> add root path + if(path[0] != '/') + { + char tmp[MAX_PATH_NAME]; + strcpy(tmp, curr_working_dir); + if(strcmp(curr_working_dir,"/")!=0)strcat(tmp, "/"); + strcat(tmp, path); + strcpy(path, tmp); + } + + char absolute_path[MAX_PATH_NAME+1] = {}; + int idx = 0; + for (int i = 0; i < strlen(path); i++) + { + // meet /.. + if (path[i] == '/' && path[i+1] == '.' && path[i+2] == '.') + { + for (int j = idx; j >= 0;j--) + { + if(absolute_path[j] == '/') + { + absolute_path[j] = 0; + idx = j; + } + } + i += 2; + continue; + } + + // ignore /. + if (path[i] == '/' && path[i+1] == '.') + { + i++; + continue; + } + + absolute_path[idx++] = path[i]; + } + absolute_path[idx] = 0; + + return strcpy(path, absolute_path); +} + From 70df92d6d9e9a43642ab5a50260e181af0c7573d Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:57:36 +0800 Subject: [PATCH 04/19] Delete lab8/a --- lab8/a | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lab8/a diff --git a/lab8/a b/lab8/a deleted file mode 100644 index 8b1378917..000000000 --- a/lab8/a +++ /dev/null @@ -1 +0,0 @@ - From 68b629431ff0105c1cb7a3cb4862b6a44db20a33 Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:57:44 +0800 Subject: [PATCH 05/19] Delete lab8/kernel/a --- lab8/kernel/a | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lab8/kernel/a diff --git a/lab8/kernel/a b/lab8/kernel/a deleted file mode 100644 index 8b1378917..000000000 --- a/lab8/kernel/a +++ /dev/null @@ -1 +0,0 @@ - From 5e2da25f129abe604851b81344464909f7f46971 Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:59:04 +0800 Subject: [PATCH 06/19] Add files via upload --- lab8/kernel/include/cpio.h | 41 +++++ lab8/kernel/include/dev_framebuffer.h | 24 +++ lab8/kernel/include/dev_uart.h | 15 ++ lab8/kernel/include/dtb.h | 28 ++++ lab8/kernel/include/exception.h | 81 ++++++++++ lab8/kernel/include/fat32.h | 208 ++++++++++++++++++++++++ lab8/kernel/include/initramfs.h | 37 +++++ lab8/kernel/include/irqtask.h | 22 +++ lab8/kernel/include/list.h | 223 ++++++++++++++++++++++++++ lab8/kernel/include/mbox.h | 63 ++++++++ lab8/kernel/include/memory.h | 71 ++++++++ lab8/kernel/include/mmu.h | 69 ++++++++ lab8/kernel/include/power.h | 9 ++ lab8/kernel/include/sched.h | 70 ++++++++ lab8/kernel/include/sdhost.h | 8 + lab8/kernel/include/shell.h | 29 ++++ lab8/kernel/include/signal.h | 47 ++++++ lab8/kernel/include/stddef.h | 11 ++ lab8/kernel/include/string.h | 24 +++ lab8/kernel/include/syscall.h | 34 ++++ lab8/kernel/include/timer.h | 29 ++++ lab8/kernel/include/tmpfs.h | 38 +++++ lab8/kernel/include/uart1.h | 18 +++ lab8/kernel/include/vfs.h | 91 +++++++++++ 24 files changed, 1290 insertions(+) create mode 100644 lab8/kernel/include/cpio.h create mode 100644 lab8/kernel/include/dev_framebuffer.h create mode 100644 lab8/kernel/include/dev_uart.h create mode 100644 lab8/kernel/include/dtb.h create mode 100644 lab8/kernel/include/exception.h create mode 100644 lab8/kernel/include/fat32.h create mode 100644 lab8/kernel/include/initramfs.h create mode 100644 lab8/kernel/include/irqtask.h create mode 100644 lab8/kernel/include/list.h create mode 100644 lab8/kernel/include/mbox.h create mode 100644 lab8/kernel/include/memory.h create mode 100644 lab8/kernel/include/mmu.h create mode 100644 lab8/kernel/include/power.h create mode 100644 lab8/kernel/include/sched.h create mode 100644 lab8/kernel/include/sdhost.h create mode 100644 lab8/kernel/include/shell.h create mode 100644 lab8/kernel/include/signal.h create mode 100644 lab8/kernel/include/stddef.h create mode 100644 lab8/kernel/include/string.h create mode 100644 lab8/kernel/include/syscall.h create mode 100644 lab8/kernel/include/timer.h create mode 100644 lab8/kernel/include/tmpfs.h create mode 100644 lab8/kernel/include/uart1.h create mode 100644 lab8/kernel/include/vfs.h diff --git a/lab8/kernel/include/cpio.h b/lab8/kernel/include/cpio.h new file mode 100644 index 000000000..e662bee51 --- /dev/null +++ b/lab8/kernel/include/cpio.h @@ -0,0 +1,41 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +/* + cpio format : https://manpages.ubuntu.com/manpages/bionic/en/man5/cpio.5.html + We are using "newc" format + header, file path, file data, header ...... + header + file path (padding 4 bytes) + file data (padding 4 bytes) (max size 4gb) +*/ + +#define CPIO_NEWC_HEADER_MAGIC "070701" // big endian constant, to check whether it is big endian or little endian + +extern void* CPIO_DEFAULT_START; +extern void* CPIO_DEFAULT_END; + +// Using newc archive format +struct cpio_newc_header +{ + char c_magic[6]; // fixed, "070701". + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +/* write pathname, data, next header into corresponding parameter*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, + char **pathname, unsigned int *filesize, char **data, + struct cpio_newc_header **next_header_pointer); + +#endif /* _CPIO_H_ */ diff --git a/lab8/kernel/include/dev_framebuffer.h b/lab8/kernel/include/dev_framebuffer.h new file mode 100644 index 000000000..4ca5a8565 --- /dev/null +++ b/lab8/kernel/include/dev_framebuffer.h @@ -0,0 +1,24 @@ +#ifndef _DEV_FRAMEBUFFER_H_ +#define _DEV_FRAMEBUFFER_H_ + +#include "stddef.h" +#include "vfs.h" + +struct framebuffer_info +{ + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +}; + +int init_dev_framebuffer(); + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len); +int dev_framebuffer_read(struct file *file, void *buf, size_t len); +int dev_framebuffer_open(struct vnode *file_node, struct file **target); +int dev_framebuffer_close(struct file *file); +long dev_framebuffer_lseek64(struct file *file, long offset, int whence); +int dev_framebuffer_op_deny(); + +#endif diff --git a/lab8/kernel/include/dev_uart.h b/lab8/kernel/include/dev_uart.h new file mode 100644 index 000000000..b46dceed4 --- /dev/null +++ b/lab8/kernel/include/dev_uart.h @@ -0,0 +1,15 @@ +#ifndef _DEV_UART_H_ +#define _DEV_UART_H_ + +#include "stddef.h" +#include "vfs.h" + +int init_dev_uart(); + +int dev_uart_write(struct file *file, const void *buf, size_t len); +int dev_uart_read(struct file *file, void *buf, size_t len); +int dev_uart_open(struct vnode *file_node, struct file **target); +int dev_uart_close(struct file *file); +int dev_uart_op_deny(); + +#endif diff --git a/lab8/kernel/include/dtb.h b/lab8/kernel/include/dtb.h new file mode 100644 index 000000000..fb7c451d5 --- /dev/null +++ b/lab8/kernel/include/dtb.h @@ -0,0 +1,28 @@ +#ifndef _DTB_H_ +#define _DTB_H_ + +#define uint32_t unsigned int +#define uint64_t unsigned long long + +// manipulate device tree with dtb file format +// linux kernel fdt.h +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +extern char* dtb_ptr; + +typedef void (*dtb_callback)(uint32_t node_type, char *name, void *value, uint32_t name_size); + +uint32_t uint32_endian_big2lttle(uint32_t data); +uint64_t uint64_endian_big2lttle(uint64_t data); + +void traverse_device_tree(void *base, dtb_callback callback); //traverse dtb tree +void dtb_callback_show_tree(uint32_t node_type, char *name, void *value, uint32_t name_size); +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size); + +void dtb_find_and_store_reserved_memory(); + +#endif diff --git a/lab8/kernel/include/exception.h b/lab8/kernel/include/exception.h new file mode 100644 index 000000000..f02bf2edb --- /dev/null +++ b/lab8/kernel/include/exception.h @@ -0,0 +1,81 @@ +#ifndef _EXCEPTION_H_ +#define _EXCEPTION_H_ + +#include "bcm2837/rpi_irq.h" + +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(PHYS_TO_VIRT(0x40000060))) + +#define IRQ_PENDING_1_AUX_INT (1<<29) +#define INTERRUPT_SOURCE_GPU (1<<8) +#define INTERRUPT_SOURCE_CNTPNSIRQ (1<<1) + +typedef struct trapframe +{ + unsigned long x0; + unsigned long x1; + unsigned long x2; + unsigned long x3; + unsigned long x4; + unsigned long x5; + unsigned long x6; + unsigned long x7; + unsigned long x8; + unsigned long x9; + unsigned long x10; + unsigned long x11; + unsigned long x12; + unsigned long x13; + unsigned long x14; + unsigned long x15; + unsigned long x16; + unsigned long x17; + unsigned long x18; + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long x29; + unsigned long x30; + unsigned long spsr_el1; + unsigned long elr_el1; + unsigned long sp_el0; +} trapframe_t; + +#define MEMFAIL_DATA_ABORT_LOWER 0b100100 // esr_el1 +#define MEMFAIL_INST_ABORT_LOWER 0b100000 // EC, bits [31:26] + +#define TF_LEVEL0 0b000100 // iss IFSC, bits [5:0] +#define TF_LEVEL1 0b000101 +#define TF_LEVEL2 0b000110 +#define TF_LEVEL3 0b000111 + +typedef struct{ + unsigned int iss : 25, // Instruction specific syndrome + il : 1, // Instruction length bit + ec : 6; // Exception class +} esr_el1_t; + +void sync_64_router(trapframe_t *tpf); +void irq_router(trapframe_t *tpf); +void invalid_exception_router(); + +static inline void el1_interrupt_enable() +{ + __asm__ __volatile__("msr daifclr, 0xf"); +} + +static inline void el1_interrupt_disable() +{ + __asm__ __volatile__("msr daifset, 0xf"); +} + +void lock(); +void unlock(); + +#endif /* _EXCEPTION_H_ */ diff --git a/lab8/kernel/include/fat32.h b/lab8/kernel/include/fat32.h new file mode 100644 index 000000000..768267c63 --- /dev/null +++ b/lab8/kernel/include/fat32.h @@ -0,0 +1,208 @@ +#ifndef FAT32_H +#define FAT32_H + +#include "list.h" +#include "vfs.h" + +#define BLOCK_SIZE 512 +#define CLUSTER_ENTRY_PER_BLOCK (BLOCK_SIZE / sizeof(struct cluster_entry_t)) +#define DIR_PER_BLOCK (BLOCK_SIZE / sizeof(struct dir_t)) +#define INVALID_CID 0x0ffffff8 // Last cluster in file (EOC), reserved by FAT32 + +struct partition_t { + unsigned char status; + unsigned char chss_head; + unsigned char chss_sector; + unsigned char chss_cylinder; + unsigned char type; + unsigned char chse_head; + unsigned char chse_sector; + unsigned char chse_cylinder; + unsigned int lba; + unsigned int sectors; +} __attribute__((packed)); + +struct boot_sector_t { + unsigned char jmpboot[3]; + unsigned char oemname[8]; + unsigned short bytes_per_sector; + unsigned char sector_per_cluster; + unsigned short reserved_sector_cnt; + unsigned char fat_cnt; + unsigned short root_entry_cnt; + unsigned short old_sector_cnt; + unsigned char media; + unsigned short sector_per_fat16; + unsigned short sector_per_track; + unsigned short head_cnt; + unsigned int hidden_sector_cnt; // Default Boot Sector ends here + unsigned int sector_cnt; // FAT32 definition + unsigned int sector_per_fat32; + unsigned short extflags; + unsigned short ver; + unsigned int root_cluster; + unsigned short info; + unsigned short bkbooksec; + unsigned char reserved[12]; + unsigned char drvnum; + unsigned char reserved1; + unsigned char bootsig; + unsigned int volid; + unsigned char vollab[11]; + unsigned char fstype[8]; +} __attribute__((packed)); + +struct fat_info_t { + struct boot_sector_t bs; // boot_sector from MBR Partition Table + unsigned int fat_lba; // FAT Region in FAT fs Definition + unsigned int cluster_lba; // Data Region in FAT32 fs Definition +}; + +// attr of dir_t +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_LFN 0x0f +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_FILE_DIR_MASK (ATTR_DIRECTORY | ATTR_ARCHIVE) + +// Directory structure for FAT SFN +// http://elm-chan.org/docs/fat_e.html +struct dir_t { + unsigned char name[11]; + unsigned char attr; + unsigned char ntres; + unsigned char crttimetenth; + unsigned short crttime; + unsigned short crtdate; + unsigned short lstaccdate; + unsigned short ch; + unsigned short wrttime; + unsigned short wrtdate; + unsigned short cl; + unsigned int size; +} __attribute__((packed)); + +// Directory structure for FAT LFN +// https://blog.csdn.net/ZCShouCSDN/article/details/97610903 +struct long_dir_t { + unsigned char order; + unsigned char name1[10]; + unsigned char attr; + unsigned char type; + unsigned char checksum; + unsigned char name2[12]; + unsigned short fstcluslo; + unsigned char name3[4]; +} __attribute__((packed)); + +struct cluster_entry_t { + union { + unsigned int val; + struct { + unsigned int idx: 28; + unsigned int reserved: 4; + }; + }; +}; + +struct filename_t { + union { + unsigned char fullname[256]; + struct { + unsigned char name[13]; + } part[20]; + }; +} __attribute__((packed)); + +struct fat_file_block_t { + /* Link fat_file_block_t */ + struct list_head list; + unsigned int oid; // offset if of file, N = offset N* BLOCK_SIZE of file + unsigned int cid; // cluster id + unsigned int bufIsUpdated; + unsigned int isDirty; + unsigned char buf[BLOCK_SIZE]; +}; + +struct fat_file_t { + /* Head of fat_file_block_t chain */ + struct list_head list; + unsigned int size; +}; + +struct fat_dir_t { + /* Head of fat32_inode chain */ + struct list_head list; +}; + +struct fat_mount_t { + /* Link fat_mount_t */ + struct list_head list; + struct mount *mount; +}; + +// type of struct fat32_inode +#define FAT_DIR 1 +#define FAT_FILE 2 + +struct fat32_inode { + const char *name; + struct vnode *node; // redirect to vnode + struct fat_info_t *fat; + /* Link fat32_inode */ + struct list_head list; + /* cluster id */ + unsigned int cid; // cluster id + unsigned int type; + union { + struct fat_dir_t *dir; + struct fat_file_t *file; + }; +}; + +int register_fat32(); + +int fat32_mount(struct filesystem *fs, struct mount *mount); +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_isdir(struct vnode *dir_node); +int fat32_getname(struct vnode *dir_node, const char **name); +int fat32_getsize(struct vnode *dir_node); + +int fat32_write(struct file *file, const void *buf, size_t len); +int fat32_read(struct file *file, void *buf, size_t len); +int fat32_open(struct vnode *file_node, struct file **target); +int fat32_close(struct file *file); +long fat32_lseek64(struct file *file, long offset, int whence); +int fat32_sync(struct filesystem *fs); + +unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid); +unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id); + +struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size); + +int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name); +struct dir_t* __lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba); +int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name); + +int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); +int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); +int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); +int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); +int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); + +int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); +int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); +int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); +int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); +int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); + +void _sync_dir(struct vnode *dirnode); +void _do_sync_dir(struct vnode *dirnode); +void _do_sync_file(struct vnode *filenode); + +#endif diff --git a/lab8/kernel/include/initramfs.h b/lab8/kernel/include/initramfs.h new file mode 100644 index 000000000..494744b1e --- /dev/null +++ b/lab8/kernel/include/initramfs.h @@ -0,0 +1,37 @@ +#ifndef _INITRAMFS_H_ +#define _INITRAMFS_H_ + +#include "stddef.h" +#include "vfs.h" + +#define INITRAMFS_MAX_DIR_ENTRY 100 + +// initramfs basically is same as tmpfs, but it is read-only + +struct initramfs_inode +{ + enum fsnode_type type; + char* name; + struct vnode *entry[INITRAMFS_MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_initramfs(); +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int initramfs_write(struct file *file, const void *buf, size_t len); +int initramfs_read(struct file *file, void *buf, size_t len); +int initramfs_open(struct vnode *file_node, struct file **target); +int initramfs_close(struct file *file); +long initramfs_lseek64(struct file *file, long offset, int whence); +long initramfs_getsize(struct vnode *vd); + +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_sync(struct filesystem *fs); + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +#endif /* _INITRAMFS_H_ */ diff --git a/lab8/kernel/include/irqtask.h b/lab8/kernel/include/irqtask.h new file mode 100644 index 000000000..395bea0b7 --- /dev/null +++ b/lab8/kernel/include/irqtask.h @@ -0,0 +1,22 @@ +#ifndef _IRQTASK_H_ +#define _IRQTASK_H_ + +#include "list.h" + +// smaller is more preemptive +#define UART_IRQ_PRIORITY 1 +#define TIMER_IRQ_PRIORITY 0 + +typedef struct irqtask +{ + struct list_head listhead; + unsigned long long priority; + void *task_function; +} irqtask_t; + +void irqtask_add(void *task_function, unsigned long long priority); +void irqtask_run(irqtask_t *the_task); +void irqtask_run_preemptive(); +void irqtask_init_list(); + +#endif diff --git a/lab8/kernel/include/list.h b/lab8/kernel/include/list.h new file mode 100644 index 000000000..65ba89fea --- /dev/null +++ b/lab8/kernel/include/list.h @@ -0,0 +1,223 @@ +#ifndef LIST_H +#define LIST_H + +#include + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + * + * https://github.com/torvalds/linux/blob/master/include/linux/list.h + * https://elixir.bootlin.com/linux/latest/source/scripts/kconfig/list.h#L24 + */ + +typedef struct list_head { + struct list_head *next, *prev; +}list_head_t; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) +{ + return list == head; +} + + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_size(const struct list_head *head) +{ + list_head_t *pos; + int i= 0; + list_for_each(pos, head) + { + i++; + } + return i; +} + +/* "typeof" is a GNU extension. + * Reference: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html + */ +#if defined(__GNUC__) +#define __LIST_HAVE_TYPEOF 1 +#endif /* defined(__GNUC__) */ + +/** + * container_of() - Calculate address of object that contains address ptr + * @ptr: pointer to member variable + * @type: type of the structure containing ptr + * @member: name of the member variable in struct @type + * + * Return: @type pointer of object containing ptr + */ +#ifndef container_of +#ifdef __LIST_HAVE_TYPEOF +#define container_of(ptr, type, member) \ + __extension__({ \ + const __typeof__(((type *) 0)->member) *__pmember = (ptr); \ + (type *) ((char *) __pmember - offsetof(type, member)); \ + }) +#else /* __LIST_HAVE_TYPEOF */ +#define container_of(ptr, type, member) \ + ((type *) ((char *) (ptr) -offsetof(type, member))) +#endif /* __LIST_HAVE_TYPEOF */ +#endif /* container_of */ + +/** + * list_entry() - Calculate address of entry that contains list node + * @node: pointer to list node + * @type: type of the entry containing the list node + * @member: name of the list_head member variable in struct @type + * + * Return: @type pointer of entry containing node + */ +#define list_entry(node, type, member) container_of(node, type, member) + +/** + * list_first_entry() - get first entry of the list + * @head: pointer to the head of the list + * @type: type of the entry containing the list node + * @member: name of the list_head member variable in struct @type + * + * Return: @type pointer of first entry in list + */ +#define list_first_entry(head, type, member) \ + list_entry((head)->next, type, member) + +/** + * list_for_each_entry - iterate over list entries + * @entry: pointer used as iterator + * @head: pointer to the head of the list + * @member: name of the list_head member variable in struct type of @entry + * + * The nodes and the head of the list must be kept unmodified while + * iterating through it. Any modifications to the the list will cause undefined + * behavior. + * + * FIXME: remove dependency of __typeof__ extension + */ +#ifdef __LIST_HAVE_TYPEOF +#define list_for_each_entry(entry, head, member) \ + for (entry = list_entry((head)->next, __typeof__(*entry), member); \ + &entry->member != (head); \ + entry = list_entry(entry->member.next, __typeof__(*entry), member)) +#endif /* __LIST_HAVE_TYPEOF */ + +/** + * iter_for_each_entry - iterate over list entries from @iter + * @entry: pointer used as iterator + * @iter: pointer to the start of this iteration + * @head: pointer to the head of the list + * @member: name of the list_head member variable in struct type of @entry + * + * FIXME: remove dependency of __typeof__ extension + */ +#ifdef __LIST_HAVE_TYPEOF +#define iter_for_each_entry(entry, iter, head, member) \ + for (entry = list_entry(iter, __typeof__(*entry), member); \ + &entry->member != (head); \ + entry = list_entry(entry->member.next, __typeof__(*entry), member)) +#endif /* __LIST_HAVE_TYPEOF */ + +#endif diff --git a/lab8/kernel/include/mbox.h b/lab8/kernel/include/mbox.h new file mode 100644 index 000000000..d5f9514ff --- /dev/null +++ b/lab8/kernel/include/mbox.h @@ -0,0 +1,63 @@ +#ifndef _MBOX_H_ +#define _MBOX_H_ + +extern volatile unsigned int pt[36]; + +// Mailbox Register MMIO +// https://jsandler18.github.io/extra/mailbox.html +// include/bcm2837/rpi_mbox.h + +// Mailbox Channels +// https://github.com/raspberrypi/firmware/wiki/Mailboxes +typedef enum { + MBOX_POWER_MANAGEMENT = 0, + MBOX_FRAMEBUFFER, + MBOX_VIRTUAL_UART, + MBOX_VCHIQ, + MBOX_LEDS, + MBOX_BUTTONS, + MBOX_TOUCHSCREEN, + MBOX_UNUSED, + MBOX_TAGS_ARM_TO_VC, + MBOX_TAGS_VC_TO_ARM, +} mbox_channel_type; + +// Status Code from Broadcom Videocode Driver +// brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/arm_control.h +enum mbox_status_reg_bits { + BCM_ARM_VC_MS_FULL = 0x80000000, + BCM_ARM_VC_MS_EMPTY = 0x40000000, + BCM_ARM_VC_MS_LEVEL = 0x400000FF, +}; + +enum mbox_buffer_status_code { + MBOX_REQUEST_PROCESS = 0x00000000, + MBOX_REQUEST_SUCCEED = 0x80000000, + MBOX_REQUEST_FAILED = 0x80000001, +}; + +// Tag +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +// Included partition only +typedef enum { + /* Videocore */ + MBOX_TAG_GET_FIRMWARE_VERSION = 0x1, + + /* Hardware */ + MBOX_TAG_GET_BOARD_MODEL = 0x10001, + MBOX_TAG_GET_BOARD_REVISION, + MBOX_TAG_GET_BOARD_MAC_ADDRESS, + MBOX_TAG_GET_BOARD_SERIAL, + MBOX_TAG_GET_ARM_MEMORY, + MBOX_TAG_GET_VC_MEMORY, + MBOX_TAG_GET_CLOCKS, + +} mbox_tag_type; + + +#define MBOX_TAG_REQUEST_CODE 0x00000000 +#define MBOX_TAG_LAST_BYTE 0x00000000 + +int mbox_call(mbox_channel_type, unsigned int); + +#endif /*_MBOX_H_*/ diff --git a/lab8/kernel/include/memory.h b/lab8/kernel/include/memory.h new file mode 100644 index 000000000..3d8aee537 --- /dev/null +++ b/lab8/kernel/include/memory.h @@ -0,0 +1,71 @@ +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +#include "bcm2837/rpi_mmu.h" +#include "list.h" + +/* Lab2 */ +void* s_allocator(unsigned int size); +void s_free(void* ptr); + +/* Lab4 */ +#define BUDDY_MEMORY_BASE PHYS_TO_VIRT(0x0) // 0x10000000 - 0x20000000 (SPEC) -> Advanced #3 for all memory region +#define BUDDY_MEMORY_PAGE_COUNT 0x3C000 // let BUDDY_MEMORY use 0x0 ~ 0x3C000000 (SPEC) +#define PAGESIZE 0x1000 // 4KB +#define MAX_PAGES 0x10000 // 65536 (Entries), PAGESIZE * MAX_PAGES = 0x10000000 (SPEC) + +typedef enum { + FRAME_FREE = -2, + FRAME_ALLOCATED, + FRAME_IDX_0 = 0, // 0x1000 + FRAME_IDX_1, // 0x2000 + FRAME_IDX_2, // 0x4000 + FRAME_IDX_3, // 0x8000 + FRAME_IDX_4, // 0x10000 + FRAME_IDX_5, // 0x20000 + FRAME_IDX_6, // 0x40000 + FRAME_IDX_FINAL = 7, // 0x80000 + FRAME_MAX_IDX = 8 +} frame_value_type; + +typedef enum { + CACHE_NONE = -1, // Cache not used + CACHE_IDX_0 = 0, // 0x20 + CACHE_IDX_1, // 0x40 + CACHE_IDX_2, // 0x80 + CACHE_IDX_3, // 0x100 + CACHE_IDX_4, // 0x200 + CACHE_IDX_5, // 0x400 + CACHE_IDX_FINAL = 6, // 0x800 + CACHE_MAX_IDX = 7 +} cache_value_type; + +typedef struct frame +{ + struct list_head listhead; // store freelist + int val; // store order + int used; + int cache_order; + unsigned int idx; +} frame_t; + +void init_allocator(); +frame_t *release_redundant(frame_t *frame); +frame_t *get_buddy(frame_t *frame); +frame_t *coalesce(frame_t *frame_ptr); + +void dump_page_info(); +void dump_cache_info(); + +//buddy system +void* page_malloc(unsigned int size); +void page_free(void *ptr); +void page2caches(int order); +void* cache_malloc(unsigned int size); +void cache_free(void* ptr); + +void* kmalloc(unsigned int size); +void kfree(void *ptr); +void memory_reserve(unsigned long long start, unsigned long long end); + +#endif /* _MEMORY_H_ */ diff --git a/lab8/kernel/include/mmu.h b/lab8/kernel/include/mmu.h new file mode 100644 index 000000000..b882e42d0 --- /dev/null +++ b/lab8/kernel/include/mmu.h @@ -0,0 +1,69 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#include "stddef.h" + // tcr_el1: The control register for stage 1 of the EL1&0 translation regime. +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) // T0SZ[5:0] The size offset for ttbr0_el1 is 2**(64-T0SZ): 0x0000_0000_0000_0000 <- 0x0000_FFFF_FFFF_FFFF +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) // T1SZ[21:16] The size offset for ttbr1_el1 is 2**(64-T1SZ): 0xFFFF_0000_0000_0000 -> 0xFFFF_FFFF_FFFF_FFFF +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) // TG0[15:14] Granule size for the TTBR0_EL1: 0b00 = 4KB // TG1[31:30] Granule size for the TTBR1_EL1: 0b10 = 4KB + +#define MAIR_DEVICE_nGnRnE 0b00000000 // ((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) +#define MAIR_NORMAL_NOCACHE 0b01000100 // mair_el1: Provides the memory attribute encodings corresponding to the possible AttrIndx values for stage 1 translations at EL1. +#define MAIR_IDX_DEVICE_nGnRnE 0 // ATTR0[7:0]: 0b0000dd00 Device memory, dd = 0b00 Device-nGnRnE memory +#define MAIR_IDX_NORMAL_NOCACHE 1 // ATTR1[14:8] 0booooiiii Normal memory, oooo = 0b0100 Outer Non-cacheable, iiii = 0b0100 Inner Non-cacheable + +#define PD_TABLE 0b11L // Table Entry Armv8_a_address_translation p.14 +#define PD_BLOCK 0b01L // Block Entry +#define PD_UNX (1L << 54) // non-executable page frame for EL0 if set +#define PD_KNX (1L << 53) // non-executable page frame for EL1 if set +#define PD_ACCESS (1L << 10) // a page fault is generated if not set +#define PD_RDONLY (1L << 7) // 0 for read-write, 1 for read-only. +#define PD_UK_ACCESS (1L << 6) // 0 for only kernel access, 1 for user/kernel access. + +#define PERIPHERAL_START 0x3c000000L +#define PERIPHERAL_END 0x3f000000L +#define USER_KERNEL_BASE 0x00000000L +#define USER_STACK_BASE 0xfffffffff000L +#define USER_SIGNAL_WRAPPER_VA 0xffffffff9000L + +#define MMU_PGD_BASE 0x1000L +#define MMU_PGD_ADDR (MMU_PGD_BASE + 0x0000L) +#define MMU_PUD_ADDR (MMU_PGD_BASE + 0x1000L) +#define MMU_PTE_ADDR (MMU_PGD_BASE + 0x2000L) + +// Used for EL1 +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE | PD_ACCESS) +#define BOOT_PTE_ATTR_nGnRnE (PD_BLOCK | PD_ACCESS | (MAIR_DEVICE_nGnRnE << 2) | PD_UNX | PD_KNX | PD_UK_ACCESS) // p.17 +#define BOOT_PTE_ATTR_NOCACHE (PD_BLOCK | PD_ACCESS | (MAIR_NORMAL_NOCACHE << 2)) + +#ifndef __ASSEMBLER__ + +#include "sched.h" +#include "exception.h" + +typedef struct vm_area_struct +{ + + list_head_t listhead; + unsigned long virt_addr; + unsigned long phys_addr; + unsigned long area_size; + unsigned long rwx; // 1, 2, 4 + int is_alloced; + +} vm_area_struct_t; + +void *set_2M_kernel_mmu(void *x0); +void map_one_page(size_t *pgd_p, size_t va, size_t pa, size_t flag); + +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced); +void mmu_del_vma(struct thread *t); +void mmu_map_pages(size_t *pgd_p, size_t va, size_t size, size_t pa, size_t flag); +void mmu_free_page_tables(size_t *page_table, int level); + +void mmu_memfail_abort_handle(esr_el1_t* esr_el1); + +#endif //__ASSEMBLER__ + +#endif /* _MMU_H_ */ diff --git a/lab8/kernel/include/power.h b/lab8/kernel/include/power.h new file mode 100644 index 000000000..bd8e84b1d --- /dev/null +++ b/lab8/kernel/include/power.h @@ -0,0 +1,9 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#include "bcm2837/rpi_mmu.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC PHYS_TO_VIRT(0x3F10001c) +#define PM_WDOG PHYS_TO_VIRT(0x3F100024) + +#endif /*_POWER_H_*/ diff --git a/lab8/kernel/include/sched.h b/lab8/kernel/include/sched.h new file mode 100644 index 000000000..c99a9e101 --- /dev/null +++ b/lab8/kernel/include/sched.h @@ -0,0 +1,70 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#include "list.h" +#include "vfs.h" + +#define PIDMAX 32768 +#define USTACK_SIZE 0x4000 +#define KSTACK_SIZE 0x4000 +#define SIGNAL_MAX 64 + +extern void switch_to(void *curr_context, void *next_context); +extern void store_context(void *curr_context); +extern void load_context(void *curr_context); +extern void *get_current(); + +typedef struct thread_context +{ + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; + unsigned long lr; + unsigned long sp; + void* pgd; // use for MMU mapping (user space) +} thread_context_t; + +typedef struct thread +{ + list_head_t listhead; + thread_context_t context; + char* data; + unsigned int datasize; + int iszombie; + int pid; + int isused; + char* stack_alloced_ptr; + char* kernel_stack_alloced_ptr; + void (*signal_handler[SIGNAL_MAX+1])(); + int sigcount[SIGNAL_MAX + 1]; + void (*curr_signal_handler)(); + int signal_is_checking; + thread_context_t signal_saved_context; + list_head_t vma_list; + char curr_working_dir[MAX_PATH_NAME+1]; + struct file* file_descriptors_table[MAX_FD+1]; +} thread_t; + +extern thread_t *curr_thread; +extern list_head_t *run_queue; +extern list_head_t *wait_queue; +extern thread_t threads[PIDMAX + 1]; + +void schedule_timer(char *notuse); +void init_thread_sched(); +void idle(); +void schedule(); +void kill_zombies(); +void thread_exit(); +thread_t *thread_create(void *start, unsigned int filesize); +int thread_exec(char *data, unsigned int filesize); + +#endif /* _SCHED_H_ */ diff --git a/lab8/kernel/include/sdhost.h b/lab8/kernel/include/sdhost.h new file mode 100644 index 000000000..fb7cd6b80 --- /dev/null +++ b/lab8/kernel/include/sdhost.h @@ -0,0 +1,8 @@ +#ifndef _SDHOST_H_ +#define _SDHOST_H_ + +void readblock(int block_idx, void* buf); +void writeblock(int block_idx, void* buf); +void sd_init(); + +#endif /* _SDHOST_H_ */ diff --git a/lab8/kernel/include/shell.h b/lab8/kernel/include/shell.h new file mode 100644 index 000000000..8c7caf695 --- /dev/null +++ b/lab8/kernel/include/shell.h @@ -0,0 +1,29 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +#define CMD_MAX_LEN 0x100 +#define MSG_MAX_LEN 0x100 + +typedef struct CLI_CMDS +{ + char command[CMD_MAX_LEN]; + char help[MSG_MAX_LEN]; +} CLI_CMDS; + +int cli_cmd_strcmp(const char*, const char*); +void cli_cmd_clear(char*, int); +void cli_cmd_read(char*); +void cli_cmd_exec(char*); +void cli_print_banner(); + +void do_cmd_cat(char*); +void do_cmd_dtb(); +void do_cmd_exec(char*); +void do_cmd_help(); +void do_cmd_hello(); +void do_cmd_info(); +void do_cmd_ls(char*); +void do_cmd_setTimeout(char* msg, char* sec); +void do_cmd_reboot(); + +#endif /* _SHELL_H_ */ diff --git a/lab8/kernel/include/signal.h b/lab8/kernel/include/signal.h new file mode 100644 index 000000000..f228de096 --- /dev/null +++ b/lab8/kernel/include/signal.h @@ -0,0 +1,47 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +#include "exception.h" + +void signal_default_handler(); +void check_signal(trapframe_t *tpf); +void run_signal(trapframe_t* tpf,int signal); +void signal_handler_wrapper(); + +#endif /* _SIGNAL_H_ */ diff --git a/lab8/kernel/include/stddef.h b/lab8/kernel/include/stddef.h new file mode 100644 index 000000000..1698bc3f3 --- /dev/null +++ b/lab8/kernel/include/stddef.h @@ -0,0 +1,11 @@ +#ifndef STDDEF_H +#define STDDEF_H + +#define NULL 0 +#define size_t unsigned long + +/* Offset of member MEMBER in a struct of type TYPE. */ +#undef offsetof /* in case a system header has defined it. */ +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) + +#endif diff --git a/lab8/kernel/include/string.h b/lab8/kernel/include/string.h new file mode 100644 index 000000000..f4ba13fa4 --- /dev/null +++ b/lab8/kernel/include/string.h @@ -0,0 +1,24 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "stddef.h" +#define VSPRINT_MAX_BUF_SIZE 0x100 + +unsigned int sprintf(char *dst, char* fmt, ...); +unsigned int vsprintf(char *dst,char* fmt, __builtin_va_list args); + +unsigned long long strlen(const char *str); +char* strcat(char *dest, const char *src); +char* strncat(char *dest, const char *src, int n); +int strcasecmp(const char *s1, const char *s2); +int strcmp(const char*, const char*); +int strncmp(const char*, const char*, unsigned long long); +char* memcpy(void *dest, const void *src, unsigned long long len); +char* strcpy(char *dest, const char *src); +void* memset(void *s, int c, size_t n); +char* strchr(register const char *s, int c); + +char* str_SepbySpace(char* head); +int atoi(char* str); + +#endif /* _STRING_H_ */ diff --git a/lab8/kernel/include/syscall.h b/lab8/kernel/include/syscall.h new file mode 100644 index 000000000..169552061 --- /dev/null +++ b/lab8/kernel/include/syscall.h @@ -0,0 +1,34 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "exception.h" +#include "stddef.h" + +int getpid(trapframe_t *tpf); +size_t uartread(trapframe_t *tpf, char buf[], size_t size); +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size); +int exec(trapframe_t *tpf, const char *name, char *const argv[]); +int fork(trapframe_t *tpf); +void exit(trapframe_t *tpf, int status); +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox); +void kill(trapframe_t *tpf, int pid); +void signal_register(int signal, void (*handler)()); +void signal_kill(int pid, int signal); +void* mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset); +void sigreturn(trapframe_t *tpf); + +int open(trapframe_t *tpf, const char *pathname, int flags); +int close(trapframe_t *tpf, int fd); +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count); +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count); +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode); +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data); +int chdir(trapframe_t *tpf, const char *path); +long lseek64(trapframe_t *tpf, int fd, long offset, int whence); +int ioctl(trapframe_t *tpf, int fd, unsigned long request, void *info); +int sync(trapframe_t *tpf); + +unsigned int get_file_size(char *thefilepath); +char *get_file_start(char *thefilepath); + +#endif /* _SYSCALL_H_*/ diff --git a/lab8/kernel/include/timer.h b/lab8/kernel/include/timer.h new file mode 100644 index 000000000..894a23b9c --- /dev/null +++ b/lab8/kernel/include/timer.h @@ -0,0 +1,29 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "list.h" +//https://github.com/Tekki/raspberrypi-documentation/blob/master/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf p13 +#define CORE0_TIMER_IRQ_CTRL PHYS_TO_VIRT(0x40000040) + +typedef struct timer_event +{ + struct list_head listhead; + unsigned long long interrupt_time; + void *callback; + char *args; +} timer_event_t; + +extern struct list_head *timer_event_list; + +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler(); + +void add_timer(void *callback, unsigned long long timeout, char *args, int bytick); +unsigned long long get_tick_plus_s(unsigned long long second); +void set_core_timer_interrupt(unsigned long long expired_time); +void set_core_timer_interrupt_by_tick(unsigned long long tick); +void timer_list_init(); +int timer_list_get_size(); + +#endif /* _TIMER_H_ */ diff --git a/lab8/kernel/include/tmpfs.h b/lab8/kernel/include/tmpfs.h new file mode 100644 index 000000000..50367d448 --- /dev/null +++ b/lab8/kernel/include/tmpfs.h @@ -0,0 +1,38 @@ +#ifndef _TMPFS_H_ +#define _TMPFS_H_ + +#include "stddef.h" +#include "vfs.h" + +// SPEC basic Note #3 +#define MAX_FILE_NAME 15 +#define MAX_DIR_ENTRY 16 +#define MAX_FILE_SIZE 4096 + +struct tmpfs_inode +{ + enum fsnode_type type; + char name[MAX_FILE_NAME]; + struct vnode *entry[MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_tmpfs(); +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int tmpfs_write(struct file *file, const void *buf, size_t len); +int tmpfs_read(struct file *file, void *buf, size_t len); +int tmpfs_open(struct vnode *file_node, struct file **target); +int tmpfs_close(struct file *file); +long tmpfs_lseek64(struct file *file, long offset, int whence); +long tmpfs_getsize(struct vnode *vd); + +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_sync(struct filesystem *fs); + +struct vnode *tmpfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +#endif /* _TMPFS_H_ */ diff --git a/lab8/kernel/include/uart1.h b/lab8/kernel/include/uart1.h new file mode 100644 index 000000000..933b9c816 --- /dev/null +++ b/lab8/kernel/include/uart1.h @@ -0,0 +1,18 @@ +#ifndef _UART1_H_ +#define _UART1_H_ + +void uart_init(); +char uart_recv(); +void uart_send(char c); +int uart_sendline(char* fmt, ...); +char uart_async_getc(); +void uart_async_putc(char c); +int uart_puts(char* fmt, ...); +void uart_2hex(unsigned int d); + +void uart_interrupt_enable(); +void uart_interrupt_disable(); +void uart_r_irq_handler(); +void uart_w_irq_handler(); + +#endif /*_UART1_H_*/ diff --git a/lab8/kernel/include/vfs.h b/lab8/kernel/include/vfs.h new file mode 100644 index 000000000..aa3f78030 --- /dev/null +++ b/lab8/kernel/include/vfs.h @@ -0,0 +1,91 @@ +#ifndef _VFS_H_ +#define _VFS_H_ + +#include "stddef.h" + +#define MAX_PATH_NAME 255 +#define MAX_FD 16 +#define O_CREAT 00000100 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#define MAX_FS_REG 0x50 +#define MAX_DEV_REG 0x10 + +enum fsnode_type +{ + dir_t, + file_t +}; + +struct vnode +{ + struct mount *mount; // Superblock : represents mounted fs + struct vnode_operations *v_ops; // inode & dentry Ops: represents kernel methods for vnode + struct file_operations *f_ops; // file Ops : represents process methods for opened file + void *internal; // vnode itself : directly point to fs's vnode + struct vnode *parent; +}; + +// file handle +struct file +{ + struct vnode *vnode; + size_t f_pos; // RW position of this file handle + struct file_operations *f_ops; + int flags; +}; + +struct mount +{ + struct vnode *root; + struct filesystem *fs; +}; + +struct filesystem +{ + const char *name; + int (*setup_mount)(struct filesystem *fs, struct mount *mount); + int (*sync)(struct filesystem *fs); +}; + +struct file_operations +{ + int (*write)(struct file *file, const void *buf, size_t len); + int (*read)(struct file *file, void *buf, size_t len); + int (*open)(struct vnode *file_node, struct file **target); + int (*close)(struct file *file); + long (*lseek64)(struct file *file, long offset, int whence); + long (*getsize)(struct vnode *vd); +}; + +struct vnode_operations +{ + int (*lookup)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*create)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*mkdir)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*isdir)(struct vnode *dir_node); + int (*getname)(struct vnode *dir_node, const char **name); + int (*getsize)(struct vnode *dir_node); +}; + +extern struct filesystem reg_fs[MAX_FS_REG]; + +int register_filesystem(struct filesystem *fs); +int register_dev(struct file_operations* fo); +struct filesystem *find_filesystem(const char *fs_name); +int vfs_open(const char *pathname, int flags, struct file **target); +int vfs_close(struct file *file); +int vfs_write(struct file *file, const void *buf, size_t len); +int vfs_read(struct file *file, void *buf, size_t len); +int vfs_mkdir(const char *pathname); +int vfs_mount(const char *target, const char *filesystem); +int vfs_lookup(const char *pathname, struct vnode **target); +int vfs_mknod(char* pathname, int id); +int vfs_sync(struct filesystem *fs); + +void init_rootfs(); +void vfs_test(); +char* get_absolute_path(char* path,char* curr_working_dir); + +#endif /* _VFS_H_ */ From 8a73afd4f0cfac3da643db3739e73c0d3b3a0a5a Mon Sep 17 00:00:00 2001 From: Hst0411 <73873452+Hst0411@users.noreply.github.com> Date: Thu, 27 Jun 2024 01:00:32 +0800 Subject: [PATCH 07/19] Add files via upload --- lab8/kernel/build/boot_s.d | 1 + lab8/kernel/build/boot_s.o | Bin 0 -> 1928 bytes lab8/kernel/build/cpio_c.d | 2 ++ lab8/kernel/build/cpio_c.o | Bin 0 -> 2584 bytes lab8/kernel/build/dev_framebuffer_c.d | 6 ++++++ lab8/kernel/build/dev_framebuffer_c.o | Bin 0 -> 7136 bytes lab8/kernel/build/dev_uart_c.d | 3 +++ lab8/kernel/build/dev_uart_c.o | Bin 0 -> 2920 bytes lab8/kernel/build/dtb_c.d | 4 ++++ lab8/kernel/build/dtb_c.o | Bin 0 -> 5984 bytes lab8/kernel/build/entry_s.d | 1 + lab8/kernel/build/entry_s.o | Bin 0 -> 9144 bytes lab8/kernel/build/exception_c.d | 6 ++++++ lab8/kernel/build/exception_c.o | Bin 0 -> 6104 bytes lab8/kernel/build/fat32_c.d | 6 ++++++ lab8/kernel/build/fat32_c.o | Bin 0 -> 20632 bytes lab8/kernel/build/initramfs_c.d | 4 ++++ lab8/kernel/build/initramfs_c.o | Bin 0 -> 5480 bytes lab8/kernel/build/irqtask_c.d | 4 ++++ lab8/kernel/build/irqtask_c.o | Bin 0 -> 4352 bytes lab8/kernel/build/kernel8.elf | Bin 0 -> 142504 bytes lab8/kernel/build/main_c.d | 6 ++++++ lab8/kernel/build/main_c.o | Bin 0 -> 2864 bytes lab8/kernel/build/mbox_c.d | 2 ++ lab8/kernel/build/mbox_c.o | Bin 0 -> 1632 bytes lab8/kernel/build/memory_c.d | 5 +++++ lab8/kernel/build/memory_c.o | Bin 0 -> 10232 bytes lab8/kernel/build/mmu_c.d | 5 +++++ lab8/kernel/build/mmu_c.o | Bin 0 -> 5160 bytes lab8/kernel/build/sched_c.d | 6 ++++++ lab8/kernel/build/sched_c.o | Bin 0 -> 8320 bytes lab8/kernel/build/sched_s.d | 1 + lab8/kernel/build/sched_s.o | Bin 0 -> 1008 bytes lab8/kernel/build/sdhost_c.d | 1 + lab8/kernel/build/sdhost_c.o | Bin 0 -> 4256 bytes lab8/kernel/build/shell_c.d | 5 +++++ lab8/kernel/build/shell_c.o | Bin 0 -> 13968 bytes lab8/kernel/build/signal_c.d | 5 +++++ lab8/kernel/build/signal_c.o | Bin 0 -> 3184 bytes lab8/kernel/build/string_c.d | 2 ++ lab8/kernel/build/string_c.o | Bin 0 -> 6096 bytes lab8/kernel/build/syscall_c.d | 7 +++++++ lab8/kernel/build/syscall_c.o | Bin 0 -> 15368 bytes lab8/kernel/build/timer_c.d | 5 +++++ lab8/kernel/build/timer_c.o | Bin 0 -> 5624 bytes lab8/kernel/build/tmpfs_c.d | 4 ++++ lab8/kernel/build/tmpfs_c.o | Bin 0 -> 6512 bytes lab8/kernel/build/uart1_c.d | 5 +++++ lab8/kernel/build/uart1_c.o | Bin 0 -> 6752 bytes lab8/kernel/build/vfs_c.d | 5 +++++ lab8/kernel/build/vfs_c.o | Bin 0 -> 10376 bytes 51 files changed, 101 insertions(+) create mode 100644 lab8/kernel/build/boot_s.d create mode 100644 lab8/kernel/build/boot_s.o create mode 100644 lab8/kernel/build/cpio_c.d create mode 100644 lab8/kernel/build/cpio_c.o create mode 100644 lab8/kernel/build/dev_framebuffer_c.d create mode 100644 lab8/kernel/build/dev_framebuffer_c.o create mode 100644 lab8/kernel/build/dev_uart_c.d create mode 100644 lab8/kernel/build/dev_uart_c.o create mode 100644 lab8/kernel/build/dtb_c.d create mode 100644 lab8/kernel/build/dtb_c.o create mode 100644 lab8/kernel/build/entry_s.d create mode 100644 lab8/kernel/build/entry_s.o create mode 100644 lab8/kernel/build/exception_c.d create mode 100644 lab8/kernel/build/exception_c.o create mode 100644 lab8/kernel/build/fat32_c.d create mode 100644 lab8/kernel/build/fat32_c.o create mode 100644 lab8/kernel/build/initramfs_c.d create mode 100644 lab8/kernel/build/initramfs_c.o create mode 100644 lab8/kernel/build/irqtask_c.d create mode 100644 lab8/kernel/build/irqtask_c.o create mode 100644 lab8/kernel/build/kernel8.elf create mode 100644 lab8/kernel/build/main_c.d create mode 100644 lab8/kernel/build/main_c.o create mode 100644 lab8/kernel/build/mbox_c.d create mode 100644 lab8/kernel/build/mbox_c.o create mode 100644 lab8/kernel/build/memory_c.d create mode 100644 lab8/kernel/build/memory_c.o create mode 100644 lab8/kernel/build/mmu_c.d create mode 100644 lab8/kernel/build/mmu_c.o create mode 100644 lab8/kernel/build/sched_c.d create mode 100644 lab8/kernel/build/sched_c.o create mode 100644 lab8/kernel/build/sched_s.d create mode 100644 lab8/kernel/build/sched_s.o create mode 100644 lab8/kernel/build/sdhost_c.d create mode 100644 lab8/kernel/build/sdhost_c.o create mode 100644 lab8/kernel/build/shell_c.d create mode 100644 lab8/kernel/build/shell_c.o create mode 100644 lab8/kernel/build/signal_c.d create mode 100644 lab8/kernel/build/signal_c.o create mode 100644 lab8/kernel/build/string_c.d create mode 100644 lab8/kernel/build/string_c.o create mode 100644 lab8/kernel/build/syscall_c.d create mode 100644 lab8/kernel/build/syscall_c.o create mode 100644 lab8/kernel/build/timer_c.d create mode 100644 lab8/kernel/build/timer_c.o create mode 100644 lab8/kernel/build/tmpfs_c.d create mode 100644 lab8/kernel/build/tmpfs_c.o create mode 100644 lab8/kernel/build/uart1_c.d create mode 100644 lab8/kernel/build/uart1_c.o create mode 100644 lab8/kernel/build/vfs_c.d create mode 100644 lab8/kernel/build/vfs_c.o diff --git a/lab8/kernel/build/boot_s.d b/lab8/kernel/build/boot_s.d new file mode 100644 index 000000000..6de4abbe6 --- /dev/null +++ b/lab8/kernel/build/boot_s.d @@ -0,0 +1 @@ +build/boot_s.o: src/boot.S include/mmu.h include/stddef.h diff --git a/lab8/kernel/build/boot_s.o b/lab8/kernel/build/boot_s.o new file mode 100644 index 0000000000000000000000000000000000000000..3adf2a5075722b06162dddef6cdba1c6fa6c3c99 GIT binary patch literal 1928 zcmbuA&ubGw6vyBGXiZOU>yHLnFls@Rve2U7L3Hg8=|Q2r1w0I!WZQ-&yJ0iY*h@q4 z=%GSE4}w@dNDm@C=*2_*7Yf_62mb(%_7vaSnKkPqd#Mj*-}ilH-kTpg*=#L7e4uL@ zB&NYv=tT(ySQ_eSCzcM3Kn|`0?EV~r;zA)GkvI2**M^~Zg&OGl+W;pzY6Ch)^I+^> z#n^z4LYr`6V(t{S?%CA?EWN8+x1%|54sR7BHqdtYAdlZg*UR&qvzmWc04xIntcT=q|P&#@l1sh6PrK zJS@ad0>TQy88S3XDgMJ515Xyf0DWLp1A7LU0sV^+@2sB-V!{Wd(D^tv`zqa#d|es8 zD0xHSE0VVr{#f#k!Yh*RD7-HD8-+iW{96V;R5;~ZeY*nKjJYxxLpy`N$l$Ls`1=h0 zDTCAbCRYt*&!*b28U}Ud)n*wF(9J;8v`E~zzyb9DXbt@bxFGEzGVkrakvC&kAn~lt%zX3S z_kPWc^7i8Lg_L1HiGgo0TqzW|_t0=|M^hUQV-kaR@KcaR*iWN3$kCTYZwWXWQGAhrCAHh;-j0-C%`uR;Z7+jZCma^Cg;3 zV48jGkdJ8XpPa@KWK!&l_LW|rxMr!}!HjT|PwIV-ZSS&egxg_oINqOOd(nwF)PBOJ zD?ay$FNp7e&PU`+xHumZcDQDYuTR87x)ck=)G6=Y_~8q#H`Nb?XXsZXN9FlT%ZugN zSt7o;u<&gDiPg33y1$(-7Ogp}aHhB&EsJlRJ!=)_P74ewMJ&dfWlXeB8rjJljuLcS z@T&$*=BM(h)hXm@S`fSufY;BN7=gTUK3$BElntUdaw70Zhubf3wyMH$HYI!mlPGh8lR_4HBaiT=n2WD zuFLn6F+Kj0*q4%|G}q%V6UIHY=}U?&2SVk={bO5YulhI6H}mX>|639;zo-0m>h|=1 f!btB3LP^e#!;6II`SV>LSE`1@?`L|mM zxQ@~afY-RPzcz{SciHbt#_bHOOkRPtva>tZ90&P!%kL6?4g0%=KZAZx>|f!Wy|EVN zbS=MM_>^-%_>^-n_K!HG&UCDWIY%siH1_+(MB9tozvlX0jI}F(eyXZcgHe}u-E`Jo@K{d}y2bIMwNUik3lq*IFhz94Q>Y?!YaYhg{7Ex#7~ zeOE>MTHM}Dz)u15;htIT19)|9C!FE^0~6lez8bvhNUek#ax*&whnf?>0gjV(JKdhy zk8oY?O{YiEuPXXXYaMWGnnQhi`)@A5+t~hHR7W^oBMH#WK3-R4du#cF^?Qlwzi%!7 zG5j9Y4?$z|AT+-2ga)zoLtev4dX0Lg*EoW?IkpYrTJU>!*Sidd>sZ4J0RPz2#_JM( zFTWqpv0_||3G2o&0LO3v{!)*|#qToJj^oCCZ-0$7Y#v0mMO{&yre@@}mOl#TwS5Bq zTHl3pN+`2*eXu@S3#x(ox0XMQ z#(4|J!M@FX;o99rCfp;N0B1J$d0~u0<5DcnwJp3SwO?(&73IfV2WTA3`#;&)LS{Da zyFt;d_<>uQEBk)IE&G*XeksTm3)C@`9v-P4J33nZ+3;R?0qu#s056|7@w_{5c6O-{ zEV)BNsgYFrxuK=d9eRCuIF%lG*2qygU8XAM7n6{zKI0s2?}J{{_*g!bK<9Wz*Uh$D zPTR&;Uv{8N{iFCt_JBT)ccgFbytN~Uy2DL*j&!tB^nvjc7)Ws?^3h!SINssjOx{YI z6mhgc$UOSM{?iyoHLjD7wmZ70pLm}k3EyqE0un9%2LedozgCvOOtu{ig=U@P1njVJ zi1=nb;&&;0v;L!yq}erF0`@eC(YSlVdtrAb05?htOSD+sr;yt()`4e^=VYj}&)1(A zo$nLtgGO)1D;ev<*rxov4>|5=sK@J;rXaMRwO=8aThS6Q4 zpF*FE4ll}+HM&b88Xd5tUo*N#BHD-eM>-pi{}~EgJNMD`b47os=-(=O5{GP+|DOuq zrto_d9p?SlrWeYYMSpf_VZkq_=AeHb`m1m;Hy>mn>*vmA11RN!xh&)=<@2+UUzoLn zri&%NoS}26($saaoD2LWwOE>-_Y0R==zgI|oXZz0%_;H~-@kBl1agI3fXRL^3n&G! zI9sev&t>v?Sjv=x>C#eAfwF%-R|)(w@v!JG&Xq2~QXyZQy8ss!@Q97imt(kIhjESB zc;Aj%dXE8Yp3XWlo9~Zgu=xR_+x)1)k10IwZ#)0E!t*(8^HU0+RqDwrd{yBuEBr4N zensJLDEykjzo+o;EBqf6{+_~rqVO9EUsrfKC&=vm@FM>>(LucJ^VbUMgA{DeyKlH@_(b`e{M%@FOBmx6nsL9;uIs zJkJPzO6c^g!&Vac<@yIAztk@aUhapQ;HCbK;Ay^TGw=<;OMT7g_By;P^2mDDMINcY zFL+tcZNW?ZQ^Cvo_(1Sde{6KB)8)m)YnOS>BK?TaCyY+}N8Yb9MyLHF^{UA8W08lO z^eXyEcJRu3iS+2%I_l&(l72|={5zj?Zd12w7}DuknQg!{?EHKt??B#sr9yJd@T~Lm z<&>rKb8KMg{2aS#>HHkazk50VeY0MWs$5zOGP8IM%F#8;t+JobqyoPhKx#e{WFR$L zsX!`J$){EdpPe#!6pIltS6p253m8x+27c=0(`TQn1Q~p~ilY2%^r&fS{C_Sk2ICUK zPAiFL{0*L;@hvxewj+&sgTWp1YGh+yq_pFO#^L?K_nzK!kZ!g$wj%3_UseN38eYclsKO2I*A&MFZVFI;FnqsFZOQ%Szg+*kiMQ)tH}Q95Qf%Ax)BC1Y>(^rr z4Y_`_r8u6~k7~EaMhRxjhUV}86R6Se7dxKb_}P00C0IAF0z0k6v0QxTro@~2U!!Eg H?D&5JCsCif literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/dev_uart_c.d b/lab8/kernel/build/dev_uart_c.d new file mode 100644 index 000000000..7a8609dcd --- /dev/null +++ b/lab8/kernel/build/dev_uart_c.d @@ -0,0 +1,3 @@ +build/dev_uart_c.o: src/dev_uart.c include/vfs.h include/stddef.h \ + include/dev_uart.h include/vfs.h include/uart1.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/list.h include/stddef.h diff --git a/lab8/kernel/build/dev_uart_c.o b/lab8/kernel/build/dev_uart_c.o new file mode 100644 index 0000000000000000000000000000000000000000..1c93144d7361cebaa76d2b45e1d05ca79c3f44fb GIT binary patch literal 2920 zcmbW2PiPcZ7{I^HM3b1f`R6~_Qb!CWf(}_5MT?M$(Ri_qmD+j`CX?NXE^cPi*;!4x zqB#nBh}44zle2{$N-5OPQe$bss}y=uCY}QALGd()HT}Lf-`kzOOa%RweeZj}@85fG z-n_YS^7Lp^Dg{zf@G~?aW|W)}Nx*+6X)iTCj$O`86}dxrQq(W{7)LAEQ3M2lpV= z3TU4@i!pbiefTZf2U$gvIaHL{@`qXuhyiWbU^n;}G} zb~vpsG%sqSoSWi)B977;b#HCy>^8%zwInAk@ni#N_)8KEGbM=zo7UkDLDut5!D&|O zMN3#wl&1}7-KuDSZ%l${5PLb<-h+L2Y@P$mKf=BT_ks4EWL&fWhp;CupOJWu$VQm2 zvY&W%sDIA9kC&#ieVq9T=JJ_+&79rp^=}}MXHwdzzr6v!zXAV#0}grTidC^a-^f8< z9{Oekm@E_>t2FI+wqGc@<+_t~)hqZ;W9T_{zA?f8w=v2UOXZkrY1+y=?kp7Cf{$8M z6g=l*q3k;z5uj;Uc6rv#S<@9i7aw1AaC~{va~xa;iQKnd+{frlL|p3I6)yKMgS4>7(y=HG#SBx>C*=4#zR=9GU&6#BoGJ}p~gM6QdtxERV6m7$IW_&R6wr_(mQ7(faD2+)oilv-g1S40PnsQupbW6TtociqC zfwFJsF0;3D$(r=+DS4)ND(}_l7=>F0o0Vvj$EV2{6ZPiIppBRr^C9&fUzy9y+p(uq z@|?)$Pxlsa^`^e9)I}E|D&CKja=vf;VT?_xKhK2*MAb$k=PyYXm8A8b=M9}_M_NB^ ziHw))A4Nu`)H=&tpVk)_#v+FJ82%-T`~8~)6MXZ`;_nXSdCBolXb=-Qe~BzqlGeYP zuzvc=$#}VbDx=n>+z%P{b5Hjp{ndENsXlu|5YVJhevG<$t8NS3F-h?={ONV;k&&Xt F{|8(@Ki&WU literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/dtb_c.d b/lab8/kernel/build/dtb_c.d new file mode 100644 index 000000000..9d76b74e9 --- /dev/null +++ b/lab8/kernel/build/dtb_c.d @@ -0,0 +1,4 @@ +build/dtb_c.o: src/dtb.c include/bcm2837/rpi_mmu.h include/dtb.h \ + include/uart1.h include/string.h include/stddef.h include/cpio.h \ + include/memory.h include/bcm2837/rpi_mmu.h include/list.h \ + include/stddef.h diff --git a/lab8/kernel/build/dtb_c.o b/lab8/kernel/build/dtb_c.o new file mode 100644 index 0000000000000000000000000000000000000000..aee4f9c76c4d5d627fb97668e787b54d37d74e51 GIT binary patch literal 5984 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 UU~j8p{^{17J9MZ`{>uCR1o9~SsQ>@~ literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/exception_c.d b/lab8/kernel/build/exception_c.d new file mode 100644 index 000000000..83c55516f --- /dev/null +++ b/lab8/kernel/build/exception_c.d @@ -0,0 +1,6 @@ +build/exception_c.o: src/exception.c include/bcm2837/rpi_uart1.h \ + include/bcm2837/rpi_base.h include/bcm2837/rpi_mmu.h include/uart1.h \ + include/exception.h include/bcm2837/rpi_irq.h include/timer.h \ + include/list.h include/stddef.h include/irqtask.h include/syscall.h \ + include/exception.h include/stddef.h include/sched.h include/vfs.h \ + include/signal.h include/mmu.h include/sched.h diff --git a/lab8/kernel/build/exception_c.o b/lab8/kernel/build/exception_c.o new file mode 100644 index 0000000000000000000000000000000000000000..d64c41f8db5edfaf37329720ece8d72c1b8b4d26 GIT binary patch literal 6104 zcmbuDe{3AZ702ItFR`J9xW<56hxpPaZ7|8zjw~8cBsPi*1|otYsHmv4tnW7Q$@jzA z+Y3jXQb%h40P;uDni8QT0zpfP_#pzM1{Z_q}=ZW_ETrKm7L2TiYxPxLEL8Sh`{gFx#`#c2v`WPWS>W?y}GK zr|t7+Z1=6di}u3Q>0d6`aHPHl8nAoY`TDics6T_({aE)q4FKmQt7mmLz^`}T0x(er zxTl$)Qv6`dVW!K1p1H-vC+cg^KJ7H>edw#tY4iikD;;rwnN_G$JO%UHE%d9n)3{*6 z^QxV48Xs^Q^=K67J65LuH|slBroX`YuI4!3VcrAtsF86FL@~q6S=RJ6k7cce?pAa8 zGwauyeg2*`>1LmplW1JbkII$ZHbD9O73(*As(zrZ^*?9*Ce+(Y^ZKXGxrP2!>>X+y zqA@$2#)mw9m(!Tzc8}Be2ev=5Qv-9hJ@6rp@qukUf5C2#))M1;gvZ<59A9F+4VPUG!&QuOtzzNc1U-(`=UP0vZYe$@xK2Gbo&eHQwZ*XwKRx-Ed0)&u#5 z!#Jiov*V(}krn+%)0j707 zwXwfzhqgPa`LO24+fG<_MrM#k_B-7_D*Er%{kp4VMPcCMb+J{a-SQ0r?=1Y+s@Ui$ zS*}okMrkgTzc%5YbGT7+zUKN{$SvW&L%X|G)yu~vYy+Mmi4y7CRjw0VsBcdqb#23{ zW&Cy|-53$?3$@raOH zaw(IA4K?r!LvFql`aw{g3|+tEjTQU^%;hVJ7RuQPH(SOB1Z>Db<)Kp6y>ZwL%2l+6 zVzKHL{o)=kUvRy#auB-XUMYvZ_WI#uJ_l7V2m{}X8V?5f5J#!`S=dt!Ca{$c(P1U) z6$)-~tXy-c1(p2Xl2>p8e{a4*W9aLNJoXif-XxSK{Sssg<%$o*iCi9|P|;<_sa>e} z{=|*LkS}LL^o8M)gTN1~K?(A~K8~Csb02hxL?H*%8+w%q*URPNc2F(3lY#FSF?sua zH6J%HBk%_*KuLO&|_^@7g`|MW4<<*4v4`7z-~`p0h$RcKu4|5d^9dn_)m zYfkgp98-WdG^cqJ`U%ELE= z|3SeA1cIXAJtI2K}=J{YiuVltKTZLC^Or{vQ~=CodJw z33Glw9?=r!e5T|QoZmNol;HgQJ(l47{5_rE{QQMX<)LEejbR-IQ9aJBz%O{2(65D% z$$6m%nXyU*GTCym=;O0CQ!0mk=C-@;-BJlXJnl0}?vJ~B0d_n-(^%TQ74wm@Q=pnpbIRV|F2=2xIPxCOO>A1pBhTb z8mj5uCZ9?BUTx3gk(NsGdI%Yf&-;cnRM=jg9mGjXh3lI{TXpE4krl?jOWVsmOfE*X z{jB!KRWg43f3cSNe?vd4PijNTKe=Rk&Ogl~IX0Q3wXm+&?{Z|cq)B`7o6J2Tfat>( b{>F(?a4B#466hVIm3>XWRD73(2K)a5(0#x2 literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/fat32_c.d b/lab8/kernel/build/fat32_c.d new file mode 100644 index 000000000..57d92dbfd --- /dev/null +++ b/lab8/kernel/build/fat32_c.d @@ -0,0 +1,6 @@ +build/fat32_c.o: src/fat32.c include/fat32.h include/list.h \ + include/stddef.h include/vfs.h include/stddef.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/sdhost.h include/string.h \ + include/list.h include/uart1.h include/exception.h \ + include/bcm2837/rpi_irq.h include/bcm2837/rpi_base.h \ + include/bcm2837/rpi_mmu.h diff --git a/lab8/kernel/build/fat32_c.o b/lab8/kernel/build/fat32_c.o new file mode 100644 index 0000000000000000000000000000000000000000..38fec0dc010f7415ee7400f0be6359e8edc5a888 GIT binary patch literal 20632 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 E8%Xsz#sB~S literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/irqtask_c.d b/lab8/kernel/build/irqtask_c.d new file mode 100644 index 000000000..8bd33d2fe --- /dev/null +++ b/lab8/kernel/build/irqtask_c.d @@ -0,0 +1,4 @@ +build/irqtask_c.o: src/irqtask.c include/irqtask.h include/list.h \ + include/stddef.h include/exception.h include/bcm2837/rpi_irq.h \ + include/bcm2837/rpi_base.h include/bcm2837/rpi_mmu.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/uart1.h diff --git a/lab8/kernel/build/irqtask_c.o b/lab8/kernel/build/irqtask_c.o new file mode 100644 index 0000000000000000000000000000000000000000..f39805d1aa979025e3c6d1365cd8c4a5346146b0 GIT binary patch literal 4352 zcmb_eO>9(E6h89<1v}D0O9laD7LB4QlPPIj5E7;-*cK~REQuzXVcHqeNvG3x<_&4B zU=vu7=mKIBjS00OERYc50;5e(@n_iuMnx7#rVTqbn7D9~Hsg2hJ9m0}JI|H3dA;|3 z=R4my_uM=8y$_D`zT)@!NH-sSO{+7FqTjMQj;mpuLR3$cPWq)(N99soyu649zN_OP zmG?vfzk_q>P9Slwat_=EDlgVkc}e>;zz4h%`l>&V>jg)@$QQW6fZ9Y=sNqd-lIz86ZTn|`tcgaujvzn566HX`}|?~==H%~E(Ih<&X?DVc{MLt zqZxzs{Ltr~b5k(_{_BtbBL>%i;~XM-Tnc}_lXla#YW<8_D?M;)@m8k3SG6Jk^l@y} z497)(5zi&gSC3iaVl|f^q(W2_@yJT0zn1-m*m00moOK-R z!5MIX&$#E~r#0t;ant9D=$$0ucr(u%ReRg4{iw{qXH zrLhP11s5qMc(02`-T=NE<8Hy*1-~4e4ZQmBPj$<%9raSJmYsDkh+XL;-ciw=6Wq)1 zj@b8d55I27^L`DS^LQfoLGHo7?4R|$X5`t3P2jf7|2nqBE^nOOaK^C5#J=F#BfQRW zu}6UQiM_?JcZr=Luf}dc`m0jQ9;khTQviRpS^!FRt5<*|XBc^d{D!{TZ(z>~uIFmM zf#G+m_!H>4seM7u^=F+M45DfLWsDgwF^HzmPY1?~>w0T`pWufjRkg3c-W5D+;X}Zw zMjc#yeH~o(M&)JxbNO}ZjGMU2ud^XF5735n_%M*IMm{=&vkKQUqD|s?0sS`AVMf-a z&LyzV@H7g??5<$K{JX+e=M>nNcxv%)df;D)&VnBUv<0_QJ?noeN2^6}{yo*wr%Zm_ zNfw5qgVZuXJ;!?b6TLle_9wcJbR4EcBAY2ViDW88dXR9EnXERX(plGlK_Z=V@{{f~ zQ%DS@lj4*f8FMD7B}Ie9d>-zF;lx-zGn&r;RWp{>X(TeajH9B`@JKS79UZJ%IE!Kq z$Z!?P7jw``bA-(4vf*YA}F z7Ovkbe_Ob|mz%L3ZaN=*|F&DWzEArtT;Hb@EliF$$pQ3E-tC9e MUT>Su7~B5;0_%KfC;$Ke literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/kernel8.elf b/lab8/kernel/build/kernel8.elf new file mode 100644 index 0000000000000000000000000000000000000000..b2617c04a3d2c817c451c704b53a2ae3dd7ecb71 GIT binary patch literal 142504 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 L@glE8`Mmw#=UUnH literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/main_c.d b/lab8/kernel/build/main_c.d new file mode 100644 index 000000000..411b5ed46 --- /dev/null +++ b/lab8/kernel/build/main_c.d @@ -0,0 +1,6 @@ +build/main_c.o: src/main.c include/uart1.h include/shell.h include/dtb.h \ + include/memory.h include/bcm2837/rpi_mmu.h include/list.h \ + include/stddef.h include/exception.h include/bcm2837/rpi_irq.h \ + include/bcm2837/rpi_base.h include/bcm2837/rpi_mmu.h include/irqtask.h \ + include/timer.h include/sched.h include/vfs.h include/stddef.h \ + include/vfs.h diff --git a/lab8/kernel/build/main_c.o b/lab8/kernel/build/main_c.o new file mode 100644 index 0000000000000000000000000000000000000000..340cb53b43b2c43e2259606beaeaee8a39b3395e GIT binary patch literal 2864 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 literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/mmu_c.d b/lab8/kernel/build/mmu_c.d new file mode 100644 index 000000000..fe3d604c1 --- /dev/null +++ b/lab8/kernel/build/mmu_c.d @@ -0,0 +1,5 @@ +build/mmu_c.o: src/mmu.c include/bcm2837/rpi_mmu.h include/mmu.h \ + include/stddef.h include/sched.h include/list.h include/stddef.h \ + include/vfs.h include/exception.h include/bcm2837/rpi_irq.h \ + include/bcm2837/rpi_base.h include/bcm2837/rpi_mmu.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/string.h include/uart1.h diff --git a/lab8/kernel/build/mmu_c.o b/lab8/kernel/build/mmu_c.o new file mode 100644 index 0000000000000000000000000000000000000000..fdc92f6048a8ea8bef1fca6c1ebd88f9068f0e41 GIT binary patch literal 5160 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 literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/sched_s.d b/lab8/kernel/build/sched_s.d new file mode 100644 index 000000000..b49148f3e --- /dev/null +++ b/lab8/kernel/build/sched_s.d @@ -0,0 +1 @@ +build/sched_s.o: src/sched.S diff --git a/lab8/kernel/build/sched_s.o b/lab8/kernel/build/sched_s.o new file mode 100644 index 0000000000000000000000000000000000000000..34a4ec761233f0584ab66f49b9ae7f2264668023 GIT binary patch literal 1008 zcmb<-^>JfjWMqH=MuzPS2p&w7fx&i#Fs>9&U|K1e!Msws zfMum@1?$R}%nTDb4H$kJ2RN)Wjc{CPp5V07GQ)YLb%D!D+X~l}nhb6$?HL&+HeQgp zI^UZ4DuaT=RrzKPF#Ene^VI{)@z)5M4N>C&wBHeEzZ1}YXQ2HqK>J-+avC`N1ep&~ z({RB8Y#zb~*jdb2ea^tZ%z)&1B(2Oq8FT;%JIoMd0V)*0Vm=>KJO<4m8K`&znz$xZ zd0T#RlVxqNA$Mo{Rmp&8%+<*z{#2Zb9lPy}*7 z`q4xF4YDF6HhN5`1LZg<&<`>XTWa_Kwetp)W(Cq946+LZBp?(6Cy+*WJ4osT)S;$O YbubFu{enOVZ2JE~73#n=LTPmU0D2&6%>V!Z literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/sdhost_c.d b/lab8/kernel/build/sdhost_c.d new file mode 100644 index 000000000..6b4157d83 --- /dev/null +++ b/lab8/kernel/build/sdhost_c.d @@ -0,0 +1 @@ +build/sdhost_c.o: src/sdhost.c diff --git a/lab8/kernel/build/sdhost_c.o b/lab8/kernel/build/sdhost_c.o new file mode 100644 index 0000000000000000000000000000000000000000..1910b72c8be3f24fb1fd73d9e857a7123059977b GIT binary patch literal 4256 zcmcIoU1%It6h5=NO=6SUWMioq+nqvDTkJL|5u_D6A=nlzHBM81A9gp{4Owjdb|;uN zQYTQg;1BInL1@W?U<4mT1qqf~r4N1Zp^a8hP-dYZSbS*k!D!R*JNGAhooq^>c*~u8 z?{|LgIp=v&=@iBMIlA`Id=Q57mj9uPeP?|Go7y}j zv816#zQE|<+jEsLJngssN0wwCEcj9rO#4e1dZEgp-oUip>gAYUL(ey2CURzj6rnq_)Vn6h^9s*t%C%{_WD{*=%(P*- zs8#ZVxhzf3zmIy6;d7IYN6Ft}xe-TKT;|}Lxo(k|tns&^#>@}ecft*<=~A#3F|KuH z!HcmRQ7@67ycfJ7qpl*CMyW>$dQR9haxN`NwzF=9Z0An4J9;=>l`IuGn&N(OEb-|NHS_m4Qg`kZV!rizpR6W@j zb8HIdAl{`H*B@m4O{fo{URO{n#w&5!YOnTP+-;}BT{O!a{)}b2{8{?**!SSwf=%>} z)o^^y!u^JOYJL-Zb1uOya5+IO0ql65x@nDV;~GV4x*hWE&~4rz>gZVDhM{An~~bjvpmA@^UAOA2WX$fgY{bkymr_thY zrd;sGM@ed_#cR2umnr7~X8MPC=+Bk%rfi@%FhVfQ^c^1Qf0cy(KykQO9;8wsmse=1 z=oRD?jv)0o9#7T171UCxi7+P=zAl1aR7z3(OA3$bUsiRA>i?kds6M}=+*V;ArHA()}YtLxo{r!y{fHz4ySO zZDlV9mZXJxVK6gL$_*7%*mphH@W7!*-$Vx(w;&=gImhxgbjBQXvz=^|tCI@62P5y( zpw{|(_mILBeU+5RuKlVDA4^J@Jc`afSF(@B8(nw6mg8ziH=Ev{{hLi4^HLl;A=H?u zxBm{~e^%L>?+*LvQTC$|=emA+uctAoRe!rlYS_x2>(4H=y{WU`1~rM+*Si;X%X)XY zdkrSg)=?uBDLi16N~j75RHV{Bg$Jb6DsA1CN>t55+N3QHX|+yx$O8{f!~>Ra-E-!i zvpyMino3Y9;E{G`<~wJ;IcMg~+&i=TosFBGs*A-Gr_lMB@NY^xe?P^!7oIyyeNAUUm-dbL%lwUyT7xT;roRX{!o<;sHO_*a$M z`R9Mn_P6Tz-|z!GV-xYz-)Hvy`X@7SHCDM(P0zlr*3Lev#w(8|$6K$)cU_99e(3se z1@Ox2$+fNRYS$=WD31aEB{cvIta6%dEoyOesxlCbx2>8apAA^DJu9p?)E{p2V0DmnV4|I^D%ORH>oemx5 z==cPA`zOe?LoRJt>d=8Osrp)33Uj^`#)y1hcf$vUw2 zf#fvCgW*RE=L_a*it`N?oy+@ z_p9SUtYHp&8L(L6T)nkPl$%AlMUagZ#81yR zpQXR(|1hk5Pp6ARL$J_S>cB7My>zayL#Ky>z=w?>H{|W`^`2aq1-*j5CjunRO%nbTip|qiv1m-^=Hy6|yT>b^D?T)^*#{GPzii@9|Z(QzDY z@&-HCEncKn&=v~(>-389I=!W+%fsocxn$ABU~bQa8-7R&7cN|{*SUiJ zvM&3u{b$NLkw`3Fgq=RUe*HS#{_NmzAsp7LRwdRXIv!ayY^tliy?S+`W6eVZtER|o z6?>^y)sNg4Th`cWeza*Jya)5HCAxQsQp=&(LAZJO?po4u^!8)7edAyM1ZgBU`cNK$ z3q5F;Jlb$m|Y;gS?5#GFuN76XDL7T8 zt3vZgEr&s>&o2$`?JId{UqLlJR8pB@L?P!XTQR5b0V96gTbD%GauxlA}bo2ew8 z&V_95t8^(>Ou>C;I#u$5 zvY*O=o6rVqOqIeYPs7#8pqJj6!i)5jxj_#DZ?})?(F;`sn!$ln*6x&_&K6VK^WF{> zW^vq7#?MlyhTyQBLcYkT)meW;d0{aZRm*-Mlg|}=Sbs&-jGk zk^FB7{Bwf;g2mrSvUe?h#xDvU$$wekGXCr7xq;)hO!V7GILB2t$(jh~abvti@W_7K z1di`t@(kgRgZ=Pdh-%6b-f7_n1&^+3D|JfX(*CoA^Ehmy zHWP&NI52)r@JKt~wRi@Ir(*Fie$m0xMDG{q@BPGqSu^42uf&%N{Vxc8E%YVcPB_NH z146%ta2yBt4^uVu6OQ8`@fQS-9ESnHgZu3PV#){}iDw-=BZ5cvyI=4~{1pe!0l|a) z9wK`V3Lc3ca`2od+>XOH3Af{LO7Ljv6SGEoPqg>{7Q&IgP3SKt9Qh@_l5pf%A@q}k zb36}_Yy;sO&y05q9yyPp#dCysMl2r2_d9qF6OMj8NF10QAsqdZ_(_NUDTn@PhyEFd z{yB&Kd58Wx4*d%b{fa~XqC@|ZLx0Mlf5oAH)uCTcM@D=68wj_@znO51t1pWA(u8wd zog!Hq;T%_tw+kK_S1Sp(?dc%gwx?6@vBjaI;a629@6K==DRly_UoUdfq9*)C$x<6oh z7;hjP{gU=H63#po@~g?>VZ7PF(?YoI*K)#bzuE+k^sAk4wukLsNx1D-hv1QZZ6X}) zk?)5+grhwY4+W2=F~ICK!r7iHBs)$x+r#)t!6WT?SKto`{wc!I&W8nlnQ*jI;#UOE zmxO*3zN|oEI~BCU)J!tEk~wW4@JQyoc)j7Cu3B{way|`JU>q zrO)?rXDqyd-jm+3aK2}|Y~g%g*GztMzj=E8t+DWfg!fxG-^+y-&i8VMExduoQ6d@0e>3>0StSa^&`&(Q<=IEzkEZFJ zpn%Q%Y-)Sp4f*8mb!QqF&;<&kDqoUHS@wtOG)z@JJS!rWtRhh%ONWVWycmXrzp7wA z4OoHH5@qI{4sn`ZLg5_7{mMfsNVz>Lt|aW5_VRGf%8=7^RgqPM$=F8WDQeI6Fx7%g5T5lqX`yM7hN4;uU>jAag?1BHk%+2_t_jdmRkT#CR3s#OV{dU4|D^U> zH6%a|JydFuYLsij6*%R9L@ea?cDw8j=1@s&^=YR)Qg?+*Fg zy?hMxc{&WQ%a~9tzDj(pF}u+mq8eebi8h2`PZRT#9R=gcAAfg5y((vv>uk?``|+BY zy5FArs=M#jKA=5_eTT%}w|daphxML?di=q=-zUMi5f9s&#)d(;yL~b?l01j{ae&_( z?iV(T`vrC5ko{q^^T9~7^YdRZfEz8WKYq>L`~~%k^Y*5Rd>PCw9^{MJk#!>(Sr4IZ zn&ziX^CPVJwx}K8`2Cap3wQB7-;2h~b$>r!i~Xo|!7aPdGT~W(g}aC^l5czN8=vFE z)YQ?~feX{sqF0S264rz@emGGT)5Lp6j#%Rp2N}jtfMGEL81I~eaP28$bRY^(AQoZ# zA?f7c_)`CJ-~3NM4$_p?C&@thf`;T^Y$?2K7I>XFFA|PIjUu6#ys!YqNhb$~mqN?N zDURW#ZHm76F#Orswt#@y^A|xlcD;v~$fV1o0_gS2BA$NT9d-+3M|WSUg9$s-Y1cNP zuWL(#dNiWcFZztwbNI-2B7I3e8Gs)Qz^TW*cwRu9^2&VT{UP=$<9E0f6i<@Ihx|Wd zT)xk%i1*@$%H_9;PTtDE{u=DhLMG>CW>P)~nQFP5@^WR@$wIZ5FJ)$+;+4v7DpM+Y zZq0*owJ3f4kW|*aF^;}bU z)c#x#;JF#Vv!d{*{gK}j^=*iKNd2Jrt9dsV*XwUGuGjy&!lUNhiTOx$o&m;np1lG7 zkpO>+@5O&C!2cxUkD->|9>t$#{BaGx$T;;)^-nWSJbOe1{*YyycvSp4<9Z)%GOqXG zy8!=t0sg--PIZnb_0aiF(ua7+H^q32ZHdcs=S>Zl=gX{y-{E{5lvQz{hPq6b#7nt^I*wHje)l)5w7|Wr>%;rs@009G3BLdc%g2qs8X95CvDP(hZuNZRlD2oyFX?a zmKIfTrP+J$chCPl=gjQ**Y`aeaU8M3kzdKJokc}ntG%^$)zXzmq(ZJ&t-I+}Nx?6d z!u4q6ZLi8LcnwnE+#s@;6Y22E^*V*MNUrU;BelgXQs~0$D|)vO7kRH?F1pySX==K0 zMm`a@wc)H}8aHV<5|e2Ux`Jo9Cg~_1lKi6rd57G*7j>SL>=W%GPPvRWw0k(S^fD*U zlLq?ASMadRcO)}w>{j|elFW08`9q9EL z_bqOr@$*uHJ8M-w8haiJ#_u&J<5xadn~Lp-F>Jw|Xa339VC_ZaJ!Nk@Y>!E`2O8Qt zxBnNXb<1Efv zCS8?Vh+w^ddT&HORJD$C)r*i@GsugF!P5|r{*m$KOrDhqMd(Q9{c6&auoKUxBK-{Soo?GKHM&ak9JDoZ@Z=N_q|g1 z_yBC3h)jE5H1n4*Uvj2Z9j(gMcs-IYz9{*HoihF524}h}=FYk?neB=tF*~y!@P(+n z?bmDlh{suP5Itbf%`cDr?k(C;oRBNt8YvVJ3+5?pR{mh`tua31+{VT!YQMlYt@tm2 zAGCa5A)a~idv!)uososT$2H$Qh)ohQDya*xbAa(o-9eB(7}qM(543z$|Lk$Wc+c>C z0)EDuHWV*u`bKLRQ@3jKH{R+&XiAGj1Bmf$9{8LTtIh69K3Pph?>~ooPK#@ zz{a(IxhQNK)9X0b3U@O9pv_$OI+;nc7OCH=(sEPzQUh-P4vFVsH1#1`~VS z!L8h2j=d|b#S74dylSYB#pkLJ53FTr$Gox&@wYXmYyiE=5!4s+OJU@HSI71o?ZVo- zpkor;(~e$~&-YU%K7v$@+)tTbdjK*wQ6}ybwR}az7HibTqJIN*!kEY0)2#c?JpkS8 zomz+PE$Y6Z`y$>q_P+jGp0Ey8zM?K^yXxPtKh8dD@>lh5tL%dQBJ|QnA2zY)z?Uh%4&O!gyD`wmfUEw2 zI{9=WWK(gcT=CJ<*aH{vjg9vNzDpviw%1TTdK7)8kKoT-1iwh`_u$jLcj8ujSsUm=er%#x}|0fXtC&PR${!j3~1>TQ&uU_^4Y7e@@bo6$SZHeZmT282K%gbB0CYrZxGBCMB z@SjHw=X-4u8-2p5uV@h1tsWkHf?!Fqvg=Gmbkv!z#HX6bHXdM1@+Vn&&UvHu&9z;B z{R`f4_*jGU#4%j{BrD_l`SQcEk9&-B{7F_e9|cZ%uX2y^G=D(s@M$a<_cQyW~^|Qm^$O9$su%YiW_<4hW2l(9vNn^5DEOj2mpN3K+D$!Cf(AZsY zUheG!b&hc-j{lq(chigN4Gk@)OvOEP1bfQDklIIO^&L3#vnHTdAM-v|62aO9V2Z3!d_~CLaFjQ_}{xTlYPa66;>^YKni0?73 zshkA1$KaO@u5uFCL4)7WffALIzz!Mwl+oLTJ;%54Q2teey96=Pc!+PVP+RHMlVlBk z*5E4Vcs7z9J~r@TqDM9!k&UDB-H{>evqy>dr3W|-^rW(!?KE^!??%!+{X=T0rvYyJ z)BQalz%-K9T)o4j>1O7)~Al^r~0%#uAOwbmk)f?2lDY#s~Y-!k`A58Sw- zL>)2lCmt-L(E!dIv7^t#Eli&a;E!2i%4TW%P^pJe}8%aX9I)TbYl1Z7oHl) zrh1NpfNbgB&ZEPrewM*~8F5IV3*k=W0^``F8=>CdH{4nA|6gJ53WZ)Y*XY^aFUy{K z$~3(4zWsv1!=3!qkY2;4WY{(5&3GvD|K)E1FYOBEJhn1v^qcY`q=vQM?pv`Sf3pS5 z`~$;J`+|eC9CqFjSgQl`bKxHSXa6i^|D55^Sw%)}*#0))yi?bl+v$CCe+Lae?~lBe z|8YZDN;i*Oe4KI&nZUB`u%Ctb@$G-d-2syGrkS1OCNM(osP|&{?n&NMtC>;(UM|D@ F{{fZ}gy8@H literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/syscall_c.d b/lab8/kernel/build/syscall_c.d new file mode 100644 index 000000000..6a717eb1b --- /dev/null +++ b/lab8/kernel/build/syscall_c.d @@ -0,0 +1,7 @@ +build/syscall_c.o: src/syscall.c include/syscall.h include/exception.h \ + include/bcm2837/rpi_irq.h include/bcm2837/rpi_base.h \ + include/bcm2837/rpi_mmu.h include/stddef.h include/cpio.h \ + include/sched.h include/list.h include/stddef.h include/vfs.h \ + include/uart1.h include/exception.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/mbox.h include/signal.h include/mmu.h \ + include/sched.h include/string.h include/dev_framebuffer.h diff --git a/lab8/kernel/build/syscall_c.o b/lab8/kernel/build/syscall_c.o new file mode 100644 index 0000000000000000000000000000000000000000..d9042b42651a36ce84a87a5667884ce6f9d017d4 GIT binary patch literal 15368 zcmd5?eTLa8csq}zGl-#qhsK4#{bdEfWGv9)&x=KveM#3LLX82+__K}t?goTt1!v18V5T68#-u}E; zBIet2P%|WiKPmr){JeMAf0Oi(4!ceFof`Ou(^FwF{Mj7XQ42kb#pLxxVzT(0$QO5t z{6j)440h)7g~k5lIw4*M&j{&m4T-0Noqk?aiAMs+Nts2;zQNxXqlM>k`Jk5l!}Vu# z{K=_-AD<$>rUouZodNU|7C_%T=zA9W8b$tdq^}YB7Wk79sn36!bOw#A3o^2Op3-%S zbUh1Q&@E$$>#2cDtmjNc-^yY^{+MwKYKGq`7T*dI-Z1%0y3KYk^2ji?5nkBrm9B#) zAv+s3Ec7SoIwBfB!nmC&>pLj&<@fN3buYlU1!32FrImove(9;I~aPDue zgj&b0c&IDs@gS>hqdq6uwvadi{=X{YFDzGMc0KHo?J{l?E9E$s`D*$u5RU-yKupdA z;jr{IP<=*F@I*7Bi%0KN_iPNoBO{l%o!5+37 zcG7jNFM8kkuVPf|kn3s5CahmExt8(})-mNMnOm^71I(oWbCq)NSe1xsTwq=jhL}i9 z)W|Uy36R@JW+wGT9RjZMnp#Jc9|#x78FEeGeggBdfb|q09Zm5&YAu)gfJ@Ft zjSjJ+1vhdpH}<`d}(@x70Gtdpm)Udr~C0`{4p_?Np7fL8Ch;3m}4*A(TBkq3Vsz7|bn*&!dEu{7b`y=N`ul7~PaB3j0&S@_oN3Rsf={OVOEIP44!5xZ;}qQd6ef# zrUvVsb6X?!g>RFszys)bnE7Zv5I^EEtyAY{=<}vjj*i^J*F%A0%Dc2Dv`yY>hU; zi;W)b4<#FA4r#=>s=`^~Rm4T}RFd-|$o1f*Gatq+PyDogzKd}yfK%?V6r0ATyc{3Y z*vlUYU;|;b4Wjp_zbQubyjAi!%qJSZ-2AD54_rA`j;*u_IjWNF7j4@s$dSEe{#i1$ zbS9fOo%3lQpnIHe4I6cy|HtX^SSj+9=O^&&SH{1xvaP;tYX!OMb1?Uyn{1ZPpE%#h zxk2X~%(Izfo5YlDbWQlwzGsECQ{?UG6J*qWdCGz)S)fKSW6)*w6 zc+HjUc~99hHNbNiaVTQ%`aI_`dDd8+D?6*uGop_iPX3U+t(220$Y2cRGbEjFXe>&( z2zg)TD(Jx;gIwkHzC(M4W!v=nnm%J`-$}QK%#&kWTXrT??}lhRO<9U1`9y2?#`nbV z!~}BdRm>kf2Y14joodWqrTEi+N&6A!1&o^;)~>BzU%%$5wSDq-?JHmUQvI6sf5i>ebxVlzunmD(}Qb)f{b8B|+ONuoL7ONQF&iHo58yNp8@CdG3=^iCZKTUI6Mjtxy zxlM1*{@Txfb`=r=uL6ZQLKi6Q^wTugADw+-*6yGGOtwb=og^IPV+Jg z+E;P=yClT@4|4lLK-;-}w`#A6!g}JxdX(js!lm9r+;0W29JgPix@m6D=-d+zZ+f$O zWKJjp=RPRK=u|n+#n9-g6DyfW`p@k$R&3t^!~UDxKBnwgGdlCcjQvLYY>F+)82vQO zy{~;0x9?T$=R%`jJn{I8ih%TQ=k}CpSN36)$pLC_=XQ?ISZH*`iRDq%PVpP$cAh7Z zJ?KdI7~`~{$*z4I*Yk`YXPo>=8ve++f;OJNGVVK!_PgAl<0a>%j#mWz9t#sO&pn>E zx?QzY{-rQiiBF4_TEl_|!Dszw{f}A26=(SIPeBCoFK% zvkKn7q1=xX8WyvtDl1BUwj8Un2Hb?jY#WmIVS!VeRi48AeApjlyn*ZWsCABFNLD_6 zNnXwiT+4ZbdI$b0$$yRIt2lJ+xTli9UnThraNwCH|K2g(|TKxeuZ3GyG8;ZdWToEkA?hui-(L%1Kp;cNx!7B0?FH zze1b?UMc?f&`$i3c}h^r|A=`mGQO92e(2!2%<@ZENs8q!IpqJ9I)qfI3G(&<>XJxyp|Je@6F#NwGlU5OaP z60+f?bVoKRuehbB4=r@m7M-1av9@F?_Vv!V$Yj%roAMEQ92RmV8x9Yb)og{$+$yheNFO|%Q&SYmMnU$RJwl>AtaiA-ninYhP+EU4M z?4@+Prze?~jNLuSE_osCCLM`XcP1$^s!LmPf4nc1)m_E@?({*Syp1K$1s*}4Hke|O z?8?H2?sPJi=r0hvNGA^< z^stw0I@kgE&dzv`v|ELh4DURMCliTvcH?nGB--gdl}RQK{?U5T(VfVqM0>L1Kzmkn zWYP!riJp#ZqFuby(T3c_NHMYUFl@DFWn_l-SM`PFElLl92CoBG1g*p%Z{C~ zEnBxWz1SR$y%25M6%~n|j_z1j@}&d@C7nsi=|Z++SUY>v@MGXJa)1?6$ID4xCp!OZ zz`Em!+8Mpl%amXKY$lqk# z)?3G~1PC|Rb=1HgH{z3G+_tlaaof&Q29L>q*5EPM%Q=I`#6NcMTr+sgbrBdmCVtl; zf6pPmg#e4P3o@QjKQ~++4qx87IB^*@t?JGfsL<{C$JRoNpgEcs_RU+%S0P-Igx59Xxj& zJogM9)1GR6zPIC3XW(WWni;1!tk%Y$Zeg6_VB$v%o>hkYQ3ubEgXf}y=aPZ1G5GHo z{AKIK;5YFWexG6c6=mG^Ymjk@n;D;@4xS+g&t-@FxI

`xSeZri`Y;4z;U z);M_9J9u_GdvrWXO*g@+N-Lkl$p;pEBf4 z{JbH**^s|r$eZ|GLw>6vf6tIN@s0eRmHajF2F58qCccGnns3_-{-XvDPgU7EWbl~y zaf4^O!E@f=`C|jWVDOlDVDLO=$m^F@WM{L1ui%$i3xM;{Mz*eE{80<9W1M)tYVho3 zoZ@EM)5nBx|%zsKFOaQ*$O8g^6Bdi8g%It$m|t(q-de}|&) zY9^2V4yE5`YJUA4>Z~QNze9~%xc&}x%fj_{sA>+n=8y0qsI%~kj5k|&>ARAJ>+eTL zEnI&;I%(nh`_Tmp*WY*a`zvjy{$6v>lGop5^!q3+ufLm!`pltDe0D&cO{=9HWP5CXI^LO7 zqxir7jevrNj30MPgg#&0;q{~&_%(*U74(jhFu#PTi*rj=?JrdIL#RlP&NceoGCe~R z9>$+p)^k4-qid2i3$0h;{9XI6MPK6N;l-6I8(IGo8sJ*nui>Y0LH*Zgfa`tSU*{9u ztnJtJCN$`4EkpHRKcN4A%KdHohq(VnD=@bGyU@SV_}%_8Ss_FZ6Vv!nU)^7iAK7l} z1|%-?A*P+*L(pRs9aZiA^f+mm2n6xuL*>gBxg9Io&MWnA-6&~9TverCyZ?U!0YVj8 literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/timer_c.d b/lab8/kernel/build/timer_c.d new file mode 100644 index 000000000..98fe6b054 --- /dev/null +++ b/lab8/kernel/build/timer_c.d @@ -0,0 +1,5 @@ +build/timer_c.o: src/timer.c include/timer.h include/list.h \ + include/stddef.h include/uart1.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/string.h include/stddef.h \ + include/exception.h include/bcm2837/rpi_irq.h include/bcm2837/rpi_base.h \ + include/bcm2837/rpi_mmu.h diff --git a/lab8/kernel/build/timer_c.o b/lab8/kernel/build/timer_c.o new file mode 100644 index 0000000000000000000000000000000000000000..8bbff971622b5e3de0d2ea565952c9d04b0583e7 GIT binary patch literal 5624 zcmbtYPi$0W5TD&Gw%DeWQY}!VTWqi1l%z(?>$dx_n{Kyt_tmsO zlmrj>=OCtuBm#2apoBxCB%}#ZFdRJefP^9kG;b>h5;$Pwz$Vsp=6f^SuOIu+#4p*- z_kJ_;n|br*`;&gKz4Mh|AOJD~Z~^9@1O<3lJwK1CX%s4;9P(S?XSWn`ZfP`^#UJ|4 z&r2Xz9}dl+&9O@%>qh<0!LagS?9Ch{rW|@cVD( zLU2s@T(kp-=4L~1mVAltc0T_F`OF>s@oS1-)Tab}C5b!)#`39F#GP(Q8KiVtmz*+~wN-8e(_ z;rQPc=Go;l5InpaKjQ@Dgz_`|9iw-VIq`pFJ`Fu-*e1)8jzFy$flHdxF(99VtBq2a|bVTFJ1KduNHFIW!TSH=ih5# z3Kn^Fb?c<=7_$VHlE3=?b=Wgis6$CLpx!2(TN|CC_se1~?lKQ6*q1@BOyzV~y_>?( zrUBp+;t8OhWVROP6(G5)Zz}n_^^n6PYTSCVk9zS@QvWQ*n$Ds>=>Ypx@nfGphxMso zAL1bny)McQeRgpj!*lrs-$wN9tjCQ-#d(ASW350N9oN4r)yMmuS5)oQK7#v49%~+U zUsOGw$2|pTj#90ETpJCC;7jVIFxCluygf);LjklWn*jDS@fTZXQ9~y^ov+7lZS)Am zrryCiPSH2VdQHi`L^|DG)du&S0N1AX?|e7;$zB!30s!Rmuw(1iP2r}!eWNL7G~Ch> zX^k|mZy8mOE$?sG5NU3Go?)a1s8W9c0ta?O$=K>ZT}8cW=H-m9BiUA2)lsP$3Yr=3 z^ziT-h_AwVJL9d4pDZ~QdiA$oQS0dk9;2tlbCmUpALH$0-qZi$cZu~)B+;*(^SoIE zr#$a7-b1pjGE8}PbDmU-D%{j)kSz_u8X2QJX^?IsV=8av>DAu1hxOFpl-J4NslXmh zKgRk)B-<*ZC(BNi2H*A!D9&-#Z}$Adukm|LGT!LnRXZ5}iE))T#@mi~7;Rj}RsA{7 z9?pX({06y|z#sWy`VcP6Vj~2&qZSzg###3Qh0 zAAp`k3soLos@CE{4PcdV*C;YVV343q0)I=je9GAG0Lp5t!vyEA)&pW6xjKmgcvQJN9&2?c3Y7fn_BV8OMsn;~*2ui6xSvh}%g|ffLJ4Iq7llF_Ezb>=--QLnF>O zG{(I+mi-+U~njwOb+)$|8Uy2R8~kD>r2`?5>I3l#CpZnkA8iz{y`Yr zpSEqt*p8)fBvOu@PLGZ_R^K?%qM4t89%mqyiYM(fjHWQ9LBJY#DM7|bC+!r8{*iHb z2V)VZHIf|7SQ-7DNR>$(u&Ks4E@J&@)S-OZo2tK87+;1`dX^Njk3MDKSAFcSGj7`N z;(nsIE48>iKKMSy&3t+pH~AeO`!OH;ql{BNw3o`5&~RCEq&uhKtHl`QB;#hD=NUKi zoYr`B{;L{}_t?U?>BE1^hyRYov!cKPa8JW^{u(}_%zg-Kc!S2%q~Uu1Y}4>HnthLk zKda#*KKO)&>vcZPxLM~DjGJ}7?_>YK$G(d9Ba^>|ag)E*$9|)aeW#E8E+6||#?AhW zYqxZFoRHE@@o z<GeN3IyS+(&L1xZFn`7`UACHTXU>Bp*4?n+#me^UVe>=lMPZmvdOoPvMty^@L$B z=j3?a7&9n!s;;)wrpwp+_MZwHJ5oHpW$g3BzAunuR$>E|!;#KC-SK?QNj zeOv4#KJn{A;)~pbN}20+)BiF5*V$iR%fxe4{0)Vf|4y_mR{uME*_`C$sQz?27k{Zg zsf`ebV0^yHk8xq2M2zkura$qTwMPir%jqvbpHUp+QT;=ynE&x=&;LzN6#kn2{{Ret BV6XrH literal 0 HcmV?d00001 diff --git a/lab8/kernel/build/tmpfs_c.d b/lab8/kernel/build/tmpfs_c.d new file mode 100644 index 000000000..579016ea3 --- /dev/null +++ b/lab8/kernel/build/tmpfs_c.d @@ -0,0 +1,4 @@ +build/tmpfs_c.o: src/tmpfs.c include/tmpfs.h include/stddef.h \ + include/vfs.h include/vfs.h include/string.h include/memory.h \ + include/bcm2837/rpi_mmu.h include/list.h include/stddef.h \ + include/uart1.h diff --git a/lab8/kernel/build/tmpfs_c.o b/lab8/kernel/build/tmpfs_c.o new file mode 100644 index 0000000000000000000000000000000000000000..6e7a4deb55d127a4244e8a78b3caa285a61638cc GIT binary patch literal 6512 zcmcIoU2I%O6+Y{AYBzBl=MP6X)HjVojhe2UDk@eL!CGmY6ghTe5&=@tdSl-tmUq4G z?m9Si01GOFR304ggCFXss(65^4}Cxa(}DsN)QTdN@}oWg+O2pa4~f)=TB!pwM4V5C1hb# zWZ@myTB;`HCGrp#Y%h$i&;MHWBi~NHQ&wdgb!4eRU!6{V@epE4w8qA;PkuM;?N=Sd z+O&V+9r~^8O*4ljw$;w`D*UdBe9PH(u>emDMK-GJw?+NUyk3j)LL61teGmE3p9r3| z^jf7G<8InOpLlb6Ef9I`J>*V%Q4Zh(uK+_1&$)aUH}%eK>V011UoVQBkNChHA9B!J zpMPEF=_AC$`SSh2j=&G?zu5%)F~5lS_nh~Jd2r1v7f+XK%h+~{?E6T%@wnXh-uyOB z${#B&nCm3)BazaZ{C>+`?W`uTa|xF3e^huxgJxwr*?m^XJ8==|+D3!57mA%9;LvX#u% z+?dl?67$%A@A7;Iz8=y%V>!ls_A$qd<_O>HGsm4?j)wiAPRs%I&BqD3`(_=PPRJbc z&MB^8z4*DFt}f8}``@jX`fzJRx!M``JDvOgUNaTil&B7G)rs+O#K^j8L))mXIQNo3 zoz$s`{J%GA!s_JX%vZvnFPww*Vsf>rXWf?i_UFs1X{%MYM{yQZu>YMd&nW8PEVF%R z=LPq+?S0hG|CP%5nM);jaBVPN4724hm@brqiOFK7yc1h8qI>w4CUapB&P|reC6jpK z$66q46c28I|U_2NGRv-Et7v0mVQedm4TZpu3d|WcFSh`eJXGS?H;a%Vz6o}DnjA`e(;>+5yVC%`Z zV1Dc2?G5n#4e+i8_=62_&PP4JpKX9g2YhN=dM2c2E*fQcj%NxpVKG~tEKHXa{aSId z9BLo;!Gv}pH?7_AT%lwVxl$NTJ$76@*gt&j)<>cO(Qdpjy$>a;T7gV@(ZF+oDmbsL!K`noe;f#wxrt;Zbt}rh7Fb_j) z#%Hd{)TLq=N~v5N&(FwgwpfOj>51Irv;%Xd=d3=g8Ndk1peIPDzv>|FP7-~M-F_Ip+5dolZlFM4)- z`)|bToKZV(#q1dVb^|*V5AX5fzpc2at#PMH8jqF?^zNdz6?kVDXJ-k=@#O&~e*qi?k2e2T{l}ooxEkq?f#;LOZy3M#>*e38oAzB5Wd1zzOyBY! z1V;bIz%9!DDu52uSA=LqCWifdoz=gr(oaFYN6ops!e|a$QRyF9#WG^vk>#4@A%7g$ zo+h*>mtEGF3paJ-vh`RubX+)&wlr4cX`K^|`JOO9b1d$B?K@33Hbvk;=%X%5aWXy4vfzWFhXxs&hlZ-L@fxR!s5Tbzlx#dyo~HJDV5{!LKy zZ$ckhU~GhJs@3lUu%1C42Uu!k;96)@{-F+NfCot@=_CK|oh$d!`t;0A9#y`~O}=4l zD9wBbrBg?t^wTF$n*9t)KYszGUrs>j*KeWZAFVC;uW`MP>Y9T8HrBQIM*rbZv78JQ zeJ51#526nA?u2Z-U-??e~4%`?Y?pw1UH_tm`&!W#p2fiy>N9Cx= zIkOLF?#1nn=`%*;Kafp2H|F;Q**}dr@o(%uh5O;U;rJS3E5#ueVE^K=)i&x})cflH zmWzw~ufGF}%kX==`X8L3!wqFQyzGA;X-##-JpH6xIa2S<|dD*vk&70aLL1T| zBhl7*17niLPlPU^Cwd?SoSZ3*m$9IVF)5Nh<(@$}TssI9b zN=nBj&a9hR9P3VIJ~3YBj_1Q@3PlJYj?ZS6Q8r-=_JsF_#@H5;2`V%#0>785jXPCu zq5uy5t5zJ;WS7en2;vL%M3p={V<~f>)*=8}{}Q#i?Lh~Y*huvqs9C_TM6yiU&nDm= z)13RplMdz)i{H(>&bYw!Cd2V^N5$yD`<2okwfIwtSK?#j@p6e5E~A|H3$mA)tNnv* zwO6oygZV5^QF{d0yUbg8-CfwHLI)w~Kfqk&F0xPXp`5h~jgx$yO;vjZ*(rRg$@>BP zSLCE;GdntqeJX$9Lwp^-GGh<@$wWNLDPi`|)y(tEyOkDz1oLCeedb-v4{)lOJq_cj ztk<3xfR;gMnNYo?H<9cg9~w$$t!{G1$e=Bf%+9myh12G{Vp@fXY3YH-lIelrZONh0 z)E2$uNM^*-tt^h}RxX_x)UA%;G@C(ebR?68$8y`VBN=Z<3#4+7X9kj6(%t}!XGXUT zJSy?_al+_z5?eXl!l~(Oc6_^+OlMO4qiLHCj^rvhn;glGC5KbEv6MCfn^Foj0b-cf9JEP2PJDY_(osp(27xI#? z7V>i4Rv|C>x&V1MKz<{0io*(H4A#4ao+|{O5_%+mMaZjhnb36WrgdVB? zu+SsK2QI)H!A=QHJ}%zvLb*(3QGAusdlPa!XPE1&bW{x;^e{&fNJZh-to<`kc1<1E(Q zLXX@py+V)VeL`OPJ1FEO_X6Z60^|<~d70;jg}me+3wfCjp9*=&p-wwbah7@_%qh;2 zHw4Hx2gqM57J(AxUAips{-sF4@uFIbw6__=g8-|;E z+h&WKd)s!4n|s@o#m&9#fW^)I?3l&Ped~%Rh`IAbH_mWUne&VO zj-hpoI&+3z&zwK!dNTeVW?fKI@zd9u2z2wvjDve&ZT>Z&_qwfVsRKj;Hn-mcdHL2{i_ZnNQy=Hfv znwr*5lLsVtu!R-*A-0H;2b-o6QX_?pXk|iFwJHzfS9u`luHhkSY2}ot!Yc0eJ9E$M z9uIrdNEx)Ax!;`m=FB-~&dj|GJ<;-HFc46t1k^jK{A5t2n(r^SDXjLn%i{Av zJkywv&zLrh0pGlq4SxgKFv~{1foue_)$x1;dQ+{!YL$z1P`mo^z@gvG7xyVOT!l4` z&V*V&m1~WC-CD05@zx3*Xsr!F1s)%}uxtUg*cgpZ2cv3wW3&Nv0Cgkk;Plt&_>ccA z)^TC*57P@FHR|38pVX=R-BQmwf1ecY)b<*KzK0qDYG0v(EaGBh1N=n()HbVQn_(Uo zZEdrgTAvRW2G38C%@ziKtM$3QoNTS;3p-SPb}ibWC8LFqI)$~7|Mk2x5yZp}aH_kj zNRK$4i%$pg#is)KDEa8Am+}S3!}b(Mk5->mhY|{7o@&UukfU1r5c1a{Yq*Dk>hGKW zTil0uL|l6Fxle-&&%3%}I}6Z-`bv6$ll+CB#wZ5rX#O`a7BLvY?<(5Ff%!Bi>~f6O zG>e$m>k5TWwW(d7s_^h$;?>yN_&jVluXzv~LHwv)03L^|i<{48Qh>xeNS=sAlq zh1D1fy=kpwpMT9b*v@ZUF?8Dp3xld0FFH;lqt!PbnRYiJUhW-OaQaF!&2U*h1>?3zQY)mmjzD9c%vLvTt1M67A`x9eIvF75yt6QP zc9BiU7cT5h^U$86IHx>wu0q_dqqxO^b zo~3xDSn+gypX24-Tl6fpA~%rTuut@!JsLPf`Ou3a#?A%~y^frtv1l2?vE*SZ8M_$J z`#pwvUBm0y`pXTF#oBn!(msREuo3My($iUFXR;moA3%;o3>BYOdCj?B<+qc)_7C3@ zGaKl*Mt=n)_6LFI)<~H-Yt;n0m zb>t7zr+tZhg>!FBbu9D=>9<_ywSjUCbO}P2S@dm0E;RaVBz^XCUdDQ^V=aqf8fV(K zT}Kt^!g@E5kL)$^v%QW2aOo2-cK)~rh|W(G_Y?=^9JM$P255hB4lL(CPsSUo_gdcU4cZ4L-n!3+qB{(@V&;rIqYlANUSH(az5w;@YRtPkg83E1 zy#w6m!=tgTww-h*J4d;UF`XZGKo+{Vs4>@1X&kj_y${j7jLzVQcLv|%qw7nQXMA*h zo#rDBKF4*gLV?o6yV(c|24JN3WVnQiSkNEl0YcK0S@eTiHb$#8$Vzc;t2 zzq32#WDjR^PLIdpCkI{@sO#?S&SerkomrYyDeFfu~X_-H*C1nM@iy*VCt`q<+Hd4jec@efP5-WxeVSIJwqr zcTZo+aR!`@+H4oeH8k#SdZM9Gm!@)|u8IZs@;$qEe?PYQ*>)JMKUQB~yS;Yn!}b08 zvHsWFw$*Ok{vg9(SjjAbU+z`mf%^jMqt*JQ755}vuF>Cy6|ut<*l2Fms8Vk-egHUP zR5deBNe}W{CzehwX}|nAdX-6Q(Pxu12_{lO+rfcVdF{~D?rR*VEDswP(jcWZ$dpwGBJ?CB`hdPJ`k zA{7e_3#%`Sl{#@ISAtat|0Ut$FRgb z`G^ha=a5=@3w{O2DzPpz67LEcH_yYY0__=+KWbEBQ;`p=#ClC^(*7dcJnMZ1><5hN z{e!mNXQ+RS-%9-KvJU|9#K`|BX57!wCOpbZ(=iOJ3%^P{X&;=DV@+y9WUt(PEU0^2}U&End@M*?d7}xs)*zfVHq|duP_&MfDatKY~naW@BBYm3L zk$oCf>J!G#FkZv>WyUWtZuI#Z@Jjmp%Lfl&YgLk`{ap#)EYX|xWV45RJM^ufHG`V~R+UY*(j}q10`Dj< zEwX%rC_&!kfjY<@t@_$fdXkq0QX=PMbBfOVM0+-!>d!f?bnDS8PUK2HUkyL#LsWam zJA99#Z1AO4d*{5OUCo!r(H^rk}m65q@?=_BziKJsr0 zd1;?1AusU@jIT$%+EYRQz2?I+=fl&)`ILC>5^ti|8O{4*B6 z!QU4=lK(S-OFs_t`Azne_CL-z*^TZbri?I7c9Zy9KJur1l`vv}$z@?ry8Mp1G_`J037Ga#^WuA!& zd5On;wkzPvGAZc+TP<=e_}p-{40q zd85y;C2#Oo7$<#VV&0<`&lL9^w|ERbB6#Gw#svO=;2*d6PjlaE7QewyTJmPzH!XRC zPcd$<>n)4t49|Po;xYK!f=90FjKDXGb-i!#&v4(LEq;Sv5Ih?M&qaYhDDX>+Q~Xn0 zUF1HOag(17epT>D{+kxh7iJFcg;3uUh~MC0#_hO`FmCjjW1gtRWAK$eJZmf-T$y!Q zXYm;P9!uWv$1Hh+*D!9!!)A*o&hu`ucnscU$wyc|Wyu@7k8zq;=HX!zQ$j{5M7 z3w%A>o~kK<(>t#zZ!>QEW!{_4FmB?<;AaKTIzxi`g2fYKJ6yDQ4F0j;k#@K$aH;2< z#c%Za%HlWp4Z$Pz+{y1(WPf@8d7N=$hd$On&bYCI!J7q-yvIK0!}Edez~#O1#=A40?s!b+x302#k&8pf=+I#3o_w+b; zZLY=le5ZELPo8}^n@e;Yga8e5x?1%ME}QLJS1~Zq68IWg;)`=DDlb34__d=XM>&YF zcnR?uM>!bhI1XvM(mWBCGkccqK7{k@689?AV$Ewh*xcq(f5RqDd;Bvz-sDj;z|3!+ z>(L-ixfiI Date: Thu, 27 Jun 2024 01:01:05 +0800 Subject: [PATCH 08/19] Add files via upload --- lab8/kernel/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 32761 bytes lab8/kernel/initramfs.cpio | Bin 0 -> 1057792 bytes lab8/kernel/kernel8.img | Bin 0 -> 61160 bytes lab8/kernel/makefile | 56 +++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 lab8/kernel/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab8/kernel/initramfs.cpio create mode 100644 lab8/kernel/kernel8.img create mode 100644 lab8/kernel/makefile diff --git a/lab8/kernel/bcm2710-rpi-3-b-plus.dtb b/lab8/kernel/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..38395a23fc90767680815c7f43bbfb3a290c2af0 GIT binary patch literal 32761 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�D&OoC_~4g9tivONVZxf$G+%wkS(-3$L@6`g_7TDCjX zZ0wGe1kn#$y$N03GHt`At5nL~a;sv6?tVfLDtBzZfvLbSPPlEX)KP=ol3y$FuZ?K# zXq{r6RCi!U&_G1m5U=65R9h>Z>G;rAvqX;HRd$z~6%TKR)pAgjR>?KEc2EoOFI}HT z(Zk+nZg2C&R%k#PL<|DCfDac}0}-x51h)~K?qcnF74kM)Fxcu&T_b z;N~L)VOxvMMmg|KwHr9ZRqhdz%wl+uLlI??rK2!lgi~v-g%I6`f&Mc>*Fc1>5Jg9` z^17#s*d9?dyRD%lOrK+iLQh^iVS_5lE(U?YdK6{9i&rZx;GjZX*QY@bZ2zJ#%`RG- zkJK}Q(H=>QUv1*wgAN>)c8|B*&27)R8E*hT~6VH+RLhvRq~;)h{3J~sayp*djcq?x^z z*=bP$8ODfDCznO<1T0!-efE&~Xu4M?b4?Ws7QJ>Z)|qMrada*+YQ<9qvbpLa3nJ%q zqJM5wVdWq~YHPXb@qjovoJ|L>VpsV3h4W*g84}b?cxp=Ca`=_C$B&co(w^hZu*X+ysto}0S)*bX?FdxfaP>9TytA4wwD77_a_A9Hp#OVEWA!Fl_#JplwLCf-}ERJi*| MwhYsc7a#HeA5G>kdjJ3c literal 0 HcmV?d00001 diff --git a/lab8/kernel/initramfs.cpio b/lab8/kernel/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..08fa914524bd41a9ecc4d0eb44983850986ebc91 GIT binary patch literal 1057792 zcmeFa3#=sBc^=kxhmZBFEs76Bf~a_JRli?V{qC;ruCA(nzpLNR>Z%&<%yP%%zGh~% z6i9_5Qi%l!hIJDq0!2g`g+?OLj>W(Ug0W>~83l%v*a;t!jUaGxXGuB=Bm<_X2%ea$ z$@ib?zSA>1qNu&SBN1TD^zG`ZQ|J7z^ZLK@pNeH;*;qUlOJtJSGQMN6RJ>lL?^v>y zd*GWArLwVFJe_6N@BeYq#bW9EmmWAv?0yL@ly<+oBwf$N%PDsM&E>^2sZ1?Z-DRKH zmAkv}rX+|ba7p*> zDbnc$*9qOjwG+C>%6^aQ?wzObx$wm2-|upL;PgG}-6!7RI(Z$}-|teT)2Ft-k>&&V z{mCaj@R3_C*W}KH_lHg|d?0k}a&<1^xlcafdifHryIeO%@1lGz9DV-i9j-4w?Q(td z(i`{K^)s42?fUZRyIpthf$w`CblrY0(%%8UcqZh!@z=*L*U?k1k3Btp{emlW`oWvG z@4Q>Ri*kO(h4NLG>nYc3t|7_n^n>bc*E?MAJw+Z5r$f0fQ@JF^d!KeOe&6``KmOG> zAcIrzMtmZTbWe2M#`gzKe@&I1e(l1`8hH5N?)SHkUjE{dYjP^Ga)zf!OXrmL@8i15 z<@$o_R6P0Pces9TKh2Z$ya>8c2GM;7c^{!HDx-Ek?RzP|chc`)bM8GIaJ~G+e|K-9 z9^D)jSi1Xp5Ur%UH$MKGj$XGiymJA(Kt7NIlj-S&?fL!dCnW3b^%K|tOMgVVrL_1~ zT&|DY0pFw#mKUxOkLnYy$zLO0kpIK!KjrB9eWVBC_ZWJo^LJAEZN8Mp9q_ZS1L(rh zJ#_F6N(&i*c1I^v4$kj@UZRVhKY~qDn)^EZhfIe@D38hC6+3zDosgjd+7(AP|1+Zv zy0K#?(D%=|koG@98rMzG7)D*Q@eSF#T%Q`9CSA7~?O8nkIoLhw67v2E<@G0&Z&*`x(;PPAa(&5V zKXn3LZgZb-!L0E6CFl1s{f4b?^Z1hM)>9|Pu$5Cco+W$RPm4Ns^ogVKDQKX4UI$J4 zd8@cj^##vA1^tHZ_#L}D1s(U+uG?2Y(-V*ZT_?W&G5ES?xo&q!{%*$xTtDR+5UuxB20f4t*!54mEB@g4^lyR}knUXSQ_Hu^pE75AIDa z-@EriZ+zUT52R1z_XXF@_{mpb^G8o^>&I#Q+p?AzfH zmGS4!>J*;&{p~ZS71zlVPj2OdXD;kL^9M+CCk&gy2ln+9(DhB%txx>|>KMCr2hS?c z9p_%h_gT5R{x#9M z>T~#vFn?^jQ;Iwr2G9cE?oHhx88WO?*7h0yxrRIcAPr- z&v)nGo`TlRpNJXEshezy^N!5jL=TNKP~SKBLW* zIr)J(57Zi{N|B7QUeZe~t?W1r5`%*oebuaA=9 zx9R#;hTmZ4G{!pm=1{yx4?TZp|M}zGiHhg{?ss_pcOQEG%lPfkmOJ@haqf)y z{s|lN?b`Y?o4J)c`AN$A5%&Ch-a7Vo-TcyKbMAVM`}82E0nwpF(?#^9?)S(zGW}7{~+t zz~4HPfis_ZM+dwf*OAInVvk zR=;0_tYJTF9NW#>QAb$@Fz|^zVa~-@>zZ za2@=7$#wd!lYfBne{(;-<99QPPv0?KVC4cac9myVduXj%?@I?)F)3_iW5{a)q7^AKm6Kr#cO5w|^PWe|Dd~ zTMm7HZ~H9C2lV{x(U&qO$9U#%A^qRpPk-v9zqL)Tp)9qW``uF!^ofweC!To!9cNzf zC70{TlNTY6PwqdjKFQ?qv)kt{U2sh`m(D>UpP{oG_k!jpGRN)@9pPf zJ8ArTY5ob)&|LWSUERIur1|T6Y5sSlIUB>?`YR`p`L_N3oo$=ov|axl$qMb`9khc? zzpjfX-$2@L;rV-POz)&4`-eQg^50PUXH@C*laT8t(Wj+cFWcas&Yu8HD(v))kMG*Y zUuW&k=?_77e%EdC9_3>Gbo=NXt|66A<9rQ%7@`q=A(jr; zB=iAy-}w0dw3W-&F9VrS-@xXVpF^6@Ib~Cw)OKyw&5I|mLLSU_@Ht05*O@%k+dJRL zu8$x;5A#KVSI~2E2fvA*uY*tWDKOqZANd%FzW)=~@5}K%O?Tj5di{r7w_WOIM(Xwd z>KgeDXk37?4x^WNWOnnlSCtv#!%sJ7{Iq6-H@jaA5_g}{~N~2=_k2=ntCqKch&wOTd^E0=v9e?5$e1i5@ zU7xrxCi=*4L1o^gGT|pXJ4Zh7pS>5p!k?%7==#yO?@jK@ZfieepF6&(4Z3yl+jrLkw4A_d7c(rx2b-f7EmVaf%!YY%drQ1lD}m;XMc_O zL_VyIMq1);mzFzz?MHZ)7kJ-ZXU~H^ny;VnwUzfV+2sds-gf<)pZMyXPs2W*v;XaB z_9o@Y{D)VF?=3w&>fR8@_v)AY?sHcyI%fP((&&1*Ih6F_MbRDGiKkv10UutAJF;8vc7P{ z?DvuPPLEh!r*ZT@{Q=kH>3@3kvVGC{?$U4j=;d4JKc41@#bkBXKbfD{}_wT$tU(~3*!~^qj&FJIAXZY&SnDp zX&%mZ%RA}hb&}_IN?QR9kUL8YI=%+Jzm9hN8z}c*xzXnPU3Z^*)bnWX30M2+?LE>t z{dVDa@)$J@hj{tQkBQG-yY&2(554m2vsbRMi}>^6OIKbv-n)MM>?L5DmtC)3y?o=j z{IU0PtLe;(hsa{UHfyZ*{E&s@2F-L)-tmrsK7xqS87E*q8)rKkM%^K_D(W#@YS z#aCVct*o5uNdNo`H}2oW?=784%8L#`{OF4>e&m&xFy?2+_Se}n!Y)B#|9;}^zPNo( zV1(VzYkPJ^|3lfhocoEh`&+tF7q7l>^#;`R>~-gsc=lVo59XrGi`wNMyY#{{SB|%Y zU%zqr>I=t#m##sW$NrD`gWH^O{l!;EAln1KuUxw?R@cP|6meX8;qvyr_@NhHydl=L zi8T@?iwX2{!@73HE#!Z8e|~oV)kohSvjp3GDW6xb-%ogP`Qj_b&s=)Jf8+QgS3mmE z;}5@b?Gi`FHvL8Yx#Rwizj$`VeeB$L?#f4BqO-{sZhz(am21Z@U3-y?=pxsUfv}JVVCgaM=$;O_2WygUb+6_^H+|4 z?CRw!FA5i#WY#ES^FUr564e)YpIT>7Z>@FR~%d;IFv8_yj(=>uCc zx*QZPUc2()tJiN_fpI)=jM(LE`s3#=y>R)XSFY_pclpZmxcJah$H!H6`S_(vAHMp+ zhlPvJKY!^Z>*2hQkLfbAisSe;&8u(9>3*7oa1nZWQv%S7%Pbp+o-FpwNpLxtIKFn} z(&fE$Z!Qb%AEkTs+SMCZ_7lFj(1#Ol#roqfJVSZ3q32yQHRTQ z>GEX=%lk3bh$G#O4tD=lm+No5@;s|=j*?w2$eCr$q>MBAMl$CcxB4&MfPw!QI+4rA z&%B6SUbxJv^uVd2$JcLMx^^SN>dijeu8SC;(-Dg&lBskio0Bem=$Xq`o^`J7U)Rc& zYOTJzPR+6hpX~O6kB_JSB0t`8Fv-eKq%&u9Y|qc`{RPu_M%Qz z&)av(<1fKIqMPK-=-=}6z_q^wG=5k5*wINml%*{Dd=Kg20Uoz>dlSyTGrQXH_&xA_ zW>2JxtzGSO!tQ+!@WA8_`dR&;c5BPW*>B?QdxQ_7nMh@0$h|*wjqW`*J`%x_cO=EU zycG0~(rJGpTJnv&8PE{NwX`o0k9&vHBCl}~p6DEM93SWW;iQz47hX%tjl9Kd$SY-n zhV1A4)nzE#XpKfnE^3GPR)XieQ7+DLzELpiPo&e{GKaP~D0xRR%9Evo@mUTg{0X_> z=V+yS@k8<9Dbx6@hCUg3NyH1Jhiq**HOz);m*z=Z zFF?*B(F&SiL&6y6Nyxl_?=XGx;Eni%?EPe4u(xr{*25BLkK?+AYe?gcf%lB1WVN^_ zo#(k=z@3Oj4#kIeREv2M(U@n%cnArVR@x|4a&~DQMfo{f%$6WWMavwlJ%N?wNZ~6{f1=gSv>ErTd>V>v29b`^Cg1$ zL-7&drb$09Rox?RB2pRpN&cW6cJ7v80A) zrhD!7+$e?7R{0}n$8wffsCl(GKk8*iop2*B)zg#VIy10M9rADo*Zpi7`fz*7wZx(L z@Ry@SKevpbW%6cc!4YgjF|8!YJ_Gt|C>QN&0X8#E%;iQTUX_*`vzxW;V#`(|+QQ65 zq)a;;t_CB`Wj{NYGuCFa&U@o6ZrCe^Y`a=qM602Mryg#v%q474gpG>%*$8bH)%SST zHJjkKFKX<<#;Fm>6#T!k=iyI-y>>KqQbY=6(eC3`*5>xP!ujVqb zL9sG6#BRn7d(b;p+qTt#ZAZ$MwW!#3u7~rwt;PzlImJ>IWm`0Kx~DZq!}e+{nfgMh zwHjX3rw;P0ch^Fj+7|SS=k5=^+A;?HGF_maqFrq$mY|nw%~?EB>B-$tAN`m+Rq~nP zQBPc(15YJWn|V7Oj7y*cOPS=s59l3qEpgGdlmU2(fgexPvOVA}*Q`o5DS>i;ttw|1g&}`jMtyroBUDRQ3kU_JoN3y+c zp;N@~o^36JwrQ>yeRm+5)YR@;Z>fvE zh_OXhZiIrP&8i3?-F8Jx86Gv@FZ6!ls)2qS7lb%7#2|cWp5SeN7+(y9NGg zmTtFgeSvn@9(FrQ8e>Pn?vIn>ZpZJ|U=VMye(#P`T-GaS2gOpeR7cl!em-~!a}2LLSZ)c`Ks&jT$05iG z{YF-U9%@Q6B6ey zi`*DHCrMeN!v%4{lP`X?H4TBayKt#ZrC9&KpJD^iw+*ao5JF)XEdDMU8km zI!~mA3t{3N@xyeG+H-tR1-TIQ-SL!+@nwC|47Mvg%A&rP?g#kkx%&^_a2W{l8hlS2 z_z7kxcbflkXv0trhj}Rnnz>-26%^k?FrUJWYVOj*_jRbQe| zuCE%f3W3o2&P0O0L|P^z5)5vu$uQv~AnKxoPR$PR477@*}A& zj;H;(l~OkYduiLv^~UztJQwA`3(cL1Zf%*vTp>rEF8?T6@zPj(6g~gAWE4l9a?Zo% zgBs?VGSQy&kJ5SHaGLRsIMkmY*Dd;|pnGoHXnF^RZQ2w3qyxXzh1D;N2cXnl3tDN$ zC+>h(8#92l)ZnYU#=(ASap)lEE~gW|a;xMWZsPD2y-T~{4leoOl3QXd z0v-%|ut55S(GI&+st0WTm-Obmyc{P#LlA8Y#)&8g4X50VcMa(Bl6TmK)*fNmUI1#LUuGsKBK zFf3bLn8b~RA9ifAp>tfbC#6UI`y~`VP6a9=Qx`q$cMdD-L@1kF0G@Fbc_G9$KWeFlizuDv8A2KX(ZntJL8=3FpPSnMhN5AhYr#U^kJz@ zvVYi)ZO?>a$~W8ytU(olTZt)>3FS-l`xCYNzTTM(Nse#z^C+8w z%skpsq;f~-D9DZ&%{yCqfGwxJ!dP&#vWpXkcG3feZ0h}ly`q1Fs>Z=jS=i};@wBCz z?w#v^-M;C0x&~eBUnkYG-)~9}pD7qd|KNsy4QYZNFV3lb;5do>J^QoG6DH+n*B&b4 zEZti<*{2KgKg(jDm;E$n33ewm?m*ukhc{?@@ET4qZld;@4o3GbkKH%BbHG3Qw3B@H ze^W6im&yB4MV`?FUeI6DA6^SWk7%wjmZ4`^etUWD@?!cud!C*>=kcfIwY$EfVfUMg zqx0Q$F6j0+_QX5NB>gbH+`L97_m4B%ynpF{XQX=+H;nrsP9Hv7LY!}2!)=l+{NyYh zU5*C{0|?=F7~f=1^tu1s8P9Zy4)%zbP=R01Ue1=RO z&iVQOdZBN~XrFc}mgtUyAJEI>M!z9T4ENagkjAiEx~Oi@ho0FUd|V=3Q5#1Woe%WQ z9@4hYk)98Cc+ti>ZR%N(lsTh`WF5jMz{i8IBW6DwXe5IGPeGB7d!05Ge7HFo>6xui z+d#^T;90U&AG6y%`-ARCZ-+ZDuQ|(XXV)aRp%mrgLoA@1@g&kh8uY`jYC@4AhN(I$%f}@XwP=M1_kcGhhrp6 z-qfd&3>~{CyF%XpBHZw4wi>OzHtEim%bw-7t&R%6FMRPy$rkX2XOPhklR`&$aLcUbHB~3=hHz**KFI%M(0!J&!NI(lN;cK^w3Pz+@u|17l7T6gI*_+QaxVgRC9IRqVgK3OY*UDj zy2&W~Xuz%-z@0n5Gx3bMPFaNOiiJ|IBUJQoe`+Ze@b4$Am*kPQ1*=$56;e%Fyvw{ZrW7mRT5K>$!HtCIJzjwXp`Ai3g zCjYxAv%1oscZ6gu<>9^QM&4JobWsDw8Dq9)g)8H3djtJ%`y4tszyVuw$7zgC&Apdf z3vS@AZnAgS5b8AWG|L=A52)i-qo`$9adpwg{5;nh!ig?aqm@dopWc|26xIWTP)A}= zV>g|a8oCj#mIM4C>Xw9Nn{RJQz^H+-8~uvxiDOL9+L#0IfGl_|jinek(d0162)ajE z>lD+4Lijkaa&rxvr#7@~2xATKOEqr~B9a}8>1!*H>2?}bKnLC0vQ!!wLT|oFa-}S$ zufW=DvDg}Ks(cCj6lZxi@`8=Ji`9UcL7PQ={$Y+d^-~hHQ|@F+ZlgXs^@8dv`UK0W zP&<_+onSqTyIV*Chbm5Ny_y2{(Ex6X-;uG=pA?1>zpnVr4mxU{`io^0zHGawTWYMh z7IWFeWVz_Ad907^UDxRMJbDw|*!gAF*>7x~D#9H}In(%hir(9qp6<7U21ojol zXM!V?59>bf;pM!V?3?!ZxzkRGvVn0?h!2W@T$`0;g8Bxbk~5>jh%$yhr(9c(-DBAU zA62Zju~WdGjS6r;j6oJHOO3QZJ8(6-Vc8L2P^rSG=Ldcs6JU#2mt_>yMQJ*S2xFAj z*4OPZ+RJl~vv>`d$8_bl6|6TR>>uMMQw(S09=TCpH6X8zf&N44HnqGdHC{){iFPHXAqT(9(XBl;;jCxNvF1}Me=&IZe>8Wn04*ey| zlgP;8wexa;=Yd0&76~3p!_d$9!3)-iq2IPFf36!!G*W49F)4-yrZC2um}L`q8FaP) zE)HA`qc790f-kbGZe`pnnC|#8kie>#jpE7Mu^g~xII7j0wiyIUOECv8TsG&!xP984 zd(FNsD%p03A9}a*xO4G?^`4wJm+^K7h0@$s{Gh3lrg1CUDWThGcXM8OyzW>0k)#%! z_jB-qdYY!y1-=RFoZNtF7b^3a3%8EW~t>xVNQp|MHYO*TgOU?)EsO0(d!I9qYe)u`@?N2B#+T~Zcp z5p%mR^>M*UG!sv0W~NpSB&IVy;ltFc7F-6#@scyAk8{8at!yKclQNpolFDi)SZXYz zety)+FH)Xi)fv+<9h_eu%$LCCnV5gGIXLABh{BN*uuqzYbC?5pppRNRT&SC>XS&iC zjg{hQEc+9sRS1^^ZJO$h`?0Vli~V&N{UZ5x0r>PMok%iX0xpC?f|w6tTm^Z#IclS* zTwht9r1FRmDcM!n|Iv|u@h>J0kHUyY9m=%k0W zMDVd}{m5tjJJ7v<{x-8gYN1avq+^WXFo7j8z|*!k4ikLWoJJ?`t9ZG=22crV5b;7d zC!OVHCU7;9$DXhIkUr|~Mh07bEQA5p^^oj=MQsmu?qGnR*e}PimQ}3w`smk}=*vwc zTNCeuRXp!~)h4{}=D?nj-jEXO25}Jm`+C?vf1AiZ%NF|3yNw09xy6|-2#?zFGgvGq(Lo|UN>`>6 zGhcBBhmGJIe4~yG2&V==YHmjPo!J%rc$~UGafA;8sYJiG)yG-AAPR9nA2jxeV%1xD zEYE_&p?@Lgl6H(WSj?`dK1Hj+F_F&>=w<6K+g*9vzpJfz1k^(Qi?ez`|)px_B z7Hrm=M6wM&J1+%dzz1<)Xs$ZEQ(C}u%#Xnce$2X{GN(}+<5Z%@VD*70WbGB5><$&{ z0|w9w=w-Mk*%aMV2M#uk(?+{fIJ2c4AG`0jT^o<30QgsX_igU66#2Fk@_jzu7O}qN zOuw&>w=BB1<-zak<82Y^Th8<_`e1WPn$O@fjMKVK!q5V|7N?jHT$dSvmLCqex*M@`j)534>%g zbBEyr@fs{US_i;r1TMizR0Pcn=@a6)D0~4Nmq+D6s5#49K?+<9K-_FN%)#2 zV*PhAyXbXt;v`sR3@~2Ul0ll(9!4LIT*6F5$P{vdgMeheOphZa45s`w$X2pTW5hoJ zV-pe6Wpy%^D8?-&dy3)glsBdh|4LT2m2AmU{6!Pk74REihJ@pac@w^*#io*sBzg(V z^|7`Kx*n#TEwc_Iz4D_{+{p9bF=;$rAt4!-=@*vPW@0+dC54HSJKKA69R;o4NU zxo9QrUiZVmSwRo*HNwBePa``A z#!9j^tqRU59#0_omUF(inAD=}Rlm84QfzH!8xILQ(F!w+xt%xbsCQhu&6iO{kQd_i ztU|*S#ZWI?(y8u2AJmQC_%ZDt-8y zDW;{e=vS;pOZSJ$o4mH*W4%a1Ta_At!aTm78b-j-BguAK%mov*Tt(t@42LhR75Ere z)VSmDS<0~HoWAwH$O~&RWSVmZs!JaAHY@`R#5x5x>H^|(oEX(2_|WulqMogdcvCm3 zgwIfX6!45CFoD5FsaA)DMzc6iRQ&K4`#8z7!CG=l^#FIvb-_M;yzIM=GK&%YbRM2`C;stTOo4%qYCR%LN9Z!}* zSA)p)uNgl#?v!Yks6H$~E9;T|Xc6 zkGg9F9Hjbo%mW8v3L6D<70?X~%A-J6nl%U@mJK=sAgu&^-EINvA>gc#{UuHB2#DiR za{9Wz<~1*8>pkWdIv*>j8$&L@V!bTAjJ8R#5Mw^yG$PrVca91Wq-***F>Z&jMgx4n z^HHB{3MTA|u)&dKO$g^`IJyBYVh8AV*AxN%SazWr)I;@EShTEaWn_%kh0JsTc_FS- zj72KZl2M9U=i`B%u3=#n7n;ijH^rHwkE0m*ddVMLOTJk&?*o*KH70$8GpT{L0XcWd z&GKLn5rJ_UHN?`Pu0$x#7V%INOB-ofF~kkp)uug&p{+HvnVAw0@`ZYm8rWhJ5vlRU zJlgQ0zsX|FS!yH5oAdLL=Az>?jVDyBt#ab{(U+C7QM0)kr@Y!G3_c3eNPn5j^ku>{ zO+6;BtqA{tgewy-NiRH+^neo}Q-ss<1r zx}belEm7vswtq&QY!h`W-Nxv zac)sc1`-~*rg#0?qOS_`s3A~nwjoBOmAOcuy^_~rB)t?=ab7A4qsV$ZHs)i!=r8ow zjdrPSPP`i2)ANxqDUO39qkv5fq6>c5;sI+n&&>zgZ)(FaMx;3iV#+wK+R8N0CuTJN z#;C6{b@-r_UU)T$V*Up=HQGq(Z{lnn1Z>C$`BEM@FeboX#5#s^vzew!es3)=29xP@ zualqkhh1N9Z8j3vb4GMK_$KVh%UPDzrl-$!fOcNPx?47emhg@78(jlkL=(;7$llqw zZpekYVXHxSlc5+xLtNBXvFe~ERXn-TvN7>wr1Yp&?iD&{zbF`|X&A}`asN^H*O4#s z^k}V!vtAg#HJM;YtoN!d&cy?Jm|@rM2e1iZ0ekr1HtC4==YiezMwM0}GbmcX)IcSJ z1sJW2C&YrO!muaTa|J(Q?a0@TYBPbmdSNHLA(A`9LhG|@IH&PCgykGQ@G;r_cXurqrwudgc-r+GPb$>Scw z3)a97DBjSlE;|TQLoxKxIGTIHXTfBI3mCU6^7+SCpx4dSXzekTL2I=iS|^ShST{cC z>R2OVpsgY~8#8-6U|4adZLuq%k!Ki(-v1pN$6{yG2>HSnK2B z+jfDKJbu~05Pl@^myQFf<0bxC)V?b$YlB52??gUFa+=nqp0 z9EavSXs_lE-+DWK*Fx_28OBNEKY$U!c4D?6*V~0GFKOx8%45Wu15+I!CeLA?@T=n7 zWOab?^8ij8#dvpkZoB$!_@0$=m`iNw-(j_TyZ}60FZzZoXG^UWjpfPiVi?l0c8eB4 zbl2^0vi3k(gh4YLJr27X9$>utK<;n)L2-$Ovgk8Dc33m}vE_?s9&`<0fvk0H z;hf-OchIAhIm2lg{m!`ub>32HEVl4Xg&*<)YlQ*n3Je+ptSf< zYzqQhb`Ng984tT_+k6duW1x?HIO#6c;l4rh8U4tW#RAedYcz2Jc{*bOu)+E_`rTsV z4H^&bj4<|3FD3Q=&oB{5-zVhjNI)!x!3B`n_EjbH?)n z57To&%onsJYmOhjcj(_l>&}iSZ~9FiI_Nr$5y_sIOttMAb8H)-k$o{|8%w&&ktU~Gu%aCR_!fs6C?9NcEr$6 z;*t72e8ri*h);}@Dc+9i1lnAyMcBC`7kc8Y9`{8?a%PR;nHbqUl9ltpxESJOyasp; z<4dLk+;(EAy!*M$##Wx&CA3HpX%G%LN zF`ip|iqVYn-0^tW9hU^qd7nwdr#kUkc$CSP#c#q+k;I8f+>Oy;M|f^XI=~!^zJabLg%kU#b2v;0--9hZF6Xt1N&x8iKL4F70!eahWU*koI`3 zAbykZGl~a;-;TuzW)Y*p;s@cQCw}KD_yrD!74T*U*aC2A+9T4muou-jhkch6r|se} zH*e9HomCiozvTnAL)F&d11H#DR51iaV%VfYxSxo9_kgDn4OTd5mh{B3H;(IT5&Loa z5jzM30efHC{R;fT*qamjv#>{JGgy+ktJT=qQxbY18>4+P5&KzP=CQY)mntRp)nj}R z4d*;|Z3n(lF9x023jS&V_(TlyMjaR6D~Ln#OCjm6F3o$$}sCnfCas0Do4rQ5SP6ltmrP!RiMZ4b%tfZ}~{2 zhL}af&RPm&+W-dEAgmU;S(kx{2M8ap1y)j}<>nEC#{9H_Q7_(I`=+Z+2X=-%*|5Ky z0l%tG3r1$q#;h9-OGRJJ=(Wu$;yfv~M_UOMasYAFWqh{fXuq)_-}43H%d(++QoyG= zxIe&pSbw+@#D3Kx{NR>v)G6uk&%+G#(0vnaCB>1mJ`M50Xj5tL z-9nzQ;!HZe0Y*?6Z~XB45a#4T-8B|)%>(SI4soxy?oaZFe++DNwT>7)v{iPw*;Zmx zIk_RMz0yTP~S>_=#~N{fD{O>uX)4vfv; z3H7mNWu5>&2%NBHfB>vRIPXzo?Nnz~M{E$*ESTd0=tjgqNQ}B=t+OgaAAW3nHZ>h;P{Pu1na{o8r~1f->8L`Fy=BRrCC$5uBml@R!o*G~!At zaDps!C6H+V2Wi>*q(Zg>%oaF~f!IeCSYZ_yR1W*6s=%sJE%2ib*4Cik5!<9MU{dW` zD`OABW!gVlJ`^A5&m)@O1kQ|DRN@1BE>J%xx?77*xKq*svozKPM2mCYGwLO0men0D zg_wI|d9V(})~x~UxjA9jpWbyhs{vqG^SWjz1FZ4E-nDihjt^mLHA_up5f?e_w5>WC zH#qPrg)JZFuIC;u>TgIh#QYb~CZTPz+_0mpQp=e+>_6bo`l1v3&bOsieI$ohs0Z+6 zMM@UJ`l;Qr#6b~!)E2;`XkYeLKv*W-o9?tmtNtR{Tg6oVJYpwG#JmvW~)F3Pi+ z59@!@YeDP7uFlN|YL{EeOqUxS*dXoUVd{{xJB7WSqrl7!vC>O#1b1%G;d}L9Cu9#) z*bwben^G;TV*pRsSU1o_LsqK<%NC8DC0`xuYf#r&eGhc776AAGHYY^=K)XGNS2o>d zE027#g>|XcJ52qEVy-7+!m;#djaA4fffriiqZClz!;(5TBZE$PzT9*IF^{)D>&Lid z-y^Op4}9v_%T6IIc7e|XAEUF;V;FxlfvwvZf>kxdvSGVqDI24lx3!}F90#ov4Y}ce$&*Xv-8P`g& z)YJ@&qKFYh8-uzfRHSBX8eGNG@l|}XnbIDkp=z)}SRsu);P*oR1dL@U2eG|yyBjtu z^_5SBpWUDEY_KoAG+~$>(w^%ee+FSH*xnu=8pBiZxCUb%V*0AFy-ouWcQ6#LNJV&^ z0R~KrwVG;R&&}piiB;5<7|fNW+Njb_$fH(IZT6=K?SidUhd|gVbDGQ&-?SG5!`Jbf z%|Ec#X9WxrKOe&Ze+cbFsO0LaX(^BZrbZYJT+)d1!k4KuyUE(jpRIVu;p9{|O0X?p z280p9Jw0H)w;fin^WhQMxOTYl?sq4LUN;O}Z4bvG{D5HxPV7y$GjEZN)}(ca_J$-Z zbPK%MIc(5QrR@Bq`{$3956EpURHd{1EO+`K#_Yio^xD|(HKJ8C;7&_!6Kmoc?W4K? z25Q@_PPlR=t(}i`tCz>g2fe6;=-J^=4`5SRQ)Q~D75Ua@DZH+t!u5LV^_c0zroC%X zn|ASoV1^uij3?%cB|r6n{8wj!`qNLk7+2hn7lg&rL3M-T)qp#XbSauJWp}544 zO|%6nrFQI!&eHWz5^XT{(t{6ms|z}RTznL=b?m=@gX;8I-QN36bsDmtm_@`VEcrpi zjXe)0_Il8Da85i&dTZnx`7?Xk>Eto;0TM|3&WHHf9mEqm2$QW+oS?C`0{{mxls~(U zu4a35aO}uu-`o2Bxb*Qr*>B|s^B<$1bNt)%je`vfcXj-&2`LQ;CmFAA|{`J;yi?aSXH;k?8F7%#`X|t@vHj;*XN59BvxIjj0)9)i@H!A)9%D7E(P!@&t2y&{H~dBv2bIO1 zczEX&!*<+Jvp3IS4KG*Bta#9kJ?#j0rnNNA9+0-uJHWa`q8qZJKcs_U8g$eAl6~k8 z2oKVF5f1Cdg-KWUn8409Sg;RFAqF2BFc|U^;ayEmj2iq!*rSuhRT0*KdnUyj&Jmwi z2~{OQb!0^adVS<0vc>7a_5pzIK`;3wN&G}U+oO{+TAC+!DofA#M;cgklaMli(Av7}!4xu_dZrsCUJ&RObo5 zgI~b30Yn_?fc5yEC!3SL8asDsvmP+i7e zhKP3!CsOg+8W0O;NBr3u@3JgpfC)PLi|U921lBg+xFgeU*#!NB6&(q%pux_fX_P4jy$G2UQHj9blcVNpYxDE;b$%fye41 z;)>SbBiw{MGi7XCR&JKo*ynMh7Yj|%jTa~_X7K+b2Gk07@D5er=2V;?TRTfZrf4CxzGIxbl7@ zyOcY4KT|NUvI2-JHNuFoAxsdlHrR_(w`KU!(OzLMPH{1|l`7)7SS%F$6R9ywt~TlU zhj{;>8RWGH?U{#qJ<# z73wWsY~>ZKN3OPV86h;@gt6*^-qDvTQ@kKBDd;JH7%+Nwi%R>Y0y`v(&8W3Pg&f}Y zC7a;4))qzJQE{xF@y???#6iLqc5~iy@j+v#IM-T^dbIw6Y?tczU|rtCC#`m~wZiXC zUh}to3n3RH99i~fQg~+^d{>C|qJ0N-8`v`92zBf|Xr~mU0ppVi@D!T)hSX{| zC}yg$5+kWVA{aGF_4TGd%Aj5~P%p`_&v{TC=X`i?C3LOCfUgx0Tka2!T5)9|3|U;6 zV8!Z7K|#n}+s4{z#7x?wuC;<4(SDpQh7SVMWbcdv#)z%c@N5i-s_FERv51`tP|}l*0$;Xc6+(XWWBB7 z$ViOWrV@`PdZ0f5+#K)Uv?d5N3N#(s2zOpoCO!AUqxIa;skT__?EQUJ*6yPIqs|Xk zN-Eh!bge%w=LW@c+O*nQDUhiWUUmKhdsSlZZgkUlXJ%%MdX9HGi!rv>h3Hp0Yu}Le z7hM4Wk0zsqWxpCl5K#&Hi=v$>VgTjAngnbZs^&V_^AY;;RE<8O+4KPR3eE|$UZFpU zxCh!Iv<&gndLhfr#@z;D2D9GvMm8B1b`U>EJquH4wapG-!fE&vKgandPi6 zxNNqCRC8IDSJ7;AR2WSwi(z*uc##`)LF-Y^c~F0j@gdCzDb~(eH+=S<6p8_3bFDD7 z^Fp#$?yf7!S{$qmH85TE7nNnn)~f4lKB~#_c4d_e3^&PM!Hsxe7E5Jf&CduRW6{G$ zF@~!lH|lpeu^EcPHsv9F@OZ}zeDLQyc#YJetOfE zmMa^>;(A7y0P{r;RLj}O4qIE}1y{7bOGt5?Fdne$10F-ag zi+Ik6DQYwyq{?yrb{AuIYO|;>bZAGmIE9|rx>0r+{R{Tn6X8-PAG=|yi=nfJC_#XP z8w|{`=?T+&5{7_xa1m@0jzhO>BUdj|Ux)V^VXjFsBRS#RQoZz^JjfBBa~~uhhBwn1 zDA*O&rEAz133E0m8@2%70BBg2@ZMnTFKDTN2b}jQ0!y%gaS#ru8m*3Bj+N8JSW26& z)gt5Aq0r2e#i4v<5rnBDSuXjygys=R3#`f;=5{usTAvO1zPN2xbjp zp1YEWE|5!t2Ifb!gVX`^fv*+TGX#>g(j+;{rxIz6jajg7q^aUQo|y;{jC~-IVHEF? zp}b{ONQyP60TUq}=-S(S0ISuD4Xlp=9<@96&v9)6n-UXRYUwE#wMu$W3x&O?BiI9h z9#~kW>Op)UlMSr}I9p?jIJJY#qy8)@xZ}0Z8t)O^v2gZ%#>>J+oa0a!FPmC2J`clx zG#2Rn?byN^iBU(Ozp5QgP9b|*D-8K-*b@S4K`iC*?f;04oH0%XrVlK0ho3WEc5#GQ zw?JECjAc6_``V?kYy_QnJJfU1$M&N%XD!x-Q+zP$9PBEBxLQ{0|14P^;yz*DFmh^? zoZ}1^-2Mg+PMd|_h<$Vp;-O0KghibiVC{xsH&*jDXh*CXVyY3h1K&@;REBSRT_><=S&FZL{jfe2`!G-{4QcUTWAPaH4g10++uAHFD?UFcA5I(#*#O#h zwDBZT`Z#nudmIjlz9`iX*gHP#9hRUE>yhu<)b^f}2G@yQsuvuY9@!M>46$Am|1S?= zS8LMO;SQo_FF(-FWbVYx!55GBZc?1ijt9mE#mzbUelR*9WAI4>0gCUWaWiDXY#-0F zyjkCe>%<)Np~1g2#NHBn<+6;<@rUHLkL&c#F3bf8i=rbQFiV>ec-i1N8k-*GAR0)( zc)z2wA1BG55dxcFHV>Y*SP#_`+@ufs2p&H5Ry8PuDNd+{{YCNq!31LL(#1w797}nt zRGIkgGgL3wm=rp+tyKVawc0fqNOtbS&9QkC@*(-bP8_`iP(QJMAM2;ECN|3Id%UWt zcsE*h(CJTRn-JVxVgc_YgAbMPg``CLa#|(YuP`jbM~wZsl1Xgr9_{4&Jz?A`fG^Ug z7i&aESnrDW-m&ti%mW;dzef2HAFz8aiq}Lrb0{ADaLK3uHj-GdhGZHYDR*h5lGigP&|PI$Z(14gX|qH zEGCT3tt{=yiCsZD@F~)sd17KA>mj@|KHYB*5d&9Z`|TV+5iAR$8SNG7In@j3As$c4 zKCNY9-%UVBykoAb1}qwd<^oM>${xec;L&w(lgxNilpmTmhaVK<Ob+qL`F2 z6d$ya*Mx5pri)kw+DjGh?6eB-ua7Ve)VM}F1m64#=qEh^*UBnJDL-Gz+7NB}0pf|a z+Qgnpuq`M9|DhY&&kkiFUYW3C+KV<>1P|~@gHF_ok&#*CXF_^as>Z9Wax2Jh3XRsR zkM|EzdTP6}@JW`dfpQA_s|E4)zEC%mX=A@nyem?NzZLIP?3?q6Ay;{NXW+pO+WVN+ ze|WJc0rnS_$9~v6-q+{EdcnS^eIg7Kd)SJ(e0sCQ23`{rF-5?jS_`3K)K>0Du)I{& zteGCHOWpNmoKpRvz*G*~Ybzyp@_I6u;DWWLnPG8J*r0J733j*b{DC-u9%xL6ej713 zz>f-L8~Z>4!^1l|>3y8Q##tMcOzE9WFY6V;c&A_k@9YEik;AOjlOn(Rrf(PZ^;%JK z360mVo&)0$_^Pu=+uMlE@t=QZQ_=ec2Fg~gEQCGqnVU)q^@eucXn1k1-kCnKTS6aiiVc)=U@J?FR zuB;Qim5hDTfJff(2zBQnDHtcVUcSB;o z;dK)ZdRyr>CYu1>OSkOWN@lg`i=M>IW$Tpk1_GN59EP&&}{(!Q-2JP>=<})0U=ww z8PJw7v}3;2Mobx|nDi#%@Dm206AxmYJ@oEA@StKYfxSfW&QvkAF(gkrgtZLrrGhkg z{~a7zsMq8i4ot8%06HtS*3ofo)hpqCvZ8l=%Y*QN{x4eT6;~w@SY;M@`+?EV!|1yU z!?3UbCgp1(z#LRaWr1$4h*LBVV{sYXVgvv01J~%UvSeRH~ zzi=8WVQ=Tzron|0HQp2|zW79{_q+c7LQqq4c@Wu%M#WHyGOe50l)6a+d)Y2G&EO{5 zjLy6Is=sj$23=*)3oA;g(WXsae5LtHSoZq*Mrc>+?NAl3RHuIU{Noe0-yr4zn4|NU zoBBuIV7Y0AD$Q9+YXReCWE2{Y5vi zY^Gn(T1iiNS>clD;1KI$dgw>zw6|%w`k$zc0@2=L-hW7c1E_!G!Tcd!K9ZdFD+oLTgg|(db5MK>aJ3cc zaKUHRqUChHjIC20Cp-D93A-{jv55(iAr9z|zHMu{z=yCwCYwi=`*vK!_zN!x#byTg z4-)~Z>=*p+V8%w=P>#ko#qK<@DK#?x%RhF8F2T~iHhLi%w2 zl0S=Y(g*lp@kK;4P8j|4$H5RxD`sqx)#0jEkyn1ixGqZzg>(Y@1Eye`2u-4OZ(Dr? zd0THyu!m*uvFif`E_K>(-Z^#wQ}oNSyUUGTod&hIds5A$wB&Nx%#RBWe#71^XHF28 z$9#HZSDJ)%nYA(eS6F*>2%PrMQpElH2>s(32dq9gyzKooC(%hb!Atq&gwK^nt$sb| z_c4$!e_obGl9J4X z__f`|9ssE4s*QK#Iq&yF%M#o93Xn#9j|gG+M0PqWS@U3GIRW*z|#6ANpxV6^2R=)p2HL1fp;0 zwkK=o00DiiT{-of?YVoH^_BN4z}tC7?HxOSQvp+;J!%pAI6zkm zUn2Ft-y_HO`S{DFsPF6J`}%l0B=CK^`twN@_!*72*&K>6W~|5IwOzxGJvnJgg|%zw z1hAHk;hNMb`@-&Yw%8c1-~;j&vmvj9ZTVzB_GVayvW?bgq~xM@h;Jo$%){J6!bsWN z41Nk8@2`>S+wt%D=d(L*X$-o;My>*ov&;#H|50qj(p>OUOS@SeoSq#(;hD zEWF>ZkNp(kD@JTr7VFGc!Gz@f|JgeaCC9ZR$bJjGC+Iy1g5G;?0RI11?8%E}tDmIR zN*cb2eG$4b9GWJ9>rG{4)~x?zml{+Pvs!Y1U9cIwMK7HYdZ~;Bv{7lZ3gt>8FIveJk9gv{v2Jyixw>n{ zyztW4ggzJDKW6Ahy?s|cQx5UUNZ2##v2=gS{l;)i$HJK#*xj*ff;*!{NPp6Js1D+@ z#JD~W!%^8UQq5{Am?$r2v$KgWC~aCRq&SMh2tGEuWp%f_+q25>df7L7rx#kWFRO98 zyS+CDhd%w8M0-RvFJWto)}!q+`G-q4ZhD=&bnoapA?8)Zhup(c8>jPw`t|89gqKaF zBY1IZ>3U_BN(~a}$#qpdw=3TBd2d9pcW#%hBqBiTYo~cHV73C7!fuVZcXfNzE5ijh zl|ATFXF?7-vLj|f?B$g~hO37Z?a@_;-@na$l#dBv+$`li=eG99i@Td#xfCFz!>0L9LS8wEFvpwWvtzYCZR69KykC({Md6*tTlm zA?eYpn`_eNZ16#RNFH!E58zi`Xx2-GJ780(%(5AUZ$J_7Y5CP+XuZ%F zncoVKHaxg-#s_9Nx+W{>(6G5ku2`ExrB2jM?UvTv-Guv<;VCkohiJ1G`kU|&Ufs3C zu!P$hKB4$i-S7l{8hz+78cy%&!L);^6dW2U%vCCLb30b@o-JlS#UBiU6-3bHdv+|= zyDB;a_sq53c{WF@dT(k6$8{I{tl21skIO@5d=*Et8_&)+kK$JGIbWL^xbp$O2WdmL z@K<TmzpL$WGI7kTv6COVr}iZIuuE`Mr5k#fVvrNAHd(doW$)5^ zw9m7}%gWJSV4vdI8eA=n?TwhD*7~w&CYH{5#QIre+<%Hc7zz0?Ev=T15weeP_x;|q z(uiz_sp@D5rnc`+61NGw4(82Qi~K-ej#K|&XZEY_br(xacSi{Rt6 zn1MetM&Lnumo7YS_B5OFB9%C>%qOI|{4xF@_XYz@K3!=?D2_8+;Ow3KL#(&DXUF2& zJy!GZF4enD>hnCdL1HNmHq2G<5K4-ZI;5|GCtnu*`W?BDtjtHu(~#$CrlE97(hLFx2ILV%5>UM-uxXQby*#Qz8#2`@BtCbQ}azlQVD zj#|Yfo;{_+xsyY;nb@f7*NVOapFTZ)dN7(dxxvFW{Kqk)ig=yf_RZa-56?wpmb^#c z9Y0p7;o{c5wKt1cWQsoL=lFw0qET7^X|3yx=fUSf%p$k`30k z_vbO>z(WWqG39=OKSzU+KdJXJ5uSjoy{OxX!eFvJCVFSvKQxRU)GoGqr(~@Uql&56YKlZ*)*2}3ZQdO znzPhL_=8-FOluj^ddSNyvA6TWH}SWne7cv)S3B)S_GC0Ux}}`qr{o}e5d)6bt_Ns{ zo@KJJtIw?cadq}e-RDMpqRIV%?r_L4J}jL3%Yg?mUj4XN@cn#Sif;aaJyw~_;(wJd zQ(xk!s-0+(%0SO6L1a>iQrXpk5*44G)#D9l~dp# zxSH?-w|*M+jn6S>4*ZXqd+S$Kkp3AAq(tCs zqs?q$CZZ*%x+bp%tAVo#-f=BQuCH+@fse&Ca8tVQOlwnVOgE+velkHDR&C$OlQ zYY*XZmYGz3W1<}Al{7GvCp0Yo0qcCc9@b`7j*P<)Bm0LWn<-9L*z)ktlPxS9;WZOD z3ELz#Vfv7nJG@Qc_OhqzNWRQmZekCA);4PH`7i$ahrIv%uI3x+)o{Q3&w~!nT0=Dt zIr<~}6DPwNZFuy&;l!VxD6I2|^^e>9JBc!w`u=C%{Vt!GyZHu_G`48!TG*`0V%j07 z7{bg|c<tiQIP$O|2N{Idehy@&T}>J5O{0s;mo%_@}IF4|LuDIm{ncBvt<@y-tf=) znqTs=O|XAa+34oxAuR;uPkUy4=D^{^Zg1*kD;t$!kPWfDIFv)zF~9woJyCUK{JBj3 zdFTD>+3*Ly?bwtzkioQ*Vb!O*V@O+7O#7%|0s{@jFc&1X+LJh1?33^h@<|s$E1+Ty!t7TqQLI)1yNE;Qaws=FiMqh&{CV)!+gSiRQ;>Zn z>4W23m*ZZhlbHHepVoNy`@O~iYXfy2%HwQ1p01q3;&i<(wgt%M(0oQAhG4q9^w>=t45oJlF#+tdS>19WO^LwK0)#8&ARi>$S*(p zbBD&Qzjj0$(agl_SnvU3c-A+?-?9yV%_|Deu{{^OkHZjUQ;Z|{D#W(*;}3$zNkL)}Hb&vd;KxOAAhV@Fi8yKd zb}VwgETb-5VaAK>@5HjxSXrIt+2XJi4n~Nb8pMtrYr#zd@5FWwI(=-NJnpG^`*Q`M zFZtRX8gr4rJ*#+?A^N!bkiiC}8%H}Z#=UXNsowJ4%k1dBYSZnaInNF<{eEp#e!6{O z%iw6C9L=~Wm+Ry8BQ>zA?$`=BxmjYgd~{~COXYEUdPy_c`&v>TDGT-yY;Ro3X-i*; zy#shS{lm0{EqolEVA+1bmUj!Fp1rfUX9wbd)L*&W`tHRmi}`o}bg&p+JDuGlyF5RO z*o(BJJ) z{<2KvA*RP}>vV(oj&bZEYw#z^_`skQp80qV`l7F#ct_w;kG7YCyF>iJ#e82u%MV9b zD>$uRw_rvk9BxwZ2m7BX1y?b1Z9A3-)>Fhcr2mdvuFYK3@p`LS$3C@sXAhq9xSnm! zZu1lzK&NubruL#tNJCVZAQ%*Q4csC$Q|(R1$9E``!9FKwR?b_BKj?XPG)fbf)eSw? z?0LLM^%fs1htV~MO;f)ymz=>{3aHcdIZ%hq_+-eut3 z!I8qK1NIyrgX?r3R4_OK+{goE5SH5=dAZGWnoJevGx=tC#pi0h&z0(pXSUydX7>3H z@&^MEryV^mgJ*x9vf5~D7n8w+1>`#EUkh3rvi+Ky*`{q`NR@iS>prw^hp|!RhEH)% zvAv^N$=rLH!uy({|B4Ow1t%v>{MAG6*z(XAOc$T_IpkX230`q>JugrPsq*LegMmQp zc#Gl7!a5P6KgU>iQ`LO9Js#c0=|<)GVEw4i8?)Z1fgbGoQGKBGh`cF2@3kQ~Gvgeb z@Rgpgp4IatanITl_xiBFpS^=LMb&2XKk31qqb~$h=S{omRNb`Vz$cE4QE-|`3ObM5gAqZ@f5ZW`mfB}|R>pdS%G)!R%W!E2#8 zn8hN2a`=$3h{^rxd7IYPc!95K_pwv=z3I%Zv`;tm$eP2C@dv@7I+sF_C7E>&4Rfu{ ztlRj+)E3FYxKs{Y4z1*deGxt}*9mwTZFUg{a!AZq8%&3Csb4MndnDOI`D?sz0CAFi zK3AiB2jQIUSGUA?iM}qG`Iw=xo?TsH6o&Gj;|~UkLFO#xW@N+ViW32pXVr>L22J@R7aKI z=$6c1Gtc?8-C*4xt^Iw;mtTqFXX2OUU}H-#`!&wr<_xa29bI}Bdd}t8{LFri^IVwr zK=!UVLPzj;Ll>A>kK^m=U{9N=PS!b=mitvM<+QEUJ;k~x+b)35>OvIw;}FU7-0pF_ z52tkpTb8a(ig2&r#UEtf0$!Es4=0$ay*F&&+uAXIkY85BM{_(Hh8-u-tMyF&Wv}Mp zf}k&h*hIAl1uwXISywg`opnq>%>TdRKi!YVB)Mj9Xclqu4ln188W7_Z>@*ePP*>{P9EHjMk0;nSQIjQ_c8G`}T93IXfkJy`d?+T(j%sBuWN2Wtm1SI(rjZ=Vv|ZS2yn6_Gm7 zUx~nYpdTLCX$3a7_L9AGdrdi{`=b17Zu~82Fg>Tq5BR3fXH@2t4Ay4G`@`^rPs>BP zIu2He*Pa6(BnfZR?i`oFiu~*N%Gz~J+}Co5hYW=S-`oH%0udD7)`QdMB56(*dyw2P%-^8sj zdvOT!Ie#-}{7Kml;VX$=Fhym~*LoZY;CI;_TsW=Pqxli~qQhylie^{3c}_;H(sHcd zYk|;4{j%Eb(HbU69!K%von+95yY%6&C;TbRMf^Q9_YjA|kEOxq+W#ck()b55gu-lu70S+y?&u?PXRpJjw8IrDPf z^6LmcnolLxR`7eB&nSbmrNv(}W#QZr3AC%3Bm{Z2*GvM!aA@& zR!u!knj-QTW=*AZ7Q zl&a*hI9(~ zJ$RyQe3is`S%AA*QCuIeBQR{|len|+8~H{XpHW>q&^}kv4wxUXA}1k zJ{$O($ zdx@zRjcqi&${`cGPWb^}gRhCL5uDj*Zi*)rYCSVvgBVlf7kxsbiK@7L)H`j$XDzQY z&Rmz{_39p3zWm!(I7R_5lCo{XPCbx{ZweyD0hXhZQ?j<<;tl@&wBm%QpVePFM zE0%Z?hKJiZJZ{`o`rXnn{!G$f^XFaWB-;6~=qHI+iN0Z|&M?MyS_@EeEZTf@#*}xj_?E&R%7e=(JDpk0ax?LuI9J#zSY=aYbXEkQRP!1e;1V{yDmRhwnLo7+-|WyT(b)ct2{ie^c>t4JGFHC zq^EcQ=O~?@*^MI{m(Q_z#V51mx_Db9bBDB7A&%+lu^Pu%Bb)isk%f?b%SZHaj1OC| ze5@asOQ^SM4;&oa8IL4lU|pVl=F4JdeGl%OOK%8%wul82vEAYhZdqCp>kb2AX-M2b zn|uqmu@#Td+b9+pZHBI8dwkkm+>AJpyFuNG%x5#KL5Ko0b|d54XX^65?NRUFu}{Fa zz~_1qGnX|Fd0Z-WoUWcCX9fUqM!ov_Uf9o)UQ6Y$!hzA@*>vew!UlJq^fpc0M70gL z$Sbb*3)cet@fMTbv~j;?>*Rd_u25*rB;;W0fX;pY%B4 zf+-Fu`;iywkln;>HKhIG1Nj9Er-Wu}M)w+vAL9=)Pi6LH?I(!chd+zvde*W|HRDch z`%=VtrYJ{Kde61Wsx3^@UFX`wNu}?X=qvFaG3`|U*WNS~svNW6al_Z8eTaZ{PS78v z-%Y@8)j!3zoeahIb|yi^leIs`9}L8aLmgs02Ghrfq{CX_H8Z;yk{3(ZmK@0xiHUjc8<+753O z{C1k0x7*buSfQ2p6n{{*?=*fa_tjYXqVn&FQcq}pTZ8SquM$UF_6%+02 zstDE@-V&1&?(D0Bj|pr2i?S_}Y9 zS#h%;R=R$3F9qhS_T5UCuh}j^cU#$A`o1Uj`F_)?&X@Np@oHD~R;;{^I+60Ek+pZN z+gfLtkMRew^~v7H9?@V#5v;F+X=TisSaD)cBDPmX*r4rY3Vl(|f0(IHn)CU-eAYR; z1dI=*UTa^VeNK40Ow~>&r(2Ij`t>;)BJIY%t&%hRA*G_)WiVfSm4h0>u?8gO(evCh8utwR9bq@Savcc-St2Q$6 z6f&XZu0L&7HZ4z_L7AeJlvh)x$~oB0ZkO#*4P9>jj;)M#N zs6Dv0Do^FmegE7<{Y9+9QWbB~8#jNyXRNq~PA*x?AM2Mxr_~OX=cD>Mq`s#(og{IJ zx7YR){6=-8_STb`+ZZyxFAbBS{5Qs_oc#eKq+jJ;kM?NRtOn~&d3Xyya+8hQ-GE2? z#aG+7+0mX%SA=i+nKv95&TzjkojNtn5?}d$W3@lZ0tk4&5N^I*?M!dl%d6kfpEPe# zX7FeF*UJiwlKH;&=|M+a9wo>8|2zJR>@uYXF}BGFW5f4nFt7EW%A!1P77y`H{jseN zl<%){pn?NliyzUw)U5|bvh8X9`_%aUx9i}|3E>CdYs^pXm*$|n;*lt3m*Nd-{EFKm z!m;M3K+3hQXI?8Fme~XF%;%2u2Y#+u`uNXFBHQ(s%+a5I~ ze})%K8S!nl+Dp-!vG9e1hL@-B)>Yu&R}Su|^v=I|^Zrk5rE)k+#hu^1?gxf!?d#WrNpi)t&kcuMPJ_ zpS?fV^N-|c@1bk>zxm>*F+LP?QQtF|3S&jz`B;k3_L|4Bfg7C0>`}03ntc|95Z+?+ z@3g*~&xJAQ;l~)%YmHxhPj-9#UPD}k({(v(=9lE1_xPWia*%(+-Q%wxOJ8-&{Y=MJ zezb4UTw?YRl#P1_oiE=nRiPdxo2&(9uF`vw>F>(E9%@HowFSy4e6EISON}wgp*?7n z`k?RWd!I_m)K@>y%PkL6pJc(&2k(daGTJHmrLY*SW3->JHvRo8?<$9WlQ*ByCZ?V7 z(*-B+^(A$7S2@1goS%L!sX-VAX5XuO@K*i$Jx-J-I6y|zgiQr&Saf>~bKt!@lU1Zy zxq9`Jb8S|h&+esxCtRb`oivL11Ee%FPKb}{o#>bBNAd~AwtxLleyVfL*SgLveleN8 zZ8PC*>HE~WibH`fE`;pgW`ZSg`pYkHQ#0=4x!zC zuEy2NvKSvGdd=tR7L4!ea!gddpe8uk?IDBuXhW-+#FpEn3@CAvQD@=KVQ^3p4-Zi9Jb$p=Y|epI-M4`8Kv{cv2?D8(2biO&Oc9brPEf8y>G4dDjZX&zXIwQN_OHXdTIDz<0|E#zcg!``|VyoB~$1n&X3RaIa^#7;cQ!sBlv85-(WuIF2-)r z#k|?twyjgKbR4->FiVWp9e)SAz30J%%FN#+)!(O*<|qoY&1Auo#g~QiFc+^`{R(V3 zM&Ib?(0MHr@6@?wd{EK^N*JrDbC z$Kl>KYL%liTg;NgRnwf1>Y`_jUDBT*KT{Ip4{Xjn_x3zaIha4^EjYqj8^q5kfuW}t zx7~hn_42PS7|jMv!B=_%_d^(nb9`3s!|Oa7$Ck)>FBIJ_E2m{VhCRC_&A6AhbIxu$ zo9SIEhXwHHI#k`HI&0=i-?!x>1))8#TXkYl%~9&>_>hcC4+xn)Zx(UwY$%@%mGkFS zICpgyX|(G&dB=B@MHu1e1y{{ogYxGf>2n*8WsH zI1}QSX271U93lNaQUqPZKSKmAZHs=-_|_Z>w`hewz-rcj8(7S5=DpXj-XZQvY1*oG z8l$Onq0$?$!7BW;rSKYzbHbs)4>n-_#8-UP7MSBINUe6C*+OK!jP>1a$r;AarR8kJ zSPFIKkjFk%4(-ERu@3rLRpuLT9Qg8!WM^p|hW&nZ$J`q0Om5i*+Lj%7MB~Zz9&_TA z9r})PHtvH(feFI317mYvCGow)i5fgM@KwD9amLMU;OQJ`g);--b|=hR_&k7H(nj>LVWv2B2C>S# z6FKFVcWE0OdM2(P`mis%!`ydRGgpgKyr0}sjTZa-m(?$Pia*F)S-Y*|r^Eh->+;Mv z?{_wH_gFtZkB3&rJ7+ql+OWsE5gwt%$+{xkwKgTD;Fz-EA5U7Rp!woAy@VoR7&f*J_K4o`Wd@=dMfL6+gxwMCT>DJ5Fn-%;M(uqs+U+wG4IS z>$aGU=EG~Y=dR}j{mvJT%l?blgF%o%;v-*(B^qDCbtI4QYS9_JcbKaTS0ujXneh|u z9x~1IYds1qlJk82;O6CPIhxL@ht|!VCPtIb@dp#~^TC$EQS-1IPo}eacQSlc%EO%# zPiBb~5g=x5%s#JLECu7lJ`W31I#+>cqL`_peR|3a^XJ^LeJ@5Lx7=ZSitKdm)1HI1 z2@RKfrx1;8BdL6NIo(how29mPzT|7)?y&j&#pK(Q*p~#vjZ1`e{h%XWU!5}oA7cxV z@uLtv_8QgMKzJFgF?`sQ>)FedSE>EX>P2dc&@MadHv+|hbG~@3?%losHiVCg*_-~D zSnqrFYShn{|Nl3ZBMbp(W8XeR)$hyYTb%cR9v1?uk@)*$hW<)+7L6B{#JuydO;c~C z9BQJ^BvUuetXqis~?%$SmZIqR6SxiD4f$bGIHD#9Pi^3#^f-@^H07Sfpk$bRBb2A?wRv3M1Z z<=gtuNX|k;BCHq4zrm>3w!kgSr8f^;EEB!wmmz~8Z7^Cc&K#ioe=NP*feZe9nVe}V zq?-K$uJ)r%p4N+VL?*Bw^m3a+Azd71#8Fe9Qr|kEY0El$YDar@AOG;rPN9%frw@Oy zJ${toT`wxjyF5_q1n+&PpK%B^PBedYuLai$1vr==o0A**MZ$IITi~1z<1^r`TIExc zx!AY&acyHS{%ARrc|Y6V=8O0Il_*AfV6AJ@pVWu`FfP7|M%`au=>_Y?rCU#;xhq_~ zbvHf@#O?IU(QA$xMfeNa>lm!y3upM`xt6QHwU6FoL(hCRm|_!A^5><0d^UfiAe)Ix zhEHZ}oAJ%~=<1K!+LOFdYjMBNnP;(AnZEQ@jt}-Lwa1^B&`gwnt64W#Q~e}tK})!g zFZ_vj|JPa3M>g59e4%t*1)FV*@=H@I6I*( zdY!~1JX1E}(0C^1V%=zAu8Gg)!MSt6Q9R`DJWE_R;Sd=#^t!pjajG_9gRT1eP@>3dtVbE>n&I>OQbEepUh8H{5i(K0~_hrE`T!SGBtA(d%HpQlHElSZuJxE9gyy3iK>9{6MBh(v<;>6C|oJ=iQZPGM;&aemP>?hEq=S8KK( zUaSu-Yc#p_^Bj_#Wz!xddQM}O=(O%D3)?VUVR)){a5b(M-=z^#tJbfYcbk>OVNHNA z;#;mLOY82AP5aZgKGv^flO-iw$_u3j@nMUEI^z@l3I7FY>3T87Wf9ClV=egS$LjGE0v|v}Z9(~7#L`_b5h<=+eDoDlaRAOH z?v3Ji!6Qu1gjL<$U9J=B)WoOSE!L+(Y1w~@e3i8{k-l@2Xj$kD!0--W6-GHBOwI zOla8H&3CNheeCR+l54fVluFY?@L0XN=t2oA$i;1UeW6`y*nM;CPtX+=wgWfHwI^_= z!o#OKeX++OW{&(C7IX2C3Z-H1-o7WF-1t-c!Bp=#Ax2!-UyD->)`n2=aCDpF)rfkV zN{_iwNk$Is&=n2Nd8=CJ-m)$7L@dFL%GRBF)}rHc2U}D31x_X1S3alQ%ct9k69UX3 zR2G=X0-QR$8zxrQZS!_eeBMv-2Z!;U*4iBXioMVt4c0rnu6BNuwDXfIe?t#|naEx? ziGxg^zh!gy=?%aJO{_$IyXi94=h7@2BrKMfaqwxE;2FXX_F9aW9k|e?gFk?DNZAt{ zOuSfP9!As$KE)s0-dAwO``}+i=_@qEJ%`xaFAh(!HokjsZi}l%gOIIunSKNw${dB= z&FjL|1e^78wLaserp;w-7>%(82HfnWX5x<;j^T+p?J@z6JLhbl`Dy}oS%E)m#sK-F&L3!@ zhKIAejgDnIP>Utmn_R#R!4efG(jMW5rI?V68|&5GGhO9Mk(??AFg)LktPcSf_>e|m7IO~=tc^a zXqf5^l@D$pvAed+GG~V zo)%ZMW+b#;)`-z7qwa*D!{PL;tcZVfHzW)+3{z z#|!PJ{dkvJZ%fBp88?6-u?H<5%VAmBV33AS^jHs;rSd5q0qdJIyryi^Zf*kfae3W5 zbf2xp0=&*>KLqjB=1j{&kdBB6I=7h(o~DUkN+!;Yj|=(x=&cVMnSQIamiw&IML2g# zY>hSt@zsu!goNj4xI_E&{4Srm{qtZrkbZl>C(2#WL_UGdyFKbE>GwIhn7Xojn^lC5 z@ds5$y0G%kYx#OR#zvxc;w({4-n{|q9WciRY{uXM{NL3JzZ`ZvxXSIywPtnH^|@X8 zI#8Uj5JXsLCk8Y7TBC);IdDr1Ag3(u-N*QY!ZW#^X;;%WrkPFuf>T&d45#CW@=My9 zGDspZ_rQltJkG_7ang%{m7ESy9CI@%&>sAozVKRc@4V6OuzWE;h;yX&1*7MGQ+2F0 zU!Up4uce>Z&HGC4&v<{zmdf8)x#4wz*D8HsJKM$h*xWsD=kTsrg;l<|pV#m^X*hB2 zCNR%eJv6Q14i1&~WYEz~G=Is?AbZ0H(;JU^V})PkC=GAccNxg{_iL5oi+6YR(oQ;X zOxs0gXZ7<4s-mAkms9*stUc4yN<5(J3Me&F=52V4K3+#Je$NAhlkae_> zWJuKb7B|Q6Y(J5G{~AC0mD=XrKKkpsy?%bi>+f=FPhsqWkkCBH&E`8 ziS?%Me_dqD%RpN`X$j9>^3LDq=+9(YJW1gYw4dx&y7uRiU+Jb(V}55Xr%&_1Wi*hW zp5ctMKf#ZY`_1hl)FSsF-;7b}p7VqFjg*lG`#P1|;67>(hccLUG+es8zR%uV zHeSx(#OPCbl??Cht8KVnh_(oFpU)-Q*Jv~7isXrMpgY0bqk7Xr1=Ib%>QcU7reCRy z@@Ldr(v|}0tEO2af%P)6ep%parthHfqKj`i&+zx4&tcN9O#SJ_ucoha6!prw@pJ!f z%D|b;8FDZ68?_7Tf}^?&1e)hysDI6tM~OK^1D3`|^O-Q!cq z?+Y4lx~5s1!kqnc`)7Sx->r_1n@ijuY+HSF2hmaT?eW6dz(wHNxpV9u@YAq?VL!q~ z-$d^(ByB5j2W-@xds@1r+eIjmC`?m9=>nO1aXaU$Pkx{*%spTIUE@?-xI|!do!MWy zoZ`#L=HBpeOf(6_!GqU@A&5MKv)OjpwctrA#-E8_R+K#l?5aR~IBZIuejl>H;4E;W zWV5pLf)4YD(`JwL!FiXq4du~B)%@Yq;oW7=+*ceXY=0(y;LAg zG)`t$)Ej+-{vsVnG}f^Df~_$gz(T}xI4@&qx|V~zlr{({wiIy{_uzg_bh%RKhg#X? z?6xGN9o&h|&~=56g4<@{y}>UL4oY~^mTY!G>_{Ii2W=tV!_6Jj|GB5Bb1*%ln``&r zfPiZ@OK8O1Sr@=`mycb#=Y8R|>PPVOgkLq=w^cuf%`56mru9=MGC||Acw54QGxLHp zWJ9fOtMl~t0v{{I*M$;+?%73KH>G||S!_5B`vN!=Sl7w6)19-oa%rM#+cTl?tKOQq(wwNtN+eb44^s)B3HZH$%Cyx)#t8^4D!e&0JF!s=GqrDrIykdfUaG?uB#3 z=Q<4MnAj5V*4&1ve8P=_BpIS`?KZ3*1EU z?Z5-84jRoR*UXoe4PUqd2Xfaq^*Z-;t#Dt*(ZM^wXI7lP0d2@D@Etf^We>ac!>%>q z8WHy-$J~G;z;v8%RcF1s*UE1f_MvbXF7K;Y;o(+O`I2-SK9tzs(#QAoZ!}%OoZa)_ z;r5Hu1hM153tf9(AXF>7vr>4Gg4Z-|pq-e*eidG!^GZ1`GuOl^TVSi7kpD3A6TZu@ zNy2@FV(|BtL5Ho?Bea)ZXMZ}5E}BVjZ5Eh&@cN-r1QNYv>G?dfhRqp+ec~Zn@zM1( z(^?CsGYj`RAH!DY+PTUm9oja}H}IJ7nAnMHFb?n!X^)}%s#uEPPP`_Dv&ykayeu!? zzVvq5EKHLj9QeaWVLtgmxpH@#oyRJa`V@b#KTXo#_pE!xBKwE#@zHozPlZr?ceF3* zW>h-hVRT-IQn zujlu^n?sK`H<=9TmFpJQ2Idm$Q~beAYJ`76s0xO|9wXH{KB~d?CAhF_tNSjM1)H>c zrD0-uOrNn4);8yC4LfOk1%?B@RswrYqv?1*V!x^u!pr?QX=ULNWAqv1+-?Y6OZd0K zL=A>jYlDOKmUFwulpbR0Vt(tmUwg=3>SC96fw7T#bLR8J7i~!6HL|M*htn(^?o=DS z|H^)03qN9y{YjlvoW#KZTA-rf=BgNvYlsZI@+E-n1qF?C<8ptsdD^mT?dx5h} z_&k1_H=1?10w5<){S<$2evb}4*Jfnarp7gP}q>SRVzRa5(8g=s7DEGJ8ArRh?Efn_AA3n{_I=ZC86(5+~`)6YcDE zsedOP?PHzmdhWw{u4-tF=JQjgPW9*Yucy` z_UYbpme`Fy$RG55;n+7-NA=yf5gqi#r|2kts}N^2SBuuYMPv5VemEC?UUe2U#|O^e z#?}&$ZBv^~&XeFJ5FKyzOLREC7e?1-n;2yJ8-aP*6B6??ziRGgqw8(Nd(IzUJbLHX zH}IMhO}@;fv`qlR!yn84+}}3%@h&pS+a|ojZ{c*`)F$v-h)4DyPID%(9OPf4V*6Mu z2Of_cd~VrzrHSl~lh@UwqqUYZxgSG;GdktP)+K*bb3fUEe%&7T)3z&{+dI8q^W3>~ zE;3I)5K^Syn`zcO^WVIAp8{Uu9=GgXv+(F&7xYI(3#%;|AK7P)TF^b-_tABKT>E{y zKjYchb#&pc`$2*N{~t)d@^486BR#v}wf6GzQD;~zc(9t>lBrxx9{Wyj#0 z_RX#Qwq1Uz0J4)9TM6}~=O6jk%P+V_+4;txwCuexoo#yks`eA3<~}g&*T-=K7pNR2 zJ~FY1NmCqU%yoZW``sqrfB4{wciVGG(P_{qR;s@Tm#|zIIpCNp112vkzqV`w~C;>mRPqy%wpxKhM4^ zRb_a$%U5~at}@Mf(IxBVdzYIZ3z8Va_B{Rmsjl^XPrdk)`qm%r@t?oJILJS(aoF*Q z$a#I)OU|tywCnumdHT$FhO`WR&hiSJB$2yl$Q&-so~lO&h^s>yoUD zXNkdXQ3m6rjpTE+#h24RKhb93Mc-#Aao0YSzOd7vbY1-V(=$gS&aLEI71|zGqF@?} z+Y%f6>RbcUK<9D{FM+sfiuI)!M=n~4?i_8uG5AyV`sy@#XSh`R$L?lVci?H#`_x2W zur!?y(G~gNI_a3RtLi1rwW)WU4tNv>=<~*3#ZH=#`@lB-JITL>p$6?LICnUc#{=0=k z+c_-kpty_RPQnek_Ha` z{RSMtXmFa?M&O3hf2Dm4Z_vaZ1Z%J=C&EK^_#QTV@WKw5w2P$++z_902fkZ}al#q* zgXK_tP(P{Q(>gE5#PKrNCKwd9tn8dKU5fTdiPxCEWzNCvJbQeu(BU+F34K@BgOevd zl`yGhYsE0%Hh~50LjI8rP3c=Rz5_056Wi}jy%fu6|CNId8vwH}`&5IVo$Uky^G0P$ ze<9zLLovNNHur|d=z2ZR?bor7_wwPq?OZDRdgOV!WU8#&Me3NgSe@xZ;Gb|)tC6X@ zoJVupR%EU@q8sa^?wul7qjY0qBVl#>#Tq{+`Gb7ABlmBXg0AnMzp(!qEYRiT$YDKF}%vmX0s#LV?0^4+9)I56lIVf*1wT7W&7pO_swrO7vs~+ z{B7(N8S?0GZL~zizc%p_6;~9W1rz_ystqQy$_68x(F$E(WJ@PD+^dE*+~)L52kly8 z66s~qK~7HLU7~SziRZaKPqEDt4{w71ZW{hzJenr{*S`5^tw%{ zRi?j{i$X>M;@&W?FmJ;3wL?W049Z>I!Djo-GveC0;t-x$t$S$qg(pd`Z-_>!BP~b{ zv+x~TllyAZzjay-^c9&G&g6Y=yVk4KyIPU-5bj)>ri#!#7vE(9iP8WMNsjt^6RCH`)XoDd87Az& zvN4+B)6rYP>16&@|Nallp*?}|!T^Lwo3f+W!Ag)N~4IjNa8d6gW)m$Kn`dTacti*O2G zz1yhPh9pf4P-+izaoPo`XH7A9lD7F39^5TsrB8mS&q)e-ECx zYF?tdW44v@UNKBS%?=u*!b7ngwHQxu)(qwz-Y@R`YUey-&rq!W+x$Vbhmzb1{j;0) zQOs4ugG+Q~^r;bR6xR%)L$F68JGcnvulO$vC$Dw2GEeTDeY$uy*#FCL2Ehi=bM<2< z4u~sd%icbm1jp4<wvSNg)#k-^rw;O-hjt=X;LYR8h?Ggbb#`GfCy z>TUNjXCC=F)&qrd`^kERFGdxg4E$r1}Fg zrp1|~q<1QA<^!C0(-}5WoK5P1%CHxGuJAuud&gIo{jXwosvY1!gCoH8PLKDQQZQRQ z&L`6zYo}HCPx*si*n{6Trfl>v_UzexqT3y>(vR%e#4~=bLmBqDg8>0fwQs*H$N5Ar z5R<<2c~uMIm%;c&(-|KO=AWsXtFb3}3~%c++Q=>JR`_gqcdd7|rv(SbPPY$Bdo{VI za#m^hfNvKVCr0)my$+A3oi1yc`iXkXzfSM=_}iM{pF`hchW)P2OeNTU)8uH-ss;l! z;-q%YJIe|!`=@rQ1|jlN3}4+?0be}&P;eWG#(TpKx4&A)Mkrs}g$jpJEY)|;k^C_- zxgJqH&T}5bq|5h7Nv&Ch!?U$XRd&+@>UxqEZQd1~`qKSoz8SJ(Ow%tIW+zf9NF9AnByMbJT~k(Dl?}w@=iUA@7Mx9hj0yeYsOy9wy&F>HKUbUqmb!k3fKP8 z#xG#=x&a(8-aI&joBLxEevxng>}2>*@>Np2Mmf6&q~WJd<=8>lgD=jUX?BFQ_5k;!0ne)iTtMZ5$23 zmRFf7`zp1^1U#*ZpA-L-m=_F&P91%Z)qir&UnxJ^eZ+j9P=5LJhAIkBgUCvgi zo+?J{aiia%u*B~(<0k1@{khMF0%TIIDHGfTNA_6Ttu8olSS3rpH&83m+OCR@HIdF^ZEQe-zhKe zc4XcTn|%f2mAS!NA72k!7!Eq*;xBxC&kVqy^Z)x=pRE6XcCEiJ%m3}YvE%6ivVG*i zIF}xLyE|_vgLq^5n0os9{rC7VfB4{k?|S8u-*d{(cGv44`S^!BQ}d=FSflx32q`bl zhWTxfIo8ap%Ky*nalh~T{J8f&T=&2E;OBjQ*1JCc`+L31^!+{Ne#*kS0H;kHHHXF`!1@~(UwtbmHrd&&)5KE3yb)B zJ<5=u`mr7v6Z9z-N(a8V`jo@h<;K8Ixd#{ebNPd^WBIlh8X!VpBJ$lA$H?EGk`v`a z`xh`7o$vLYe#GC=up*z4phIT2f%t3PzP-FU+-7{-%x`oJ=}BnKR+;qtC-4UYh7+gp zD0{2+js8Qn7>7J41~d6Hc~ZS{_A>R$_hmQI=fS{`*I*A$A`J8Y;(3`_5FQleRC)b9 zs`fhXw&Ayb0)LSD#SW%%@UC<1=S;n+?%of>1E#!`MPt?HbOwSZ#)B!V>1UT!{eX#` z^;Ex8Qn~+p{vdNB8Plyy{-{E|)k869$vgXOIC=h9cG%?g@~KLBx^`-X_#hFC4JK}) zUpwJ)T_|>I(fE44-7n{XqvBMUi*auE>*vqq55i+H`8M-^F;)_B;z|CZrUxRIcw;8Tlkv+R~RK1$f z)cQ^QL2UPG0}4TZMu#U~x_0Nc)AH`ZlM|+6gE^tsN8W{vkYDUWifbp_%3w38sj;iB ztJrh##kL#7R`QsCEnywv8>+n4pUxjNSUC$Z{b!U&8aq4r5pG5v^a!O~uTS4m{JVMA zw8I*10$O%v^L>_xx`%a^)~tbymM;JO3zO3cze##>9zB} zkv|wo7bC>iDiW8Bel6@k{6S%5(rq=mud(_z9o#4SnU=LbE=P%A_KudTXIc5DiMQBy z_}=jPtN@#|odp(q1{^KS67;+HgN*6!B}%+WX`xDgHU@_)hL9RKoB9hl=A#ozW%h~u zx;4Jt(2JSY@A=ejnpn(E8~Trl$>w?E@VQ+KZqoV9V|AWf+n4HLncDwG{$Q{-nK6F* zDg#)jxU@WoA`sY$E5DUMS)N2uE7ayf{V==*JyIOdypJE80|&U=gfj}f#%~H zzjbu&IQMaGEe)RQ^k~scIki&*J7gd{e?%7ECWgiooR@BR{=4{t+E|^R_@x`XzgS{i zW}cljws82@uGg6~lB3S~HUqPqT`?e1zi@3za2#J?yW)0Yt$Kygz6o>g=$2lu5a+1* zl`><;e{_Ere-I92$_>>eo^;2Mqe@2$Ejym78dwNzkXE)vm^#a6$M8i_J zfp_7YA^pMhK-!4n2J)D|B}{pn6!!K9nq}d^=lFwKr%B8nUx@{ewNJJ<`qZHn#i%xJ zGiQ=-;uueZbz&I9_wBfDCl*id>lklJV|YW-7z#XyaYY`PpEty5siBD)?xXiQ(b(bj z-dlU@+wZI&(u<5wKFA+b*YV3?&Tyt&?6VVrY9(_c4l0=coN+$J_p5QOoeIP1an?Sh zM;Gw6an!k{FP(549LLEIu8)V6gO4iTb%Kh5HNpRA$zu52#7o{QjDGle&$tMKgU~+V zQP!I@Af!R4G!w_@GEE07JGsNNq1D={SbeUvykuqU^ar3 zh5ar3DmBu!)jJ6@Wq$`(miY>Q9p@6wRwCOI8vnErSo*aP**z?9GU6b<2q3osqxCk- zTj+7FAN}LAMUO29%ExFnx(hg7H?^c3Hz?|q6&#xH(0;$pAJn+e*~09_wJ)b_IO9c} zvbAci&g7kWM{$_P__9@N#4*hb>jY2i*E{!BF}-QJ!|C*%18bHxFnF`(rkv`T{3&MN zqCB`(Zfb1Wqz*1fd#vw_7cku%ZTd<6pecvWmyzIhsPn4)597(+Gipzg+4B-jh}E6- zp*oQdoNL9}1m}#6IGvs{)kwLV4bv8fSFY6asAtVfp5fE8_$eOet2H`x`VaYDJhSKi zBWr`Jm#TMrkog>cQ0FoXEQ%$e^S9|<(n|X7Z;8k@l65B0*kl$RX8TUJAKy{OqlU`5 z!gVjStsBfmc$gJ>?sJ3VwKO~>%EL}D7jd(>!*w3+IZbQ}p-pNyTio;5;qVI$L^$87 zLwtfis56o|*R98)xrppRV5dCcYgy+pFKkA2fCniug`nwlV*l zi#G7d?Y3e&9M;7NW~uqXzk^oTVXwT<#Iap$!UkOEUXskiY3U9M_xWA?L2L*d_;zkm%#yo_vtG7@8?txF#e{=^>6q{Q7XF~@P-a5= zYLFl0$sdz}H(v1OsJ-z5fjcTk?wC0hcgId|x=;DI%>zx?5}Sm-mE$+@2ep)#6#U8O zqdn#+`RM$yFTKm9&kyZOwipZ)R{dQx7I@}wo?@t?1JHftXc!8)x%@W%purm{#*cO| zg`ymn)rCFBR|3EJZWDu_KRiY48-s()!*@VZT>CJUxomH+QDd=*PihvkElt&`~#BkM|elx4pNm-CTfzry$sHnqVg zz)!z{KN$K$e^O&m4mA%sFy(mX#mrS|3zE_6I5j-o-D;W}M4A$r8TY3LZfB1|ey70{xM<|2Oa&CML;;I1r8cdn> zyZ`_BgJ#def5JYtCq2IQa9Ynz75z2-Gy6{3lyX?kPLHp0n9u$iWl%0nd$49^;C4+9 zdgwK4DCPJowZ~UE)E@70_-BK^Rylsu{mW|a_4wIFf5CnQk79~r)AT~W@-e!L)!6PN&cQYUMB-p+M;F)<=5Km)H{sSNWaeT=ORWMB?-r|3NTkaq#4O$$3y` z3*`qaTHLv4bUTf7$8HhrqSB~d$Yb{{^y0}>8J}%3U?%Ov+`@b|>mFLG-7`DSxg9h)E%2Bc?Nr-Ow^_U{W7hBD4{{Jh+s2{pg)7Vd5q{3GKAhiXLwJly{NKSf;m>)}w**hi zO7qd+QC%-PFA)0v<2%^9!Lr;nzx!?cLE1rn!i4y6+JVLGb};&m z;L5hSOPlNbF8-hhGw@~Rn59&=J}yarP^=ua3HD#Gk!Q!w-c~^lQ{vCT zQE>Ozconw{{B5=Gl3#dYGw0IowNB5V`&c#MsWgT8{x1GtjQEM*6(O`-)py`5f^mW& zkY6~Rt37RD_c!y7Cso+t<+g&qMtrn;n(x5p)c65k=C_`=YYh|SCB6fk$&9Tj^xOD@ z%t@2!3cXpQ{YhSmb=Oj?J7OccHrPzHc5_4R!l2!}bRaj*o2_hr>+~+Y!s!XLtay-y z$6D;7KemSBwTC;=Bfed5zqCKdAH+}4XqIbz71z8R50ZEFCFZBNY}ngWX9K4TO|=l5 zW^ZOrd|Z9=`CsOm`ovhqY`rVT?W9S|xGR+;+<1mtj>HKNEZ` zb6_9F&W^^+hxmi63GyidgJF>nT%a{g3$FB`>&e`qJ^?c(&*(8LzNY3%gXUx zqN1_wG5{V07F7}kg>Q0Pc-jOQZF_2u-ElqYrqI?tJdPOO!U=E>#aU#Y0<-!Qe^5L- z`Bc%jX%C9P*}!iP<5MyNYo(tP4-LNq!{xN9CZ?-5C$gy3@5LMV@_-P!ul8eIvyF!3 z`q1~h%h1QsHW(C2==Q<8L(qqA2A)>J&Z5{@m(j=ggQn_f1XB*J+lu8xteUNK%;Bpo zdoFDtuDs^b-lg3P%x>cRq{^;qH45SB_GvHr{d(m&N~}Zl8P*K20AYjRe{gcB_lM)Y z(1rB&^r_TMaSG9gM4K}{{uqDI?Ah=u#12iOU-|owAi4?FQvxke69W=I46A<6c#U4I zQ%r>dS$DOr-ZBkOF*%8;wwg8|9wgDBwHJ!1ro4lH#QWZ>L_f<7;14@5o8qtc^u5Un zzUN#VqYv^21C)XN9&I6CJ^iCB6ezh&-k4vQmsp$OTo+ff)wVV&l+^E@S-VE8L)qVh z*VU%5dD!!Qd`16m^<(_Ow`Syn!ys<~ae7(OsBL30TpQ)fr ziKIefeBG7T39U~wcYuLpmAA6Ebk`eUgxz~U3y7b|B|?D83K zxDW9MO`kAzqI%JZ#wkPMj_#(><~bZXCfBJ~>>j!o;G0h+Lf_nLNw3y)Nu{Pu=be3Xk@s^D+LQ@gu$L z&|IQe2CdU&pJ{VOPv2J$Tl-1fKki&|j&(UDv9Cl-XrfokkCOf2C{f5Q%-Bu;qAnGi z8_-_GTNh~GSo0m5SMmy5ed%`d-5IWtuZ?rFFZi4ML6z5HtTp2<_2J(hR^7t*o^D`V`Kbkna=5r+X>p-PUU`7 zA5nV{Myq;K`E#0E%;D9MXLD#btmAKor-ttw3*qaS(li3gqQERQFG-sCTrjkY7Lh2wI{@Fs2)5{ z5mVk@xQy%>-`4eRp>!&5AB~mWAa(;SnrAj`@Pn>6MGGK>&+rGm_C)DaFQ%{1UZmN; zIldg(M<3OiMW=eLx>7&#`IdI%Y)}x5pk8B=O}x0EqsVMnb~@|8^t?EsZ2p?oNRIP~JPVm%Vs9nlHE z7xWy|9mBDm$Q)ymFd>84=}UD8?E3ZDy!bu;WCqi}Fu`}(-!_S}#zDJkmV3Th(pQQd z*ipe5ERqv|+y+4D)Pt!@y^+uVcK)Dl!|VS4de8b(Ppg&j)|6Sr`4w~4b%B4-Rfu)% z*bY%#PXrC<6LC)`)n;sa@gRBcZ|4sR7kp!bvPtLIby7Zg)x+D4_qkrb9_A$bWGqlj z0L$Gjd)sF*;&vGvx?Qfl?BEuBgFpCdJ;;=QIbL<8YbNI8^~d+Q-}2>oB%j^f#cTB9 z5oy><`GUd^UVXvbtl!BWe3$dTJR7atU+d}JH)Y5By*fAh%aq?)TN}U0mllKDtg(-Q z{WT}O>sar8+pqKAa=gp-YkA*4Bzu0j{;y@J8GfDP9+$jb<6O#TVSriJu|ClE{+Ijl zQ~$qw=liGr*0X-+{agC(U%&sCzcHU`jrnt!4_U?uLmYEy4X2a!0?wH&QxKP_pP%>t zlwF^G|JM8Y=Ntd-3G<$%xsd0dbr>(qI`U_Z)VL3S4UU?5qyDa#4)IY#K6r!7oZ?!E zBUZu=Gp};4cr|@5ZR$7j2Wca(Iq8Sv$b3)v%({gSD3J-6sZ@t!MUinN6 zE!YR^N(NzK?0Bfm9=DLs`M<&+RAJ0R^LWU#eeLPhM=7s)*137D>#w)}@H~ZMfjK`z z^bf@(n!I2IZ>?kS&ewWd_42A4`q9VvgO&=&&zo|YeyW1fU)3&nY+FUz7keUOtJ;?8 zPyJcEHeqcEE~M>M>o%U}+WLd)gM)ROzC-Qu8~j0yg+Do@v8P3`OjBXqs|CF&uPIw< ze=N7ov!wD3wkmmlbrjk(D#Md?S*30cDRnMOhrM8wJT#11d``!g_=DV21}oDyyauDS z@D|%>Q^9R3gw9|H+SB&ZS|=Yy2N4bxdVXjPf}Nq+DU8Iq;}b2*$6a*Nh3aj258YbM z{o3lszQ!Lk4WE8%rQ~}^s$G^15Ih%8eyHn=mV|8^~;& zkD)u zG4eh}0^kRfH^T0EjM%BL1Z;2%#&2!%=a{w?QC`c$OEa~M&EQhKxYMb?cQm{~_*DsP zke=#?`Gc}UYlQdugZA@2^1;^d-qw9X)3rnHM^n}eU=!M?l*d_}&Gzq!K+L4X!~ zleQB8x0S9ayicRK7*2p|MWv5;d9F2#Bz zrT!+~$w&Evf326aW_yqS>e6WV3{PkddYHH{5Y>g@J~n6&_5UPp76Rn&iI1-2jK4_cawyn}jSZZdP2 zX2h?}f_Q+MD(?a3 z1+(g0;NyHY|KMxQZQ2t3gQ-Gm5t?vfCM>5d&0@E`Zr&Ax;P$DXMEzjTgN^bC9!}Ld zqzbZSYp_dkxRl#2+hso#X%FeU?MOX%SXRz(YHRXIV+-TeQ#cdzH@rIX4!YSU*nkaR z>`u14Y}@FkK8p)*1#GHzKgS<5eM9T+D0#D~2XR?K#6&SpC1y8wUC=zH*ojtmTn{Az zvBIVS_6b)wcWCu)sY_Uzp{c;NzqP58XA(?SSZx(OOX(+0mQHp;yPPu?U*Jy_htKr^ zyTCf#%ldQtL9=WM`nTiB*E%t$v_Xy2U5;eN}N9gi&>hC2M|82gB0SJf<3V za@m1TO9xfhW_EsWZ*sFlr_`y=PWM&rKz`01daB@7!7lYioqUi#NbWWaVGS)?WRu3- zkPnSz?shLG4AQTaz0~>xOy57xA;V=~SE) zS`ow?%zKPge#RSc&IDNWY?0jM(vM6cf!^o?L4#S&mI`Zx{Fpc zyzt|{y0?z#3>qw*w#V2DjtCyg`1Tq8An}J(!OK^G9r)6@hwM2lHgSO%bjLI~wUs{_ z?x47xorYB(r9<0A?{He&&ZTfYfwpM!y1XQuG`U{kHwxoaj@O4`NH&Aovt7&)YnHU# zMdguhl84dGIGtqkv6>V<#ve3&TXtZB@<(jduE5f_!x*;6r{JrXQ_i#=?vzW`s8vZl z>g7|c8n#ZSM}hZE(S@zErlGBIDKP@2Sd z+uHn&_Ba0XoBQ0^+2WZQu+y*l57k0xy&io1NcuaQ!W(gci*$mzZj0yB% zr;EN-Z|~d1`k}GycG%OhR)K2=UVt64*EV*1i9bkx_*b0Etmh{)@>42bBBe8JiE`0L z)K7Tr+}q6>&Yk=fneb+BIl81~2uxJF{FQhgW~ArjL7f@9K~a8x{=v5m)W@&;#$Boy zqD*Qav?1ElhG_w~#_7V{!j7vGEEEc%`8~Mu56QoKb7B)`J?K&gSCwD&fz3Q~_6`1^ z+R@vO{%Tu6>zYxUGI&!LY}T|9wJVwoSd_GDNp~PG$jxJr^=nnRf2(`LM)ovUwjb&c0vAJ#h@*6{0xw4Pn! zOrOM*(&qGj>V^KHG1xo)`TW5cTD#Mow@zRw=jBg$P2*Zy|0xF;&cE29bq@#Y7i{v* zb^4D#gheg)+<5IXRoY+dc%A>_ZBPL{JAT@g^ec3jb)09IdHo0c^J-V7GH6fWYd&!? z)Hl3qe}D}t;?o@-DD+=;sBd`n@dxz}A9Kf&1X(Qfy~D%*jU9hfbzsNQ4&a}Dt*sC&uYDo5O>rF~Zpw!*d0JeLFA^Mm}<{$lSM&JUxv%xzW9 z4`cCS_E;kGpXW|#sytbkGBd&q;SWopJ>pB{HP=NcGRM!5>V z#2=*mek+8tG(?Wd5ZffEbjmx3|ATw3^2N#RM*MiA?{)&h7y9fzs_0pg&kubQgE{1h zlb3B^S#ALx*t^kG1a|}L{1$&Omc-60oW-48zu9%KV1;GjQnSzk;vE zedQ5oldn&{Q?$n-&116eC?_6%?JRgKIBo-Mu*0*oQg@Z>BM`AFtH3F_vaicT_)hXp zyPXhz`xX9RsZ=_lfr`Ibc^&BstG(JbIfvAb6Y%g7g;~8l&m62-ve2r|>$Ah{LGCr- zpP2+WAspd#KDvyLCi#-@?zfEo6no29TI0pH_=E7ggwv`ms4nQ68H?^)q?~B2MXG2T zXQhdJcoYNI^rqaY#+QZQu)n>}_SlWB^rcQZGo7CL!>gNfpH1u0$y(>-Gkr`YE}zUl zNc;#c0Zq4Ne&ruMo9UPPcw4$@cwVk@pC<5)!pT++QMXfbVL~*=s8QcKXse*nCoRiv zbaYuIBi3cMsFdRY)er3|Ijq&^qiN4Jz8{_d8 zvf#@u6Oo3eJt|$x0s5lw3_r#n#17(%j2%DoG&X=w#S5X>BdxKu!dPnX*}|<|pv{l7 z&vd6~RZgX8eVhTS-CS4Il-tq%ySl_L(l$Itqoarqe%ioIM z_CCiSlutUB#tve)S}7BX1ZIf8IXVI}ru^g_l>RjNEYayJm$nPI*u`hMQI6-QrJG}y z_shVgHtMlMPtHwS@%U;JuyVt7d_KeIx{@bSoUSZBcxjC)4_P)!7(YvR+QQ$?Kgc@A zuec;{&ZcAVrTibx)q=OS;t)D;GaJ==Y8~xG{n8K(-P)PtW$C{*&pR9*#WgyYF5F=1 zg1mduv+M|udfj(%A>Cfvv>|ctJgiOJRk(S@@yGas>eG~4W1!c+m76mb>_yYm!Mcyu zF7tM!wz}QMz3S{3?QQ4hWhd}x_hX@52p>ptu3UYE!xc>rupHrnramaA>L8m1FANXx ztv9(oe`XciPfp176AeYX|1ticuqYWKT#8`}TTI@*<0BJu+kI^CbdWcV_M%m}jhf@x z;;_i0O;9O^{h^rQZ*?~PYrD#r)udg~W;z$fXM6Nm7n}2Wpz`R1E5Z*=-%n6y03W3~ zSJ|lx+DjFjUv-k4ZIcm`Yxm~VOOsgv{Vv1xWX&Z^FuT+9JS(inzrTIUClL&&0Rj@@jCx*{z2jo)vOeQVfu&R53$=Qv{LMa^7d*@ z-r(2V2i8m;>3N~pDw6JXw@r-3)}(!c13YK7MESux$sLOC7p`-4i64}?k@yQYjvic; zJZ#YweW^j52J6RSPg=bn;}3c|F{ZEoHII99dw~5~+;1gDSAS+&+x61>Qgw3OE!*c) zoScm{Voz*uj7WhC*0B9LL0j}zIPRi_(8v$tHh}co{^FLLL}5Gd;w5yy^bn_q-`R5d z3I3qx7h`{vdyQAJK@V~yn;(o3?`&{f&sOuhW{iVtyA=01a9u~c5PNa};OHJv1>jC2)4))OmkneCjtQ^|Q+7X6*;gXAZhJ*uXAziGly}>0|!3PQ&ri zvEhG~TiuPv4+B^G7=O@|&nuU~oz+)(pgjSW&Y|&G7l_&Lv!~^XS&L~bfak@W>=n;E zn{)ZlDK8qRy;|HUmp}>JQAL*w=%GJ7pLfq@E`5wYNHIBxVKBw^y}6vS#j26ROYIF? zwk9`>Y0rMRv7M;j=H41krqN0S4{*9R*Hp|4IBas|%h#gG-Lz`AYnVW;GE-MgnPYqP zBRuC*{6X&VmXewn8PostLfTZiXqiuo6%&cAyE$oVl*rb@bj{lw`cjpxA=qLI0AFnqZr$gebRCApTUy4!eo%d zz$S1RZnHFXpZ8w$bei?s;eD|ef28YSJ3C>_S${e;vB3S)6O&v?@Eex%muzW8>K&T+;G38bE7w>Imzsy zRqwyvuXp|HogX{iu>ktQS6?^Z?X@*Cy?Eu+RqgGy$7de3e1WIinlaWfZfh*mfi3Kr zeOv2g8<*bgmeYT+MQ{Jq@v0Afo%)7({$=da6zMlQ0bX2Vz_LuN6SnYvVK_^2znXE5 z`>nMB_n9Yw)H3#|N zKORiEnMeKJdVqBT+Ekctd;zZl{*+y>-*&y9U+?*QPl_X}z1EOgqP*uyJ?o+MfSD(G z=6)N>lzE>_0>c>|S&v~8nv3SWsuNRp#0X38;XC|6+KqmgIh>o#|7u6Cht`UJaRzBC zv@hjd(=~LD)ZgLTNr%&tt=tc_!5^PSig-@0Z@@6&od49=sn zP`(g8BRX*|r#Q{m5elMz?6oU$Son!S|cKBhB4yf{6ViVsEwGW z|FZ{{ZI&uWIS*QDH=OFebLcW_|4eX;{!A~)7$jRg&L^By#m>LlBp*=Q`~rWFUt!!} zKBsVIU!wkEfwhU7Y4SG6zY_La1ZwVcXv~ZX!|SLrxTf=itH1nkPD%1>bcWM{i{T@OixZoa!l6@qO%2o8n%3dKxC4U;UFdO5{(q6u9z5tHW z*Z70tC#QVL{W7+0ID7m(l*{B9gimp%-1vT_<468D!__gq;7ZLA{^qX1qk1{;#3-LB zh>HZih98a`ZH6<6&-g?9!GOt$!i`4L&g-ihGijS@vl?eZbKYS{Mp2bIcv&yHdu+_I<7PLwpJmyhRSgXCQTlyP9Q^l2pb}=Q~^%Lhxmh@ ze_F-mLAlBQ$ULB!ebX-xQS_gd%CU*Irl-fLdq^F?DU~j2+pXVMiJ09U7sOq|cPG2b z;LX%Wgxp1Se5(PtUj1~yqxk2=S--L@Z6|OVzWlHSIP{hr_t4cegNPs8{r$0@2U)zSt%^yr+)5m zz52J_de_`5*1VtN55C5I%||BI-Lxeizh~kw!1;ERnL3DYpF6Y%>53ZvVnw=~=T;?= z3p^&rhn<+#_w|$?idrmOQ~pkTk6?(WmVsuYu|52r=kn3Ev$xbCc3KwhAL9?2 z`B-b|kn$B_1a>L!E;tV3tMBsY-3>-7JbaC=O$P3)$*WoEil5y+JF!)w({)45GA5S-Qe>joCbP6%D)@J`$9N?43ACGS5CfUSaN*=IexDX1FBCLGo zUZJ1tmh0u*nRc$m{%;<-|2#A&$qv)s=_6dMhqqVqKq_tlA9;oRh~WR=oA}>p|L4Y` z*|rmbRuMh8lJFe->2OyMT`-UJZ5_?*>_gz{#)(4-`9i%?0x6vaI0%lq<`GCe2hORT|4?Y_h0)< z?9lonm1VJ!BImE_f<6(@{E$B_X7-`s+_0leoQ_>P-RL*ZKD?IZIyuJ?f@Y{|G&z}L z$mPX7mv%6IcYN)|3HC8(8tu`k(O7gZi_h@~Q_|)m4$0`EP$z0*G2h@CW>0E#z{z8I zFI-dWRO=ja8mBGX!NTO2j08rpMg*L!-;Ji{o5UG>U;(}noKO$swnR%&xPg08-=34# zPr8r7)P_&hhp?VaasD~}p!7J6@D5`y)nXBEwS@y|x9OwOpia=AEA>$YhF#+eP;=BScC%+%|(7x;e zc9u9fi+bc(cLn4?=-7k8OU+BiS|h~+BKTH-Qt2Iq`YrbYL;h}acmx^>|?lwV2ILw z?b2_^t@<(kpvkMGJ(abm^-Rd=;79_)a>b6!QkykpNyquDxH z_OW?qOnc6}e6QW9xyP>fvzHlpBJHb_x+V*$#w9%|IGszw zpe>p6t-(FQ@!i8`RsE&&GVG%L%Xrlgud~c1qZry+k<+6e9zu@%S+_!bQxK* zEvFMiuVF%tVY_-`XeLIcj6QhNaS!5Y51mYvHK$#-+nYSP0QHaY2UP{e&!%TB4$Xm& z%#6imp#^2dH;$Fty~-*#oZg6~sGUZ!TdrC0r<48TBAlEt(bL!XgUpTcn=w~1RsMDOtx~XG>qo}7eMk5c5AmWr4k3PMbgb9eK`no4 zuOjm~xn8});8$=}$%||*d@cW=Su>h>9^cNkrC46`TnV?!lmr*L!DECWz^_@rf3g{h zNTb#&Jko(BGx{y@=seLDjb5+$mfy`EG`PCPV;!$CYY9otbb~H!eDky^x8ZVn{nl$+ z_OrO{j90^FXH=ms$k7YG5JP3N+pT*29nAfE{6WfZX>QZA!DDWhgS!ziLoOm0-DKx6!2T>=T~xy{vk)sSEZz;+@@WLN5{!%9&0?(IdZ&y z=};WVJ2$(=P3@1s5?=S0LTD_l;h!^{Mb;(;7gXcXo*rLn$QSD^i>*jK-My6a%}6|6 z8>JqDT5NhQ{egE zIL!B|Jo=nz8^XY4n~%Mc(fZ*Jl-tB$;zJDu&^h%rBR-;#+e>oK<2jl{evIl4;uf1?9lzdj-R!y>95Au z$luI-ohuI6p0`JEKr*DjXu5510DQe*I{3N*lwCelX+J8SJbrq*X?#ZFQHgUG0QUsv zNux_<>;ivq#aa6lf6&x{#!b_3yzvGbEOLzaQmT(YuDBc=lII99?ebUi5SD|+zuRcS z;Z%7BM*oytKt}Hp|07gE)=vH|@9DC`Dm>d`e8u?0j20&RD#yjY2L|ym{-9~2vO}0M zhiPBLPZ>^#uUuMAz>4v0X3(8ogDpjL568}`kA{@tu*qL1KXwKzO}j$X54vP=7Q@cy zktq}$S6Zaws+)l$No+aypn?71DDYQ5#ve5Gp+08fa$k6-Vnlq2{3CK{-pE-e{AvBx zc%|I(U(=qzZ7+{XY?~;rZKqN3bY8`a42;mgWZa!$)0#S|bjS}B98`AcQ*$1aPs|1z zw2_peEqi`wK0l2A^{&c#kcPH%~dF|GlWa7ZYk)KU_ zYdj~!EA`ln^zcE$QA^*8ldIDKAFR5Y;`qKUmM*KN|JcghKgJ(4G3#b*^7*x2lFyod zazS!2ci;?mXy59;()|^Vpgs&fcx}x?X;8n%%5LL#CO*6fR9FllCEAan{W_n=X@Bjw z(>g~Vt3qXb?X`zj{M+REB2OGR2%nKg=cn=yYM#gqX-sNg%zxXK)~|t7p~QG1jpj_l z8)Jy4NV|-k75Hn3La&;ytP^uILT!SOqryJmhA8kmyV)-z*XeE5IzMt(zE^ADP`FpC zEE1g|dX``YO|%D_Gsoo~e2PDa9r_)wO=+Fyt-&X^xcad;*wU)SuN=uav~G~qoR%LbYE&>)odYc}E1w%{T}>yLG{b!k0A*h@P*z(1OF9d`k5 zvb*^he^B$Esf!l<+;Bbu(R?m^YbPRROoUs_Jlq&h)4hE%z1KW3A@>!&wI*%Cis!Gj z#XZq7c@o9D17|W^$L9gOojId(z;{&~z}X=VLwr2d1w2Dx2k5eTFiyjDx^%tv zwZM*jk#@FyW-fDb^(~dV56&n0qF`&nte(N%=lFx(T8i~yT5Zd3!SPyl7(0o*Ktubw zY($ZWJP&8#$1pl815eePr{fLHT6}8J$)Hwumkr__vQhd8c?Ze;=y7Plnb!^0TsThF z@H$OyQLt%GD-}L5c<3fN{~Ui%bwKRumT}68`KsaC5#4P1w(?3B&}~cQgSJNhhqq=lJ(0`0_bcu5EXMCw_su3?t9^ee~Eo+SFtlkghw*CB})+a`zw3wYnD?6e5n!@_f;Jh$?N{i2Mw})C+k3MLANr&&By8^K9aNPF?NmUR)}I z4$IdxdA!`i#5G(zawxh7@rB2x9+VgI@AC)oZ)izE`?5S7J>j3GyOAMITE&PJ$SXYJ)ZU5UkarMSv=S)QF|`qHHQ#9^p^D9@|%LS9%q)<;hIPvnpBrbe=LSaw#Edm@`D4sF&$V0fbrTE4;Yl%&IE9b?9!|FLmt zy-s`b`Hk+Td8>4hrP1jthKBQ5?KEkg{r+0Gbn2o3n=Zs!r`9}G3DvIo;PSzn%X%+C zT)s$eSErC$_r4yv4pJe|R)E ziSmw(urEcoR58SiyV_eDZWO1ATTdCy7-GH2@nLji^cA6C zj!^Hxbk(2UtK=Ai47IpD)`um6f>UA}s?}a-usi2$d+7wb`Q<*Cn+8vvX3NRg>qllY z1t(bAo8*q1kRQuG=*1ONIuo-*Ke2RcwH?uoU@dQ+kaXk?+&gTo`HCecV?|e|O-i}z zgcrysjWe1d3vT1Oa_VIV(HLv>>%E-IRhRbo^w==M2}hKV{doYBlJnYrevUu*YI`QW z&)7phq5ikjDMja@F(44gSsteY9?CM|(gzH7f!3f`xErXBrzg00>>g2nJJLdv_ZIC= z$3aFjY7JYnwg@>K;uv|Hy^rw+RaOrVpc2%kbYPojgU@f}l#fe12jWOg`;K1I2iCZ{ zpO7=3;?r$}5pu42nb`Ho>WsQ_=drBEM}yd7IbW0aQuQFLV8Huq1_ymkoWc+B2Ngf2 zc~E8d9@ygT%e^*dID^=wF^x7A8WnV3=@+J57#u{WhC|nV-Zo7Wmw$>qj&|E0IR?Yo zdU#b3-T`rnI??k1u9sd?O+0^%KZpgdI`auzRY`t1(9S-f0||yqvCht=7TH>%%lVYN z)2_~ke4*g4Rh3gz?MdY}6~h-`i!sjzq*JHV&zR$lb-th9*Z;Hhdp@8U9T$?*x|u}4U`>RR3gfzZ@FDv z_l~de2Y=VZfE5qJ^jJI)%zGcc#xMn;mzF|2;W_SKJn@U zX43kd`3Jo@k>BP}*?;Yix+b0t^NTm;nKI+I%AMg2KDbW&EdD%=iKg%xx0UZ+>mdHo z-*o6VUj6VVuEG4_ga7=}&wp%q+h(5eeVMr>W;B8*5O$D@W}O0y;@+D&5hqGqC=;j6 z*oQrE4*iza58{KF^@CSv>gVToJ~>|L+x1(&eCN;anBO0o3E%iByuE(N%^VqsEwCuf zIaGyNPxCf!ZJ;m2bhEZr%&<9rzEiK>cD>wRQ~u7YejrpY9h)XsAsKn zIV_78@3lX=sB4Q(U)r1c@Yb8WNq^@dzM8&EHmR#9zFyzOIo~B-E_94HWxvq7X)-U)HkIvIg-SwLH$ZzbGS>@J4dr!0fr2LfI z|CRiM!i2ng=^0{dFl$J&$JrYHMEJ!URNNd~)Zy;A-clcCnf$u#aXYZ2e4P?Y;ixq+WOcOknSnAWTcG>-?0GS zpb>RDamt7$YTLz^TT$5?#K_ApCj5{(!xp0f_%Z$I7UFTiWZQc!kGg$M0q`5%`<@@iY*O7ZVk_K={e~Lf&T9;85t)TcUjFDO|q5rsZj6YHLaV=Z$MLXxd`Q1(; z>9iY_e6TjlmU8=6B^^05(^ujFR3Fq49Kv;a4aO@B1zQl8i`U82P}+xl*O!Kq#tmdN zFa83Gnc#Hdem3}>Ky%w{Kg>Sbv=!d=ZytV2a|8Gzhaat7>O7oEhQ$m6rUZvwMR)S3%3k21m*Z z2Udgr;{^!6j;HBkW;ppW+W%Dm!a6<9DZj z@V|0)2`gqCg%e1O%Q`VY^Of4ktRV!VET5@J{Y?2AF?6 z2RqqR9&T{>SSO3;B1L`gv$q+KpY(eSoDAA8=Sap75Q( zW*7_XM|aKlT+pe7kM<1GhQ#lJiwE8b#z4EGEu!1`DgL0x@6i~DW(R%c{OBaG1AMU3 zy*rt7ymw7@tE1H*I%DkWcZRWgY<|z=C{ueft7P`c@ey2u`<*54BMz#Ly?eUn8xP72 z_fh>uy1W48)D`{P?tA#5u-(h&_=A+)tO2Rp>Z$ZVW1aDmoTB7qCO)T z5d%MOEN-alUVB&Ya&V_;$LUlnZU&6z8QmIeymRSZiO)KwQc${gvsSges*da6S#xl> z;!1VkJgZ|T8x>y5=RU?C1p8p?x+QnwHLbauF^TnrFlV^^Xg%(b+Rh~VIp(xV{+LYL z%?P+{Hp_jd{ku=JMhDf$hW5X?oZ)fK#5TDy`08tzxti!j`K-RuA5Fxoq2KN_&AarCpz`X`Up zh59<{QMWRUljt>+JMI$s#lvYN68Zmu)jXPp+@UVE-uG!MujE=?Hpg9=?_`42Yx)A}lVr_tATQx_hJJF@UR^5oI#`9@*7+2F5Pcr@ zNZNmzxG1fyLdqdXU)fD&`Cc_#4!6qIZP6%CSWFhtU?^Hqf5va=_QZUVLTj1|UN>lo zh6=q33SPo^K>$ubw??4fwAeRN3t`e15bYYRWH z*PF*9b6D7I5;t&(0U_OCipgvTwzFW_##mo2Q=gsb#|#WdC2~BB^T@qj-<;++=eMle4IZccI35S>@Flov}v3nY4IW*{+f!Dku?2s*p zPFZE>kL)#)?lW>^y`?vsamsv9;{i>Pe{?Unr19E2{^R^XvxZWY8Qz9CQLIVO=(EgT z;O(3?b^1^L$HN1>xPEs%Jv_0+ED4PM#y`FEKjqUsXFd9=4|hp_UlQ14{w}QJ&p6O8 zqoA^bwO`5SW-Rto+mq+F;NqWh7`#u#)$&qURBQ9>SO=Y(Yk!Izl+%j~^6Ypj{M)^~ zmg9d;b(lS|8JmQa`TU}LJTrtWs(%>n*dJ0MCO44Ej5ZJ$;$bmupHsd*=Tydva`g>U zEMb1MjU4!?@L_dWg9E?zPI|Il?St*F`LleG;`y-`&K0eCe{yP$V)-0#vA+G{L=5z< zG??51a93Ji;}5ET>YiE#>*rkiTXC<=Yo6u5HhRv&B?IMQ?L0*Pbc2}Ptu-b$Nk`g_ zZG68CPtQ`igKZ}Gv3!E$^7;~g&>I>RufSMOv5lWsyx)`(9t7COhB}p5b(Lsu&yO`+ zY>!8QFGbuC{O{t^2^#}nQl78X9?T%)cUK*72LApv{vc&HJW%b^b?-IqC}x40D3w;X zWresG`Y5{C7QwQ%9Uk6;UVma+Te#i!zm(Y$nY2tkvdLQ`5m-vI?f0%d_ z>@oGBxC5WBb5>r>4qBVwcWy;^Ud3@5;2?$vDSspWceoWE_lPoginK2{Vc=|T9b64Q z5*X*#_=E5Eq`r$y{%t9iEyg;xG``Ue<<6kV>2}oq4fa7hvDAL-RU}LPz_iik>||>0 ziad&{oAx<^-NLd=eE;|OgH(cS@D4D4pKmqa5n3otmvU|f^uV8<7*Yona+D=WkJUoA z?~vXPEp$VN_Z9gQGt%LuEv;?@#X48o6u617xi9etwKnqXz#d-)49RzVjKRvK_dBQW zsvf{9O`nB(&}me5i~7AYzE#dnuqLgTR3TSd)K@b*EsV1hd}h)Qga0Ux=ePKSiWf0$ z%hTVDS!C^U0^pGaY%n+o{WybuCYpEj5wuUU#ZYR0!1071)MBqayQZG8Q49gjK&ZaH zKW=uqUA=-^-IMpg*Z70nf7%jbF5?t@gGsH9-x!}eyln6%Fb}mY^;yMRRN9MMZ(J`E zADwwh?`?o4QI-AQLfl3>y~y3u_3bP!-4ewhnR!#|;or_5^owi97^|_C+`7?A3;oCT zT{sT)K#YsgcqJx;vFF}8XAt==98wwgvRY(c+#2||U^UM!@yXyeZvO;6itiI#5Usnf z@dpi_%DRLYw^})7yB+x1hF=b+nz?v!TUn=8LUTxSod_?67dHmSZYkT34=BSfdQk3S z17EF48=Im>xMHEm_n_RY{H!vu93uMvbu_Ywo%T+Z}A5;=Ei)%Z7z0h zwTY+bfIFeV-rm>hBRuP;QKLEbhZ(OL%Y=W~pXT8^B+1{mTkUQ1>);1d)-ig0b$F?J z?!yiI11CsTcopjsoTcC351KJI7APKL8wXsOKF)6|j;hkGjdHum?cT}^eDwWFV{M1e z&GAb8V14T(oA&BZaI;acWprr`r!Lz*E*!AHbOuP*YMyV)uki;J&q<7!HK{XaNJpNr zYSqVp>2$u51Qy}s9W7kgIN zUDt`-bxUuM2>>9gyr#wo`<10M<`;LZEr@f(0 zl1m(FVC8Vg#f4mNhSF-a*UEu;z4(7(Z)(A4uLf^k{6Tnv>j`~G{6XmrgKZj4?g#jT z;?;WklxXJXpwfmL_f-RJjy~~*0XV0H)@~6;E-4Cex9^wxIx>ehII~yJl(Sk?Z5Q6^rfc}B54hg-N5~3m@bUG7mCl zS>kLHe@fj%b|rBU`=eSo+l~4o^ZMx$?OBOUV~2)!%!kgxLvdPW-Z66>l|&9)>cF>3 zq;|{ske0d%;Mz{7im_E@@VLeMrQU0v^7fLn)#$)Cd#YBVaa*iG0<-EUx_WyLUl+YUHDw;EqJ_NDDDv8$dJ)?pW{hgOB_ zzT+Qm!ntkq=yqGSYcHAiNzKM;auZ!W)|2(;@(;2m`SBH)wTTKV>{BnmauwU`X{F|l z;Yha@e{5R;LSHz#!VBbU9^4+8$t^$f$L4lyyt8wM{;sy|1ybiSy2DF5vm?LPLm%P5 zKaK8XR=(}$a86}y3>O1vMFLO!&`UreDFEF*UdI>9u8vPfFy?IH!U@7 z{kVLSHMDH_UESmNeO9slpNDR{K1Zyj*XG$DstMt+Jf7u{-fMcEM3jwjh?_)QoZ$~rM<3!3sxGV= z#^|1d&%bkR>$aGBp@P_#=x_IDlDS;`Qp0hQhAZ4B0e-e~btbiJZdrLWTepi1W4oA- zUJk3!VGzzV%Cn+}BZ|+ak6#`h_mg_e@{M20KS;%d3d31~0{nIS;8C*U@;tWeXtfaQ zJf_>r%_hG6u!>v{@ytJkKPVfh86UX`h%@5&DZl9-=mu}Lv=RHBSzPj=a$+}+`_GHk zWqzo+vw#!$$M6SV+@3@0l9m}i_@G{JsJ|23uw^d=Y8mVkW*s~xSA|(@o?I*n$A1!k zFjWlgey~9mUUl-u3ZJBwr#@)+8cR72N&bl%T=2OdiNHUDKlsL-X!ndZO-r&~WZFv3xG{gL5L^EC4mFS)M6qK*Cr{-Cf*i-}Ht zEd7>#-pq?;ZD_c3e)8{fQRR3&gwbe7=FRE@^bu@0z#CLv8?7h!n^`OH{`Wbre;0qy z>}ypX4)t4cb-nhlwW8WNf6zMXRhF&MJ|F;^>sx(D>tS*PQTXS&#GZVo^;#1CF!zJ@ zWY)^Bd!zfKhxx3rN#6k zuQj9hJKmeTu?YVc*c6{}-3PJXM`>}s>Qw7}{$T3(H}eOrzY6A+pCV~}NZtv(Hhwz% zjodTFSMfx+_`^>%_@6OaIxd%XZiQd8?R(*GXl^LKoa%&oWZq^z&VBhje-LbvFUMES zJ>QZ)+~{vo*1zs4*JYRSpCSrratDS|g<7d|$tSF6Iogb*?$Vn%B(3MR(Mt|uapK3@ ztr4Dzuki=DPe1s#DL!^>LmAqp`nL|Xjc8;S%At!x-2Q5FUiQG7(E0K>6uw` zP`)@}Bj9U^jtgLgzlHe_-bLEz%JDkT#n18${-AVf@rkP`Y44=*C*`YzQ>X3XE?%AR zGs>eJYXNkm&iLRP;AzUYCjL{R?YIf)yuvkDpT!P}Yj&;W!!To67$irTvHth%ZQZGrFhBxz=e@UcbwA@EhR{ z@C3ibAKYqQQ~A}GebGwk`nazuaAxI)t7OpQls~Qtk5kwt*xyrlve#BYW8CQ_1;=ZS6;T9qUx`#bu*2Ld&Xy-e49zNHjR>V=!uLt#8?FtSLJ< zIuEqu)W5#LAM|ghe(cbkOP-~h+LHQn#gtunG~xHsuDXmC{68Ed3Szfg5=FAU0dVe7x{x|TbYGSpglfi;3~uCQd=Qr!4?0K zF^bKqc+BwA0*6%P1W&Ndrf_a_?TnsdbhMf8YZoVOjjq$V8mao)YySBTe^3K1oP7QE z<_;|`LwnHpN?uwU8V-FGUDia6oQZDhjOJ*zIshLe?+Uob+U~-Q0<@_fv1$3tW>Vy| zCI3<~XQL_lSQne$;}1&1BZYqR@E{Hm{R96#7(VS=*v>6UzQGPbJtrp$AC>_7XIG~0 zmwoo+*g|eMxQ}(t;iM4<@C@9f(Fw@g1ASfDoCC+Czmh$f{tTW|s04O*4Vjn4?NC5ySo=`xzO z!Z`-yhwEZ1IS19ZifC6#W7M8}j6cZaL3{<;x!`GLu1<{Lh+jJ-OzT#i-7-Gf&_9Z_ z_te$t5*uD@f_4NBL}ySJ;t1k5r#{f@dp_ruo9W;rL?>zkNa`9*UhvMKIKl95pF?3k zZkF7Bo;K{{Q~3uqXN=*7fp1Dnnzcrve10^l<4>INk)`{Deps5(+6tQ9Ofr(w{j7QnXE*9@b(MClV!kWbMmvl03+Pw6FU39N# zBet|Q*O%dOSvekUYjLr|*;OokJYLV`&1Cf0Oy&$?z1Ac)r@@&zp`D>2498ZV|6Kk- zA5`*o%@N1Wx#{j7A_gkH=@rMg|R0yNNBtmB6JV4Ycgx4S857PES@m?!5 zot`S>CeYlie7nql{Xyjvx*n44>pt0g)JMJQE#1wY+ezO&6J*XjEZi*j^qIw`>hVdE z*ThOIVD~pJQbYJM=kQ>p$wtKGlm)7%<_g!lb=NfFM&cR*u5*(HODf~fDf}FU#vO~wa zU3stc?*W2o_mtc{tdpJVALF_GqUd9LzkSa7%jZ9ZKRANm?D1$Rvc{+%JPn)F&jHkE zTet19=sz|dyT#p)E(IA_W`z=g8s~ose~@U9jPCl6Eqd{*J>7%!MZwis_HPF9I+VE!O;q*5UMr8rrDCBYmZeUDS`KVf&}GEB|&Ies)SW z`XpwZk0lwfH=h2a`Y>fpJ=*E?Futs7zoN0%Jexg@E_~xKZCTj3c#LMR_G%m6ctie< zpZh9(7kpj8TrON4rJQax93Nhs#^7>9@1u5J&eO4B)JcwFt#GkPmYTo`93P-saq>{T$lne*kB6JF#ZXHT}|)> z!?WO8CQeA!NmPRFS_lZFDT#W3Z;VeA&v^ zLhc!Gg>_oF%Y*}RJpoQ7{)^Ga- zYjLCIV4C9|WyA+R=bB3{zD~jT=H32C91C&{g7Z|0&T33~=WXyee5}$B{Stpr)c|JB z9-Mgml&?J=#g!k9-v<{9q)pp!JLq#NcVnkRedJwdjEcvdP2in8Jz$w`fxnNq?-}lU z#S$0K(_KthU*ivI4MEI^+EF9CJw8_W6OE=U<#WJ2Tyk8A8$?1R*qWd&_TozlivrUk=JhN22Njz_3^?%$S4aGndzky%c(&)l!s(}m zzez5qO75`m-$QU$3#Hhj8@WZV4`?{zPno=mD+F1<%%yoL9W(O#@fwZJZ}A5ev+K*0 zhM^0$mU|aLrxs0MH$$7j=c_WpDS|gOFPD&QoCosP4rx|yID~i8GC2sl_cpjs<_4!N zL!1D7y-cBF{F2Ib^fmsVS)1k?=sAb@xF|HyQ!Tpq78aoS%Ia#p6;ISsZ+p|p1 z-agjB!t~a!WDmK{z1>=!mihkm5%J$zo#>_Mrf;eI<$L@=##+l4h8HXjr}U0#Pw4fD zyX>sdd376hyOPcqr|>}TLB@9Lw4!kIFzV4l1^}aean`9%ycPbp4Ivy%M$oQ&x z{_Xrht%LkqpYLGrL$oKxe>98H%4W=hSFU)BLT`2N?JA`m@g>jU*{Oo%;Ky1o+S2MX zx~-cg_{r`0$W-&T^UU7e;MjJX=t$aRTKZD{L1MtF!^guLKQ-P2@Q+9Gy=XaeNy3Nh z1RAw+?zmaNeOM1#TC?2R&8F}Rx0?kc11m%C6kmH4TqX#XuoG7bA3WS6{{AigAo~Zh z4H1vW9IZaVcsZ`ky2(PVvYWeM;sL7S0pC~8HpGWjXy;2_+gbY0W$I?Lyx*2yXvg%a zC+TC{3mQ>y@z6~LuUTQsSMm=g3#tCIvksGc7L0sfydv3GIPCn5^9l8^)l~f8@-cT7 zchku%daX)ta7#C7b0me?WG(vp3Wy9`1|IQqfp3L6=qAB%7ht(vVjI50AM9Ul%x8_{ zGreYvT$4jOQ;g+Xm0`RSom_h@_+I5F-_I6y4P%%qFcEc5FY?Owtm)b?P%_vDhIc-LUet(-L|nrdN-Y?cD3~7Tl~SrEKlFa zfYC+Jw@{2&1fFIhKZ&iZ_->dX-(YN?tS`HjG`OsErJqIcN$Hucp5%ZerU9|Ef%=E9 zbuM)nVof{-b1SJ?w8#1me^3Fc_0i)*9&+2{k#@&mnU(Crjg*JiaK3ZyMeplCGwM4g z>`bzz9D|Iv8@FRKf0&$u;NlDToPKh7CAQ)Rl771hr?5)IpY<*NpnPbob+dlfz0HcX zo7EA?D7Lzt^Qbt9IW=K|iv}>%!J3&Z3K&^z@0;a{$9wU(^5w(6d$}BrTw2$Ybv_>R zhv_^$DBX*Lshu4>F5lu0zO+kNw=+=D4)EO&M@^%!h_S^6&fzN7eBhbGP1C)@%e;}( zYkFDP9Wb^U`pAz;Z@G1rE8k(X@~yF9Q>=$J!E$gJ?D@aNAJlrCvPM~(kl#uBLgP1( zPl~;*VyJzgQaPSR7Il7U+r+^<&(E%ScILQ)TW<3Et$l5s5{vTnGAQH@qd;iiFQjZM zKV5x`Kj_c3h>uozP5BkKPWd^fZcKe}zFAztzylQAKx**jfTmu)bMbCgt^WS9ygH3D zyLfr68Wv@86MWhXC zIH-U)vOxF;c7S;>gP+^>E{1l9z1(H&aqDtEjB@ATtO>T3I0sM3uk#1Rm5|RzhsT@1 zrjY-XE|!ElnevO@^~TL#xYVxcK3n=LKLss45T;F~M- zwuRTq)AwTo<^DOBQ7<0hxqX?&x5MatH9Ty?$Kzs94y}rQ|0;03%?h>ESNVglvcEZx zraq{X#r)13{yKia1iqoHRaQ^>w=sVtJ ze)aYL>v!or`uneTd7s1IwVd#q__bNn_)6juVT{SIEE`l#`N4lbfAC$lw>`h!2wi*s z{eAtH*OVE)#}JMB5O#PtPSE0wmfDu;hicHgB;N^ZOr3CnkA0dy$nW5rRy#1i`HK#~ z>owO+zCo2i_f(hy=lY!K2h_)OZPqdJ6Z>lPo7a5mGx@T4uimHc*LB0GdvVyfWVm+v zE^dg&31dz+Yopia^qzm?FnI-Khq+fe(Qk+k8TJ`n6E3N3Xuj9G^lXs>&yq$6pP{Wi zUF)E~`K^+N|5GOVhG(zVpn4zIejdMrKd3x_p6(;M800#jkNO#7JS-fWwBFjr-eZqf z7K+5d`_SU#EwrnrH&*E~c3TEllRxe~Uh({!`GY>?H1O^ho$x<4sGX|b_&zRti9g71s!YmN?X?s1SGFGZtz3sDPrdFh zWjAfgCx82R80*ysv3g=~4Y%&3kMCbjwZUY^zG~JOOv5Ge5Y|T5)%WrbzT2(pME%(G zWz*P%4Kn_dL*wWKCR1m+ZHD0+jMMNBy!=?;A%-9IOv|s0FEY|3*Ba-_>jytidB(n# ze^70}v=MQ7l{=P+pf?0}J&`A({IuH{d_M-il+Uz_-&zmloe}RyJg%nOzGa`QwRG|D zg^7!YJ!yE7;thU}Kd3su7;y(fzQ#BmIj6v&j6SINb(GiWi^^w>J!zM}3Bv@V>Ilc| zB;Cx6`z}4d2)^M2_|&`!mI97TZpbh32W5hp!)QO#T3+{(oQ7-i28w@H5dVPk?9;BX z2RocQT#ii3FZ;n;yYJK$Du!P=(Hb-mnv0qiH=<+u2Q-rO5F zH1FtXCMc8mjOfGR*EJZS!9?8jqrH#E{H1&`RNHRutEM$gFSvsZ;U?LCPdXr(3KFc#D{WD{*`Y|U=%!FU!y1G4LHkIS9P zFt^#vog+Sa`hQ;BV1qY{r+|i;#w+p_DIVZE{6Xf7WNic`$Z&Cl6-VG?-gD&cQkxJq zp1-yum3Yr8-<(OxSuYCiGdb8NFaF-7eo6V4u}8ZdIXBPA%W_U;sru!bDxdGIL>y79 z@VEGbe%4USdm0|5D;x)Zvur`j(nWU{{tEL!$-3+!gPO2dat2DHu3POqH;0k-f2S3) zuN|iz&u`0S*wcE-tOb6azrr7k`ya{2YOY+AZGwl1&l5K`0FDsoh|76tjWe;lFM_UJ z?!2ndFQn0TnUQm^1Fj}~ZR2FhHD{e1+E68x^9oEb=XRp)$2yw-7JsmJ%`2`&n7Qzr z8et*%VRRRFR~fjSiQ2GwO04Sl@ul76K8JjErb#|B8_wLN26kXeZ;;p$z60J}=4p}N zOL))F#kqoCo}7vw%0DPd3TqG6u&nLOx`XwHuzw~!u)#x(Jgu{zB%xRDWxMH_?}gM{omKdo^YgGz?cy_2xL%GqFb2q?}wP z#*};0P4|!MOS*`blJrjpQ#f>R0gGtwwrOAFtn3yS&&&dxwz-5?*QGCwO#Zb`TudHO>F{l|GX=C{(*`n=Gew2gl4tlk@rZ{lf2r)Q^_ zA_pS8IkYR+PvOdaDD|a>JE~Y0@djrHIMXN60TITKpR~`n!^iRu$_{dLdv<6)p$EJ! z_6_Je9vGK2M=+NqvgB&6jBC4Ud{;~5_tzPHKDkehuKg(a@1EHi{6C9lG(|UHQ5*41 zySLWGZ?9(IP4w>HPG-*La=UIOz596q}XK9qk@{hWcuFTBa?BHCx9)yG5D6n)fEhv{p7Z=-p!Ry;$6 zwQ8YX;ZeP3sr#9<7sZV|q^)4mdiadQ{MlT{n1 zb+QC+yK;A{AIv{!x;J}o_Wf#Of7xR8uzt&z)t)2SZ>49m(WV<&!F6u?M_}O^(%^7N z&jjA!aBKGCT=R3U!GG{E=sD!OJNZ~)7*zym$~4>&KIxOe9*dnF8`o>V;uMo zyoZd@gEnBWGvPSGqbzfcGRJ8X>Io>vE?A7>_ z^%D8Z^xFZ`oYjHZ)>*QY5$M_zMgcw)iyW#RX;}2S0;*`kN`Lge-O3XbTg)b}FAH1kHhCsf=?PP5b zy{}ra{h$QL?ifA#AJ1K28`~CAzI|a<{5JmJr*=iM>9;RDfNPR@Q9T$O>Q(+9?TW0e z8z-l}ow5$`J&yz5<65|8gsYtf+r%lb3SJAX?~OnBo4lC(Y?=`hfbCGLFYp&L8O)3km;aRXHBf{kesv(_3bqNH4yXKd3yY@ISRLn!W%%@AyqUd~iBV zzKD;QX|d<15ThM95KR3QvlA|~KF-&0&tQcAG=Gpe`~P4$-Wcl#`#4Z_yy0aZRz;dU zg4S|+@{=50vp)NEVpMMij|pNYG5KKLAS>^5|B?@HIq>UG|1;0t{YSs9ZvQ0SG)RY^P%bSqg>x}rb^k`G{I_z1WlC9&5T#Nt^E9q^`Z5nFcR;0)eZAy z5Q;r(t0A$8oWF}Xuq`~ zSN&;a5V_{I_t>6zc15tjlHsql!8WAfXLKN)l;gCM`12F!u3mw+gN=QRe=_lcbbeF( zLCY(D%?Yv%Ny8^lA8jr8AbuoI#Xkd&X}91B5zh;~HQD2ZCrH;)T5@d*{)@Pf*tTui z^UyRiG2+mf<;>X842!tRm5q5X@TDBjosg2z&k1ZM= zp6u7s+id5vPCAbbXe555_)rxWJv@Uew(z9(@Nx@Guxl&d(KuF{!DQwrQlIH#~$dlVFQ0~S@qpFHondMyqn%IDmC>D%~&_=MEQ z$ukmOF zEH#IFD}I>*E|;oo(gr zjI)MUhd%(CqRHoKj13;%q`}S=I}*K7wLNh?zllFMthW5r1>9M+9WYqN7}qWnAC5i^ zu6%8!bGbpWacGv$w{)h}i_AmCL)1PrdPm-0ckLc{dA<#{*f3ZYT4n~LCVnS2R@uSp z=!+JJ0o$HLcNKSC7~kvyahMv`fw(A>n?G9}75AH4iQUVb@gkkLuEJTXtGQG@g0JJf zroaw^4S})M#KnGNU+KklHlqJxZ^wrME(=(c#v8C2KW)98p458n!IZ9?K5N4?5vOa@ zh_6!p<)lzN(001J^P>z`wVl2;)8K^L+qF55z+JV@k9zQn`GbBdtGG%Z%Zs4#EyCuz zjOE}*)zNCU#fgQJ)7F^7*y^v}TIFPNH%&a+jjl8*$%lA$Enx`vcA&nv%~Ka30yFn8 z|Hww_`O5QCW(}|3Ga6@Kz#r6i6E{J7oA>X?-wHdm)rC{LOw%r;`HNm3W92pFFSspN zaYDe#G1Xed_6U-d!zd!+WQ zhnpFG9e+?5TF~h0dj4WscVq(rWGp+C9Cd(3w&8e{o3~UtpY}JIGw=ZbCj>9(-rY!7 zx~Mc(3tM~1=qI{xaio1HPMSNSP45}Ag{ftv?w0ndCL6l8)?Cm}zim2`g*e^CC1#y?D{S9`67(OU@CLp}MEFwWP@Zt9d> z%u1bc%^xWqt;V5Y`!A0<1>o}$Q?LrZv=qoj!j_>~}{vi7T`hl>DS3j4pp>Nv=VT{?~qoegtxrVRRtTP$yJCozx zo?GijDxG8Bf&NgUPuho@`&h9n8M74I?%pA_<9j<&xUPqX5?uh?)>Q-8( z&cxcZ%E!gm@dxoCedohq8c~DWoR(!jeL3&V+ws15!G+@T6xcjMt5|MCzbWB!*e6yf z?Hj%zJ`8Zwmf&h|2NPiDiN(5(rOLUc>`U#iuIBEW%Ivb4T<`11_O_djBWq-3zKlPp zK4Sc}O-u;I_>gn6Z+0!A4w1)~inX=zZLZ z6h%waoq!{P3uYQ{niIL(s+X0nkB0>n`D%WLzQhg1nPXq`Mf^dvC$QP~7;o~#y?EZ2 zi&;b8avrmtHtRyxSNM{2uc>w}VJ#DvR5`r79`W!iTj!NDMKck`RCE}gbN5+TVuhxU zpNDSyin3iN<~n;~yuw3wBPDz@s)((DW8d>%#vfE4SGzJ>Je8YpH0iJwwHIYf)_T1c zo#B)Sf0OH0EWbZIdXrXppRf)0E*F@x2iLe)^@X~dl(Z|;Mc<_qvLav~l}vE+%ny>+ z>|lCH4Wk$MhsVq?d&?9K$1mg$zV@t406zS4NjoS11pP6VF%Vmf#k#P%;tIkO@I@KZ ze7?*e+2eljx;l5U)!vCUxPI7;`6)daC~rgS@NiSJ;CdhPuk#~oz3;^~`Kz@FgaT{- z0hgds=M^ z{F*~ApGxJ)jKyHdyp9izS5MqjJRdJ!4UsWA;2p#YWaax@C=c>_)!{HNpX%dUA*#aw0k^A+$YJ~X5rqtx#b=o zuLV?vF7FiCGFxiLqe}X^w&N5P*9--O81)0)R9q{ck&zt&;NU9vCX+6yv z@+!L>M>YcQd|L{w3Y};^JgSAm2q^Eqi$C~*YrgA{wk6)+2gbZM++fD1$z6S(c%o!s ze|oN2GOC@qv(7zJ=^J_=;{bVPY+D;x(CrNHf%pgbgTKW&lsEL1EapczL#&<9W@4DO zHbLf@q|fO@7re$Wn@r2Mi3@SnOkCj)9--EEoc`_)jz6fh|MvLQ-|2o}Hpah^cfpG? z-O-G1>?Mm2_GZ{D$gAcf4S5>#bWOe#3-8M|9Bf-!gG=&3vjv zQpR97=aqSBz) zh_dA<3F0_nb5Yt1_LOBkNqww+7n4q<)tpN2`}*Ti{fGN{jq```2c?^WZOd>+`6;hV z^%%6W(U{fMnrz7nly}#szQQpyc8X`ZyZ-e4&!45pd9U|=*_@0I;m3QmAJVD5Ci~NC zJ!i%dlV5M0K^anS|K*{zS2xSr%Gk9?d(;~MOuEfp(r2O9U~SBH(y#XPbXUQT^!}3n zU+0JN@bdAa`GXo?y4vdg`Y_`Xw@j=-e6p~YSY5^hGqxsuL?cKRIF5QGO8_N$K=hK9{Xpf^gahs zt1RB&Fq*3mtEI;9(rSHM{6W(m&3ZmX{U>R!hHI^{sZ`1y7qiytyu<{U&et8IV>HI5 zO{^?i@%c)&iIb&RS??3>hx-@k4y2+>ey3c zi_cGaZ!fIl z&FRCtF&d}rk%TwF-AczP`#4wvn)HgFsMqau9=^no*IsyM8teqjZVXa~YG9pdEJ;A3D-yGA;A zYk?J}PHQw$N%IMgEpZm@miUIWoj*FiDE^?h2Ai%o9&Mu7+{qIEENoGkeY1O8p3sSC z3l~c~?K(WKIy$sqoR0KG(|!9knxuBiRkD8>O=h9t4Kft56<>TXM>v?UlRr4Wh(E}D z?A3?HRcTFXT*Vg0{5FUj#g%|ht8lM-%Uu z=`WjP^X#Nk7*a-4VLyL(eieVvtYb;L=7|mK1GD}MM*NIX)9H0ZKHx8k{}IN3umhVK zOQ)575Ki=~RtXjhyQjqn4iVT(Vt#6c-QL;RbNZelG#2Sa-beedrx9(->8V>il6+mZj!q|IeoMofeX$&8k1Tj)4U?f|u zo6J7xKRz=5vlj4$w$0LfKDHnB9qvnmeub^u-S=F3Fm*bK#VOSZA*t8jHLM%uSlrZC zTiTIqq26KE7bJfJ-bmWLHWm#9u#sPqarO}X?9;><%=hmtVYX=3wr=peM*a4rL_C}X z#h)pG(TIOz3kz|G)dyBqabX!?bIt!2?Dw6)a-NDawhMzpPyg`zTK?e2*h^nW zf8CcjE!)g(%yIbY5J$H#ia2@dD|t@lZf+`HO${!4%6}=I9cygjTP`}Je}xuj%|*Nq zyBvNC1qM-%SVK?q+8qhXw?X} zdWGOMg`dKOu{g%SmcF`)wDdQl#J<5^g3d90(<}3JvrcbDIQzf)7s|&{4u$J^`{8@HzedFc*J+-TbwvATBIjrj=#^Ug( zG_0PFEuepU-#x7&)EoR$>2RW`3tnvF8xTD`E|XrRbTQ|oc7^|Z)ip8xj-By!+X-*i zU&SA^y58LF&EeWB`TVEk$}#>`&K%8k<_fURR_SohA1?RVEH`EjtP&4Ax>@>ZTg2(h zRK%}ChxRUAPM!yX>{OZ)cl=;f+!M=t+sI@G=!9mk{*`m_^L#RZ1-)O#6-%9Ncr_5luF9r{{;vtppO}5rGd0A!l)056@ zV0q3KHka(+aLw*7H}lB#*YO8^1*JqBXRs$@OQT+}Ya0D|`Bv)4Q(wleVX59odon+q za6fjTdEGh*^n=gE3;L}*POHaSw_CZCZcZ$?9^``SLMpHhfDyjWPtU)NKdANA+vfJk zCWrS%SMdf}gP@y@rl{=GYlDN_&vu|u8%G<2^;{4A!R>gr0T(PDhr8x!L<`Qoq(V4Z6)}z>^ ziwXQ8>~G}{!c9}!)xh+aKdcf4vmx;&{T^FJ{6~DVM=F%x7johKJ{LX= z;1CuFJ{V}l4*P9tJ4gj~g(tmvJiGK{Nv!*`Q&#T(k`feiy5}d%} z451|&J?&@UfvfmAKchjMyuOh^Dc>CT z=Qx(n4X2j>(R^G^`y(+1ucf27gVIPXtn$afEPI4cNZlmAi$D0T12eZ!7f@6!liWAw z(ZsUjj)zNup`Ycp6l#s9?VDqTb~`7yAGG4zK`6Mve_cpZ@UhHq&-2?Zr1m_8kxW z;fE{cei_F8Er)Cg*u9b-20&Jx?ct92j|=Xbar)nq5!TF%O-Di3Oc5e28 z|CTDz*h;}mpD-!=UV2q~_^zqsh->YYzvoaBW~}k-45l4`C$rYpeYJ11G}Q2!l?_`L z-kiW1oOT4pW9-|ZN+}l@M02IV#VXnNSZeYlZF^pWxItS-t$y`sZ>L?nkkEXfi zI9mHU{-EY-GiNIgCLadNX7d#0hU^2_+2CuM{V#o)wiDP$*V5-qW23^M(f8jRw13<- z@v*>iTt9YRbS~YL?ApX$1BcT2#-$7wkLMo8$m6}4SaSUi+Js>zl_qvgxOjh@vX{mw zK-`gQyS$BCUG241s47aZZ%-@s7yGW4_Sb8SpIws|o}0aosTa!KpY&H-@GqzP#O!ff z!RNBuJ#2O0WXeMv?p>UCErz#Nc(xSZsE3_74Q41T%IJUz3ly(Se57B_FXIoAKdl3$ z<;6Ztbz;_b-6Do9;}a6@Pp;Mb%1vXF0|!yMuvLrCs64db7^T26Q{vshc>-*6?b-=A z2U}>G_)x@=(<$!Y@15c_NYk)2CdLu*BMmpQ42Q~1z}LeTc%pv$N#Y_!PLFc35t{kc zCcHz9|9zNx(wG_d3Ddy`mc!Vz$k&iAhIyOEFf(pOcr);pddpf8p zuLc^aq~C@Ml~13Ot&1ZLs#_OME1VhoUFz{{r#x<*@$r9S&cA&W2K`n1LDH`7WAu(S zZkf80&7F9Ie%TVm_k(Ln+n2uU%2hoO-^$-UKCB0WSga9_;>MTS6K<`pSdWei*5a<< z-6?;HPx$$S@8;@!-TONJpnQ2~SF-b}jTuf}tW->1!8|h5h3ceZbd3!sxSoe68&}NJ zLD`9|?*8*`nYXJ!CsG|QuZM*+QcKroIz+54uvqm8^^eb|;n}J$>HH%8AnR<}l==>t zkgpEyiayU+kGAWn?4-x^HF(x8oL_J#ejA*&T_E=3Be#DXuua1o0xDS-ikrkqu~)i- zYO?2~TBTdEoDnv7e&pc_{`$Nm%l^x<{e}EN+LW4-`iD8Z^&Wl~%mwMD;rO~^IJLV3 z*c6(a==QaC)mo_JU(}T+Hn#0&QJY-w3_5sV%ImkyV$; zZ|GIai+CHp$QpaMIBSiWQiRK2;j#zW!_!sitp^=zFOm)g>2&TrKoXAzEG`H@ak^!RapUHn1%w&sbcFe#tK*t@Kkwv0u>X=%UZ z>UHVHM$uNw!~buU{2_SWH}iK?tgu60@I9`G^EZ69CyH@5duGDevEL=R@64rYkaSD5WO0*{UJnGv6OVXpPsSMdk67BR6H40k9rpY>P=)N^i%_{NO4=Va(n zKE?{eXg#=yU0I!!tKISDwoc@?&-Q(SqE*OkFTmBnFWoca!hLmj=8MzgSm>X7kM3l& zF=wT>?wo5Yv=Nr@T^H?&1;c7P_$vM&>k-x=vGj~G{1W2Y_Oq%vzMn{g=Kxg!{{jLmxS?jdtZ zZZDhr=+Qg(;CaBabJxrt6%5tzI_*8!@`U=V1a^z!$*d9Nb7OeBo*yZ5E_0MwziAD} z`BnTuOqZnJ9Q2Q1wizOJ@M<0J9X$>CdK`U^q$u;l$}9`mRNpsPGzQS$OD(dORv~$T zABgCtFul@kb%rB(4`14|x{|5E*Dl>#>)a!CFFNf^P5i+}J5WZ~x$=el!G!i4 z)@DdnOn!n^m$)fiT3T=kzuf9}CsvYuUT-k9YT5o{I-AWl8mzPX&53rY`A5Es0ewbo zbU00p4~xeDv^SCwE{L8eQUjv1!5Q3K&>20Z3(Hex=(~Rve~>+_)``?LeWcr@ZiEZ! z+Qduo;+AxyV2I>Z@jtYN0dtp6?~Q(b&m^Ar_8Cwra6hN+jaVNU)#+yJB$C_J?ihqC z7}^X{k@emRG8|i*LM*)5*JA5IDs20mFN{Cv`2kqns#YiL6O{+;LFC^jJAod-IA6G@ z#X7Q4-X7}X>-v_7*iOgT*SBbLGWW51X-tB{=(KrCOfS7%kxD6UhWX)PxLcmg36HS9 zD{gvz-@Kdm&AyI5sJ2AfRo>!rnl%gmlq)ZG3Hj0!)d%|$t`14Xp`~jZ9Orz)Wd7n4 z-Jec-@EFH@1=d$h*8ZwLGcW0LI^WL&*<~_@kmOhK2l-~&j)~<&ddZXaB1*Q>z<9!M zYb?`YI0O-^T6LZY+g(?Ld2onx$8?st!ykkc)vQDYmuCN(7+w$igS#g_-)>Nf>O8<9 zJPcOpT_G3Q1ybStV3qnZ{-CJ~QYm|yd|+kk*S^rqjjF5n>G4!r=bkuTiY-ViPRc)n zwVzYE#o2b{vjh#eD>yb&WrUx;Ht%&i<^}T)5u}+(i}0^k zdd%~``tS7_%2R{0Io{V^dlTpTJuX+HY=w{DgHvx$D_b6izTg*Rlevqx7>$M@jP2=nL`^XdESiVH>kyq}x7md|Pa)f(PB*JYQF z8Zw$0BXsAZ-1Owt);}I~?@te?~KOIA8iU-B0;Im z-ojueTaBkD#tua{Tuz1FRKH<=SBj57Nl;twiu<~Kf->&AR1 z{e?$3guF#K1o)4S`j{S{Zga(JOg8Etcp~@eZB;DG#PDzL7sjnHf7HNiv72a~eN& zZgpwBrKH`7q>AV$rR&FwyRHwf$Hpo-sD>Ks9~*D(pdSBO{-CLR^=)Ay?8}o2j6L(+ zB6lHP4!o9h0p1jLUSbNSrN4=--HqMRUdy|y6ZqRF97osx6n_xzfy%vox+cz#Q_4+? zS2QkrF^td*71q~=$0eLZDlEVw>L(r^dGA$(&v{|tW+UBlchB^}W;KF{Kv zfvGuT@(jC-!x!%mN z(Th)nHYjZd>=n&BH!n`6@YWjkQ}GGKUBebCohJbGH@?)^#0x4oCn=jJ?gONCSSRXu596;jup254A((aNy8YN+fX?Wn$(_15T6t%KVjKIqI(=1ls!XDbhG0e@8OTKp`3W7B9! zzrq{Wd8av~0V!Lx=1#-Q25YYO9+W3|nk|m0+6v_<-M$;PXn*D0oVmoWL#wh-c%&oE zS}B#OkA}}fGKWg&IO3#;SGhWY%gy0@{+Im0_Ie>r#%n5(KPA)d{A#DGrR;oDcL>L5 za8q!hbe*x2!(ikl8=rZ!rec_@_l>?qn~-gnc0XpUIiWp^KC5Djrf${l=@?zqh1u@0 z6^1{otxqO`GG#+U*Qk7!m-J8REGn10w3vM`)192o}ket z3}`?sy-+?FT+e4EFts*maZ9yQmRRJ$Upl&}Kl(S$GSsEkNY;K)dXR3lqdN83^vagL z=JwOa#LibflmMC=X!M~i)T#6__~f4*v?}dD?o4c~)vcOm5%1wD-kMKqkKaFKPvWI; zZ(5zl>kDk(lV>Iam&C+3Bfi^TrKqc0tA-Ba>qXpfzg zo#>REauNxC4}HqOoZp^v}p3#JH8^hOR}FV1-BO1S#LFO_p^iLk#@jX`J`SF#1?$Q55_aZ zz9G;lOpSPJf5IQ6{ZI~(n$i!R2oH8IKIg)*Cj-@Ynsi%T=776@2hV5JpN>O|dJH{g zH@Cc5=!(1!)5qn<5cLsPuzhQxFAXM0`KR~yez-6!9zwp0F!Tl(|GF`Wi90vhF3OG% zTOGg87&cg;+gHjKI_&r9vDv?1 zJqSNK1L0qZ0$#KLmN_=@{C*ia_;Q5$_%gKY}${2%y(>&4t|j8m=k!aqVU6Yb2w zbU3Zu*7Y7^dp$G1ZntpLs0WQ*_};PxJT=R#`{XOccUATzDg3tM-{udh-4gE;%!@uaXg!{V z{&GI`biVaPPRx-Iym57<{An5nSL2XUoA+ zRxw0LKiDlgSngVVp^9Gy_Yzy9*Sx6p>|P83$VH#o9;$M6mmRd2R1dYk>c%IN=|+JpZ^{-88i5jAw$>&~;&>7i%(Kul{q ztIn3}3sS9<6XyqnPteTGbP|c}vbnT>n%XzY?6dnrX?ZyK?p>0%aB&Ys&@L07(#p){ z@d|wT+u7;R4$&}n_eC>zb>zE{2tC^U78;kyM>|vhyZk}LhCMXf%c&AqBurbk>YL7b zBl@Z{kG6(^>{JU|u#eaL(TyrI>@}iRu-gpu&Z``H3$4^{TI-%$saQYQn#M|%#jQ09 z_L|vj;d15kEOLhN;I^8`3?AoPU}P=h!-n1P-E;d@h%@u|`GaQdk)!Rza)E4i9lsLo z^f=NO#^KEwT`I!(z-cm6-AEV8)J;ZntPX4y*ei4}zhK)y>vTl&lW>b}_w;$>q}Q8E zYSG*+?=|d>zIDxs+;6kae1AEw3qia!{vLnuy4tt+efbFq<5NP^PSIzRudrE9$_@nY z@xMEUwQ#Oe!6X79#j_%d7j?fA73;8U#Lv^&;kb{Z(Ys6b2mR>o@A3!l_T6R;i;d`$ zE%0rJd)sUON*45)*ZY(Eqye5j?Cs!###WBJIT*<8(Ow_d_04>BPqw|XQq0f4&mV+t z*-&0A#SeTPzp^jBZ~lcx*`^249sGW91J%U~0}?4e-e7p~bV2|b+&K(%iQ8?84K0mRgex4f-=d!;h zce@p_QNNBq_}lXTH4gI^GDaVxi<`bdVu8IlJ}|-o?P?Ex&e?h1kBQa9j(2;kwOP*i z;3WJ_{vbbvp6qpu(|}2-#vPsi!vPId+&>k#mxo_nlMS#w#w~Rc>L>vwm>!)O_fP2p zy5K*MKls1)`QIx8d>YLP4g1B@?(TG&IaI4QZ{GU7PyK}VnD^!5$j||Pb2Rzb;L~Mr zHg8Sv6DIoilBBgJYX-0=d%Absrr8ZpNA!*tY+6P#@qvP&8amOajQ=EK|5^4pZ5@DJHY zHP&eGH?P5SVL!zvWHFXn8?D1lS^MMpN3R)j0=s^CyM-?-Ed;}25y8u4`+Tv=njPHDLspZ9panC#4ED{KewK-{_X z```>3ZeR=>3f#f5V!~m^%3*WBEawQ*@nff#Ken)_Z{QDlydpq-!;>K|+M}~4@4`Je z1s|K+E@0xK2}2R*P8z4;Un*W&T5%Nn4HE}a7(;qQtg97yksVK*1=Yuk8})nKLBo@( zsgjs2D9U&bFaYsOc1K$khN$@&*D*|@-M95-juBVHxt z?Y3w?V0CUgj;3htcwhBtUtr5jfV3g7^VpKSWBlLqzh=I61Ah` zMtjlH#fePLt3{r#ec=G}<+QNSbOb)v~eoI#IM`|cy}#~;8SBp+c;4h_7% z>}Ea#&+wOkk4a0KHj_^{EBq0_`_ZLMlt)%@F`qLw?MXP;NBh}7HY=G{Io8-M9+UI3 zHYQK*shLllmt~_Z`djXxo_{@mP&PyM3%()yMPEqzh_om8L8kuG9)FNA1s&nTVsy^$ zG4IHx+g5Bk;*hoXRfBtgDc$UFcoOR#`7#~UujbM3;t#5in|>Zd-woTm`hpEMON>+c z23+%=Vv{*5yV@*0&dYkZcee-4s~Z3ZT?+%VpP2$0b&8*;IIp)Zu?0(*>)Vgj+T#w2 zL-@n_gIZ@06DnH_FK;b$V3dCRI~Z4QNtftisR(^McYgG-J73m!XWzB&>2Wt2V?Q34 zyY>Qng?bSV_-w<0?z2ZP3{9M}^a6d$Z{iQqmbBhT_Oq2+Dxbn{K{!tD)cs?Vvr2f#Uo4gC2%6 zo5j{f-xbV_xve{^I<0P`wo>Up(BjOD6wDx z1Nke#@gyE9@h!iLKd4~}Y;fmc|26tI8rks{{vPe&Wgf^3j)5zf)YSh#bI>M;8Ngg&&uxEDHrUU9qUzAYvQo2;Iuuzi$BPo$A_&$df#A!b9_iHKj9B%iv;HAmM*CbeBM1cwfq1w;HUVmJR@Vc zm5hO4k?xsTLHu|ULw^1+pG@&rAckuzQW}{3h6XFv?76{kHjEte#H2;XSZh_A`8?gc zI=gzJH}!8Csp+iN8%*fM#CPq02QJV9h3AYmD)^vqR5-P1f-w0A`CGZCD^c;f|CB$N z+7kyhQFFwf>~tnh>Rh_DBju~zsohg+)^~~Ke%W44Zt+aIFuVuh)8S9kR?NWhwAI1J z%k0gNtGPoyao}$(P<*NUGTWbq%7bdIg+Ekfbj|ger(Q8%j3(?wI%1J$^lyk$QnXV3 z!yz*aMf1hOvltv%hsE$Rtz}QSgYT3o9G{^aaWn&;4=b#7fUwJFk4yP$H&L|g$L<-r7ij5vfS5!CpH23Td3U#>jd94z6%n~2ai=H&_wV} zw@hqjo+;g3Br|i@21ipq4F2JEfDAKFc;}PTt$E$|r^5mq z7UC063x4eh^!uEq9Jzcy|Ajv|4xHP3oA^nYyU1@GU=SJjI^5;nwK|RsNhj%1AMnyg z+yadud>?yoohHrZAJ^s)u54HPLfLGoK>9*<2>MXNg=ArHPUu6#8GOQjgzLpKFCN|B}{50fi?2R*N? zs826FyO_#mBOK&a=BDi^pDKTfP1)6{*G=6RTa+ITCpeDDhT~=y=oSd>ATPK~keBml z9&aD-P1}j(qUdf$PK9mgJeURkj6Zk?gfg|zD(?X+9n~$z-o$D{lhHh9mdzsoQ;5+puKWbMU-MK%f*Bh}1sMcRRm5*@5LXy>FdU`{qx>A5_;-W^{hSNq@n7P5eP&Q4`*o_hsRC$!=}N zN6oh!W}ebq#i_C6AK(w_$4y%F@138I8@kZ=Eo^WIXVCM(fp14*IgB0tC*cn&J)i1< zIfu21#%&JeOLHCLAEvl9V>Rms*0;KqE#~w|Z){|Ilt21=tk?DX+~{53#2-|;m3|%X zJeVi^qb{tjFizk!lI_(4aVxmz+n}W-Jm-D>Q2wCTY)tzxoHW_xUPo7$fmsVP_E5C% zIg>};ulJeLLKf)hR>9MlZ}|*)Rr=Mgyt;YUgZaFE?^h@9(R`-*Qa$|*{-E&g*FpNE zpYe;|mT4p6+{qqM6ep1N7+hM}wM~N9Pm*qIqRg)zZp&ONT+QP@C_le?`GNyag&kdEU(x}fU?dDSdlpm{${T&XuS6=TjG=-_Y z&00`vF!D%UJ=4p(euF%UTcQGHjmG!A)BAgQ@$Sh7+Kh#)!6^&b?erV(eg;0H!|0JH zA11l10ck56^NRP+^fA)CX?pM1UG-n@1EiOU2v6-fvG;zpQ zJL~`}G#_(p9NI1EXFW{ZGO(V{IL?pe4|-!M<*a@x9;)huJOCl5`qSnh8X9a9Jr|v_ z5ZD2BjT3s7WAS3JS@fk53D!0f&H=8I#~vxY$~Mpao^GV!5Wex7AH^Rez3ShdA20pk zy|;?`TIU(D7UGKGMY`bSfXR|}xKhGxz((venq}fF!N0Sw)JN<9{wAzp;PKbu*$7wu2nlmEyYq+Si) zRfOvkJ1t|kL8N3sR5`&93mg8R)5dNd?(n-^@dn|-=7bFoE~ARZN~^1J|8n!Q$QZIwNi0^xLa_@!f*l{>QDSfKfi0* zAD>k^|BOGVHd=2jVzpIvU)*8Y#0H{yOlQ*Y2gy^KHjKSb{K0$&Jv7(!Uyauv2ZL#s z4`~g-xQ`8&7<~Eiv$dl<(>3vyNuMybl!;eqrz?ZXvAMq2*W1Q!RSK0NrDJe=TFru{ ztJva)l^bA#Y6Jg0e=xn6zxjj5N8X*y%8AM`IA71V4}1=kkMi&G2Q}AZwdP>{WX@Ae zBJz!$H%uLf|62#&^m9*GZMunZERe}xCOl-FweXt?G38IATRT-5OqQKp-8mc*t>-0K zPn?tSFNi-_m@0-_Ztz&ouCYDsgL1tUt0Vl1e#IX&elKJqY4)OUa2}*tZ3KR>@cwue zeOS5afyKbYkHoQ>PG*9iJOc`n2@t;re2U)}a zr}%@<_G0N|BJ-ou2qt&Q!R{V=khaohzNJ-31L}2XZDVvCe4$dX$b3d!IJb(Y?Mh74 zmHqOwNO$adYL|m+cXczBoD>UcA`@|p2462=XHY~GdG<%EK zqIQIDMw@Q!s0Vnbt5arlv6v&~6~%b1hO&?SGJe`F^XEi1l^5V<*# zjqNcorinr6V(-rs@KcgWcEK1mz<=hsb2<&MA9#&_lRwxz_hf(Zfmgs02pkm8EITL? zW2@e}ul(^3{vdsvv_>i;AAJapzbj5^J9ApHblL}ZgoX31Z=*B!62-%2w@=*gE4k-_ zxvV&;lwaZaXrm+gOb6VIUv`rXIM0R;tBjdT{$~8a`*_m|m%8hOe~5l&)9oy#gK6!G z9};_>eD;Gs$grz*EPf*B#xq}Q4sN-zbJ7mwhqL%->Q=_r5S-I?x;1Wvw~0Bir|%tN z4&rxpUvc7t@?1-A_vkDl<67L;i}WttNNd_YIs3oOAAClLYbahQSl+tOaMpqD60UXY zR3a8cI{(2RBoFMD(5<(XKlB9T59V(&Z}i*esvFrXQ|OtZm7lIHW+Qt#gC8%9mhtMD zmR2qC6Qz6C9>*uK+O9UZhHXq-n`t??u8!`1n?EQXr1X0Yf6(CZxB0AHYmKw6YmX}* z{6Vv)^ZEPJSi$IUw)^yPe0QAFN!yCvFJ#?eFjGM$Wvzdip8{-D7I?{mim{OzoV`y|s~KRKFRW=s5Ce&G+Y z|FC?^fQ%Z2LvSKq9hwHLYj>2j=D~TfcL{Z-7pJ&iY#*uqWqEAg!{^l^cW+m!*bPfJ z8-Aw^Jo4=1AL&fvn$AQtCp*r)_ILS%H#?KvJ?g;ww|stZje@E8rm4k!~E)YU5sni#OiWadu|{+A?dv-ZWA(QFfzzE?VpC0yke{Lt**QOJi9WVQJ zAs5{Eujq(|irYZy=ZQZ^(%B!X(tOPdK~o{Y-3-5(Ay!A{c`*3bGhS+ri?ModIPLg@ zn@*1iaQ)=v@A3x~%gxvbKI{b8b>6nX_oEW`UmSZy8vK0725;~$jc*~m5J3iwdZs+`XbhzK1Czi+I1U#^O z*{@2cz$kMG%+g=NAEX_8;1uunMY?}w-}$qAyk39DPW-3`uT7DG{qtes-R0A((B>d* z)Jve2JD`Dj99&ah!XJcV`;iZ&=fACsPkF?xWMJyyjd8y5DdPvQX9l19d*Q=*)pva4 zC3Py0X_|>Gw)zOswllnOO zCTVbF=~sV~KPVgzVbfpn2S3>ke>ctl;ikUhSKL7_E9O6#GrkS@XSk=V(<$J8)Ty5E zJGrD2om;EX{Gt58|B&AQ?KYT!-F?V@%;EV;=*sLfjjxKH{rm^EU)L?3U-@8NNPad< zAeuvT{jWKM;cV`j_dKmLrCoVppK1JT{w*0%K89XCd?xm|mvA$m|C{Q=7ksvxSJuy3 zW@@jY04?<7v@S^ANpt?nxFM3 z9wD}D-mfv0`69hP5SztG-&(_aE8KJ{rR*6)N^}@mwMUa{b}%{Szl}d=;^SzqR8?D6 z+XmBRf9T=3%m**r8C)Tn>*fZRP<<1hUGEOK#0qR7P0TWP={Tuf-gU>|Y-O;5a?^Ft z2*C&Y+xUZ8JDUBC@DCmGt2A{G40MwT_CXn9-TOE))7%t7K{VXyP-Lk3TPC+Nn+ zI~sW0upRgmKG}|JtHLb4i9hJ2S^l~)PoLIc;vw>2HA|c4Wf_kVpG)y_#M#3BTSt$~ zAHf!{7=iEu+t?qil5D`N6@`-sYrw`uowUirXHL}baR|RG{-AJm`LB6#7))QKKMW?< zmb1E*u~jQw)B&6`;j;!yA)aDN`ikYI)9y3ww!mzNQI;;3h&Pp&U%A`5!M|w#5_|9i za~78S%lT#eLD_fB_()sAZYG?+ehLyQyG)x<8%opW=al^}PCl^zqQBX4XIuKn?%ui) z0tj2G1wJC}(K7V~AJSlYb=f7+vwh>uzxVis{6Uis*?0`*5(&biAV!=8ZxbvKzMAx2 z4L{bz*#j3S$G7*Io5??htuesDIJni;t|>v6|c{8rkPGzeYrdGFTB&(h%~wZhK0|Dao|~oT_r)KS&zkxMz9q~Z z)9Mx+A6(Op(=YO99}9P-?XTwW>B{Nku9?B+iVw-YgAoq=eBC0R^Z44@r)KCaVK&?N zg=Ks55_9Qy@dsr;HDfI{P_$m}tCQEC;nq6!%)P}}YSY$Jw=SI3#W*^*;0{)Ik3O25 zYw)uQT+|snFR-bn1icEghqEs}QfoLYiR$;oA2fDc)~C^2eRK_L>@;x(-Fitn%h6oZ z_i*AVIL<^%Y?i>)qWfhZ9p5Z*NFzBoIWy%$`2pVpdlzr5LR(vR!E?btzllGnL6v^D{zgTXmv)zXD2|c+&k?Ld=%~yc*_bt z6a5Pg+q$rGGX?PV?}PJ+Jq>uh>b& zOY`ceUJYJ@teHyV$*79z8`x}xIetHdLpy*Z1z&x}dSyMjET6G>AUkFt52?Kxn~A#K zcf=o5eef5|b`!B}u{4W1%y;Z7>~Y*1C56&iI4I#w0&q`IP!1(wV3oAKQ7%8OM6lATiYa z<>T_&9v^+%L>(SqFpRl%2i~T=A;{Ascxjaa`J!WG1H)~mFx+GVPB1sL{Mo|R_hb^{DJNV1(%Fvxb*_P>9dT^guypSG;=$gLoPVY-d)$iKm*;%&Q}V}>i2a-{30}WnfcMZKJO0A?%ltv|K}Wq1Ce1Ylg1Rgb^J(;?=P#5F_{wOQ^yX}l7bAPM1tDdj>QiAw` zi9Ol@mq9D`XZ*o$jXy|cE@?F7KVwoK*Jwa?tZu*3+fMtN+kqIO=lwN%0UtaUR`H*S zKS-NO8f@^5Z7L7%Yr~7pt(K4QA=}*yXZu`WH;5%p`&MQ@Nc}wgLF!^o;6U{T9UpkD z_f-Az{&cVS6`k*`^A;aV_GQ>18Tat{h(^F7jjfuY>>rOmcwXJxAF(W{i_iEudd?gz z_?~2i7??%<+zPDdI)4S(>BjlMB!o_j`KiX2S-`Sk4>Yx%?fg4Y-)EXIW( z{zce`H79ZCv+uLZ5d07D2TeMZK5r9mo__xKbdzg<0>(G|<4vBmPp-nDdh=$CZwdL) z_--aBSrUg`JBUis+aSH!0c zZ-jNGnLkx0ilwYHoArU#2sB6GBGk|4dwNgTtbe@sn1pm`nlw;TCSJ-u(x9jBHvWF} z-lF^ZE-fiOA9`-qDAuM*0~hy7Wi7srd=&KCNwD+k9Q(HX(h_=~*JSh><*WQDogb&} ze|~PR)wj5BKBKfq+v1&9?wc}Ew!D08wB9lNzSrk?iw>_WyzBRWuTP49O8IqpzkY)} z=~TI!?*u<1onTQLJ?Dr}e%|lle~LZD^RLruzjvy?n?A3#k5^tF@1uR1J($Xubel3X zX;7X_Stze&Owmu8<8wW{$CUSL-XndO-(sz3vBx##sqa_XzyQ&yC5EMbHz^yp8MDl5 z@)h0io_BhGFE8G`SJ}UH=Kn|jpqEzFi^^K<#yehZ&)TR>zi+A?6lqgtJXOKO-1I2x z>yn@i<7ZvrEKIHzyy)1{ZN{;xmcQmO9n3ZwsdZYZKQCj@b9{2Q@vb!IFZ-M9FC~q9+NAU+=W6(Pz zue!0i)nJT0_q2MjjDYVTB&MAjNi?1b$4%?xN6;JOT4u)`d-9*6cz(#?AZ=Eq?f$4lBB)r z82m51gad;e4_r`Kka@50+CMnIh(D-4YsONIoyrH#i^1+5eKO%>q?7d6>Ad5}e_yfl z{5|0#=f^mEYW8VUF)+k22JUo__9Koe?P&)tsQl!~&v)?$$%f{dtnppb*y-Ed=K!6G zsTQvopZ&J9P~mwLs*VQn9(RkOc#eY1|Vtu9&&r;`&% zlg4!#a|4{nozouGz;M9Y;Y7L}v>_wdNC#_Tuz}yg&-_0AAbTMAt-h&`_^L6|uX&>W zXxY)|He2hQS8HMli@%)iOj2Pu&KMLU{cdFI93KPgxh_qKL)oFvlWyr;X3zz|z5-SY zAF~Nw#eDOGqxHYVAKd;${-EpuU}vFrcop;F7E9APT)jR{fwaFmo?OdqcwRZU!llXd zTA$T!Y1~feBNfK4HRaxtjxe0z4hU}q{-8h7JIB`jN$=FE9CzQzA5qYB#ViW@cbfE#^V`!k+l1d)6T5xzmo+Z_X3VOT@_-f4_}CXtc1CzCgB^r_flR zM16Q8`DU}yymaVJ8s+L`HaiYkx1?sXYquJ*C`1jN5xFv>t?h9{%8a&&!^jkat#lGP{99rr&mJ*F7?S zoG;6Id!4a@^}2N!cHt1V{lj(7@0+ar-2P4839ffD-!9OK{xtkS zidXrlm%(H?e$jvAS|DM1#CUbTOmFeF+R%}-p9a0uWpFK@3$4`8#vj}!3&FPz4hN2@$-oE+b{TdBp`;Zd{|j>T)G;I$iGC5M%3c~p&6 z`sZHy+xUZ;(>~JAwWlLPKD4gTi+Wv+D;SmCv>41TN0(H0w+MCcSBe{*PWW8J2g2?p z>?U6%u36e}NYFI z07shQV@)tPW`l(XY0DJF>x*(B_025>i_y1|;=g?mUt< zJ{dEQ+h(|(%4Z**y5dH-yiK z(egr*t62|F=U}fp;)jaE>4!Unz0`0vmjFFDLxLwW3s$9rTz-$ z=eWd41t0x3{vg@|8x5}N<56Ftm+f60f86j=6_-MFbRoaGm1a zjx-wKV(GF9Uhj5*Shk95Hvzu|k7|oQ2ruE;8DsZvDPKItPXIpN@15;^9bAq$e~CUM z3_jP8mZyg=@?H5N@IG?^dcRwj*kQwH+qbM?OIz8!WjwW{Pn&t0dZ&LAvx70$j&FCY zGthb^D6m@}tDTpF#ltjaF*c?Plj)XLhmHXlSu=b{Uy_d&a=l@=kK~~vEN~$%BsdS+ zoPjl(sUR5N!yoj@^LvMj%zrOoe0{H;;9k`PaHP)+yQq(zu}wsgNkjzT9);n&H9cpN!pL-E6^v< z1%y;OH zD$bs`!uQdv7LHbjNq1SzTlVB8{$Swy_=CdfqCVpGp%v^0ivuHcSWlTXXS}(smrnKK zzhUHoDKw8Yt(IiKXgbuW0zEb zIe%B6KY;TtAR9y&mlBJI9cYrz)?@W-pea}Rw)le^Qf7R$jgK-uw@F{LHw}%dt?npl zr90(oW?V~kqPu9;p4ZUmCfobrsy5En&a2@hkiD?3eB3g_9w#DNZFvFtttWZulw?TYClX zt8m^n*Re=1TNnmX;mz(C-|kbfb-sJwNNe=F;t!fVQ}ea2Qhv;V54+iG=|1{Tp4NWh zFp705H~+SoKEQRpqHPx!p5_AQ%opV~{K0&6yKJ}o!*P2T9d`2F#h>#BzbO9TyT7p} zv8V(5G>q@D*;5(+`5-ZIl)tWT7SA)^(G}K8dt!}-Wzgw}z$Q}8;+Y*Z@0PR~=;vDF z@R2xcH-i^y%+vXP{tJKbi{cNy+7)|V^v&tJMpMh?%*EqI5VtO@JAtEkIeHqjpqk_>vFghQps~*8$JcD(c^xb{4@UGx5Xbc z?IM^gk7E^AP|f;cEC_!v{Il=}tyfH_ z>HPn(_aEAh8#~uFdM%`Kq;i%hDrYK3ru)B&|3Oi!-P_08{eIhRTRfvVnk|V-p+FQW zU}6IJa^7|z98QU`WM7q*YuJc;=;z$hA(P$3v$<=$SiO<){4&WJA5(u&^{H}-3Vd1B zr)anA63K_b+;3;#&%>{!CMe+AU|A%$TF9TFPtq5uzw|l$!I*K$K&BNwEiwcf@WK0w zb;-#$$8BU15!C4q`HPvhUd1~u$Nl)?r^g?|9~3(;OPw*fzv546r@VdQ>e+`S{yZ*) zb=Gtlvn}?pGTzFm28+JLVDT2^B9rB)&RG0!@duSJGA8@?kQ*nQC=}Db@S65!WNnrp z8+MvU+AMX!#22RcW;_aaN6vqjKPa_p<<{!lZ;iZ;65He(?Jc?OZd{MS%X#yTL|^dL z7~h1eBd5;!Z7dhQpt3dIC(pl584v#%{vbbG|7w@ST<3kmJ)sl$cH+;YP11JB@kb6F zPF~mfjL1dKJei-qP9-zC`Fbsn@;Y&BQx68t$|Kba!U-4)8iQk`pbp4O6NopanGx;0m|H>ca z_Q@?&G76USCF{3#$@j|}!r#&95A-SIs7nFJa4p7tV4e}4Uy^(BwZ3_O@B8E5e&_xA z>;7R^Z~grC{sX@yr>KDV4!#$?$nXCNfADK8;a%U3H~&t?CURVIS-wNzBeLhB*5HG^ zlRKCGq>kV3@f25*{hz|P-unK%9KXGO_p_hG9}HV0`Uv-*a<4h)aDtgA4kz+(Eupz4 z>6iS+9y!9XOlvb%Q6o_L`|tH3_x-mv|8~#i`p>LC_?`K1|Ap(IG)0m#A!IFh1*p_p=c-FtTgYx*d@&_%|55MeO zbnw>0yLO+tnF;!+Y`8SdY9+guUWGMD5$wjCfY;P`6zm2b5%_}2#V5WaIq~UzkK-sV znBX_$|C7J@CU_Nf=M;}>EVyD>;U0r#{ssO)r4j##`*@TdH1x0!%e*S%B7K%K++%P_ zj&PijU{GEt8PsL^0{lU-vsisvKke72)WhqhebXqD6Hu}x&7k7@O5F?-(FaqbiTUAfnSRT`Y#9Hr>U$pnYZ zCKspp<%K6GI{7-O-$xxgV&J(h=ikg9q^qD1@J|^t4~$KrO(wcG?d*EwYxQpUfTX5i z4*eT&HKh&^Wg*SZoIaDof6D5Y+@ezJNc13hiS#ua9LyB1n&7p6a{eU#V7R^(PLT}Q z$^@v%c9=LtyGHFnsZnNz^&s(SnTk_EyJoL@|5}5m!@U+<0j{CsCZrY{eJISw8Rj*HdHcY~!1~Bz8QNr3<<=Fws64JC=h`2^T)k#@3{t*lTj&8j zk@pK?C;CATHn^eS)Bg;AP^}4MPF1oL^jf{WqA%0W$q(vLd(f;_!J**Z3I5*&ugx`g zxnwK|auw>qO@Sijty%eb%&*SChsZETe`ER?`Bl9Wxbr{AAJhuucan9ErVSSrxR~V5 zRXJO`V{BONDfr-;dS8AOhJ-(DZ4d0BG=JFYl7FeS%EcO~@}<(gW;1qo_Bc7K?Y*$N zfo(a05B}Nd?W&E}*3T^3qs}}tyZOWT5YF3_yoETJRNb@xhx&uz9EVQQ{aY4XoUvy2 zBIhpmRB{2U+OF%a)aq={+V*t|XElh`LcB@phHWO!V9{Q!x-Ga9K4XXMr=%8iS&i{B z&i}XbXYvQtzDMOAp(fnmuJSeeW5p+Rie}w21y?f$*WM}KYOK=a>eHX@b^F*2d(`!U zm(#)@)FR(wZRYRe)0dxaICib=n6-b5KM3ym&0*<&r2pNNE+6QpZcLeP!xN+`UDfeual2PTj*i zRW!-ZxzB@Z?peERs0{>nbq}T>oT{&L7?)g~>g2t`*AuQ7_%)ve@8mx4`8)mfKKnn{ z9}Iozd9aVBTdWd?aKj#&jZ1Il^yUDx_tkB?njIxhBYCVhpSv_zS}Hhhwjz9R?f6yKs-SwyN2X!Sk-0s66McO_|W(h_hb6piV z?$EUvsT9=az#lvW=#+oxP~=xN)jx$lDBUW7bM2C*eBL$WdPz;^HS>lOc;E)`2OpPHOZa3FT?_4l&RV=FMd3C;`jJ2 zcRoEnr~V*vn3Mpdu?XP^FV$7Cl|y_Ba!L4*V&_9g_=E5fWM3&biHvjQ+~@EIHSN61 zS7;~WD{=&TR8V7GNPMrz5m5IPypW4xC;rphQ>0~YUfGurEMO6mxpRl3i+neS?-tIH2GpKo#m=JHo4RGKW2q*xWIp0{qHZnyq{ga>dmtS)H(#PL%2Y&UdzvHg{@89`LAOHKk`(Hk(a2q}t-gjBss=bE7LS&x; z?klkgtid&%_>ot!q91yRx$J2wm&5jB_=B{EgLn#wdkvpTj#{22b*s)kOYkX~^TTF9hxuyVSgo?P#}@vav|H-*4R$`b zV4M?d1kU1z@CV6bsT>WG0}Ct{J0Ok<8G5&5;#DM%qwuv~oW?%%AT1bNGX_ zJEm>LCn9oCW38Z_^6NZ&K<;&u+KyfE$AQJthj!p(e&eurw0-+}tTv|4!sqY@C5N!c zpz@^V)0K9@HBw>=V1lPUxkllaf*YG-xRh`l{j9%R_YXI3SRlt^>2vslYD{|Pg6wPM z(*vAyj&F2Ktbz@f7H)*fckFl3&B)zdFGL{|6F~efIo!yvc3gJG@CV!RRx)w6*S2=f zo7!!gqApuE`Pcb_!`8j9C{`y|#+;S#f&|C!Hm~Koj7gj_FUX@fcJT3r{i@d(#3UD_ zZwOYNlNepFLg6pRn$F->KJ=2{26H%Ny@Ma5+u$_9i?SSQ^sQd8wsE%3j1}5%aUOq- zKZp-m@Xq7SODFTyLhFo=SupP1daxCqBJplAuQ6W``=;g(6@!@HcNnCRu3S6aB5!KlHS(>Wz#oit z=Sj((S2-1Om-3`-IsI4O^G+?J)*maKgn0l|%oKrF@ydBS^CWk(#95H5nb?s$`9;S! z7hVn=^I__m*ypo7ckqJGBKJHIyYJE&;rx*+l{#yC{B!7sT9F}s+yVprYy80q(IKMW zy)!tEFDbZ^U(#<-m0@AkEYbsHH0fw-ey;uat+UU zZg%I|pp(qJZe9-l_F4H!nd|fSVk;>at-=6BFLnTju||H>JQzDQvi>4}a0IT!Eh|i) z)dZOE^6A~{cT5sc%l$s}PDvTCkVOWs^m=s^e6y+YLkRXvT-&m9979RTG@0M|n!t1Qx4&M0Fo+8dPh2NCV@u>IrvBt= zwKjXHB(ZF{j=f%Oi2;xU14(F$PI5%t0^E1WFPfqskz1Q&uB*p!R6ZvL<_@PcQb3N^i0 zy{s3@5!`;GGDtTj?>;4Qo=P|UhL^rLudG*mHKb;NaL`?1e^#B5-EOp(ucFc4turgv zOwI4bG=9+*KE}VuAKYzPj^FALZ-Z^M=B}S^sl3oezWLfYtc&vf^VZxgUb&J{n>q=w zW#VbfbKZ{6mxCeml@qv;%L$J64`&x7+vEu9pUv2!f z!_?CbY;fA;U*!+}#QKARamzd+rou@)sSLzri@ZKurw*R3#)5XNRJ%B=OTeM-sgS?Y zQoiKB#vlAS^#|F56LKta2nH&+r#wX-?mveNX(|?+{kgX3+N=#*IpW7k{!rZDiW|k) zE5O13${+kW^#?;8$b6n4mRj{G`j6V9OCO{Dgsi_Tbe2fG>=tvI4Mw|3fp0#+0B#6? zpZ|a75B{|JgNlzP^P#Ml#0Hd&h%PwP+L5(zUF)@qA$PD;D+l{M>s*C>yhIm&g+KUD z)gROk;`1qM`+kX9YG*K;JnNh@@ffOGsXpZnKc7E{fy4^&y6u$G_h5JivklP4qU7yc z@FC?;HuCxWLFR~g2fv8if2lEA+NZ#6d36WBrEf)rKZxDjclQZ0(C9OJsA1V3Zr}^k zr6}7T8UCQ~Qm}K5q;E`boLe;}NIoDnHb;a%80IRA>8xLbGYG~Bzf0y7;hm|u6F>0h z^9NO%C4U2BaNti5fnCR9SR%jo#H?8&!XIQ#v5*EG`2OMU8wdE0@PE}MiQ7XbNX7&t z<1?2rsDFV!$f86RBK-WDTPV*D)a0|&x`gXt%>dSjy6-Qkk+H;Yq~aB1%|hGdeexB* zKmX|ZA6@%N{6Siv4v|AJoiAMH>$(OHjr&ba1!^WvAJnl_z7i3Fn;-JntPkK1N_#?X zRM>KnNBDzshBCeHxztRQ*!GL?AHhqww}()b=u+0mB3gLk?Ln$ zuhlb$kKqrBP0JDXp|5@+eTs|pn{t~yiK+tx@hh=A_mbwRXM%T*$#a<_|JbMS2bC0> zaA|oaa&YfOHe|rIb-1U)d&S(ZSC410Lq0DvMNPgG{*(;34jAF5@CV=e_!@VWt+4OF zFHx!Y-Mc%c?aIeU?z;{-eGK>^f)z?`Q}T^|2!BxZb*Tj`1}k$kV=T&uTMO&u6u>?_ z8w{tKhSLZKwXp!JW$dler>Irt-P+`*MJ_ml!dFvyz*2Ip67nMF_|X1@J1BqqdHg}_ zxz4;C;)Ah6KU0p^Cl4=&UyQc;CBQ}Xi`VsPbm-iY z`DQYi-K{Eb{-7zm3wSVJ{K2vL{@f2Zgw)9NyMs-(vn!wLr-b$>g=+*EX9}8i*Q>8$ z%78m+@jmWVb$D=QzOrALpWlb%hf)L9L48i;guJ^p`GHl=J3dEUQK`47_>437be&1= zxHayB1xQaG`kx4U?vH{lNs=HTjT44_ulKgAzpeS>L)Yr9M=GdfULl(A^A ze(Qi30O4iY_^`3_#lxi*PSpgb0kbJli>203^#|b(c9P`p${n3^{%9-yU}5I|8Fx_r z_Vf6Ij7^87#Kzz|%xLrW5uTIqmd7*lC~{xnUKdqf$cAqYMw_RH4F_{D8v57*AF@M# zI?o+%-(6?N9pMksPi5UD2KUeL2Q676$xkLyvPhziW6m$$;F!O_HoIU0*t&4zMIIx& z@dmfOZv@M;yS|fSG!NGfOmMRG_vx{mf>k(Xy5SnNwqSbySp7lTuEt!9t6g6)S4jRu z`ViQlw0*Pc%v>Xt({=0#n_BFNIr1U0n0LVi@zGK1PI8M%9#Q*ja?Sdu z_=DKETD$7#MX)LoLebV3xm$Dj(`NK&B+8drd&Ru{qW);n^2{@StX?}NoCwB?kKqrh zbydi@dG^UG>cc4?+)~2ZZq$o0$kvqFVEt}IP}K*kKqr>dJsFG zJd)(&6x+@b=Qf{7y;u8nJ!C2c<=An^VL=`M=JeYMY!m+No;U;Qa1MvWaeM%OP}Ld5 zg;Q%!;oGeVw*o(JO0J6)!^G+M}3H6Du?P82+GITgg6& z(-MALJ)S)!^0Q^dqUL#al=7;xPO&SzX9{qi79FB6>)C`Z>*BJO{uutC+PC6|VlEf_ znfXx0;XG|*T2y*6#C`-DIXM|(lnR}fxnFvv_|Yll50T*y;{VhS;aqWa>ig|lIFM)X z<~uy}0Dew1_=9TQ#X3^f#7C!a3-&|i!Mkv4$oa|<75<>$x3V7QJok2jdw}EI!4MoM zLx6)^i2{F6t)t%l2hSu9Yrm<#Yu!0uwo)Gs>^TDbL2O_AT9i>_o_~>3Vc!rn`1{2j z`w$s;83F#FjA4gFYSlF*R`KYUdS!5C@MgN!9)XY|68u3+)?ZrU+6D5t5Q7rzLq7=DK@Q3FsuhyNlM<7$ zn>@;GwQrQG?5(PGYyC0&!Gmg)U?AYHGQnXFD%L{P(O{n2sx|w)m{^P!)^Oh5nU{Pu z=@hHN|01scL->O-M@w8HYe6MLr~{d^Re*zTX|d}0uyD-86}Q$4o>5j-yPSemNuJ0z ze)BKa9}HuX670uu{)ld5?U701E7Us4_VcpIg6Y6(F)On$W*ojz(G*Mte-?4@AHpB} zS~C$}8Ph{9p^CNWH#@1jdm?_p5FP^gPOtbItHd-=%g-0QhTM=U=j_Mu2j4c0T}a1b zEmet67teuUX{V|`xQYLL=$RDzGWC}~Fxzmzx|>z<_}Jc%2dv}+>JQSN-gcpIP6Dmk z+NoECa|37ABd?{O6I^!fn=5b|;aHi}Ci6z!>&j{*D#oYq2X*XNa?8KRSaJpzwm|*j zuO?TV51&T*5FA3|N)B5OoXjYZKB{ut5I$aiwuH}|BhTF!KJ5uiFa{q| zcz4g~y|6ph&JPI`g##sdOlx3JAHp9L5oF9oCpx~-{j1{zJD=Q>G9Sbm&R{(R69-S& zjmE9Zb+a~x;Aq2Zp_jVssD!&BVIJ?0BelYpWsdZO1TeD>1U=_^UGw&JK z;rO0mt+l5fr?Y_TEd0#{+~CjP4@!=VgQgAB$%ZR)x6eAzXRP&8BiHpC>*vnOj;y>_ zJX*b*3!gS$CN6`q;JyX7-FyyzPV*#~l zhvvO4a%k>8e|h?~jZ^B`AH*LF_k(JUC2@*s{6aUGwCqV}w(wRHzQ5D9>(!>8IxS^PoT4SvkpirOly-8sW}Me#?=a-}WdOw>5evQCkF!Docnz{?@G z9(4%4p*Y?FLjHCBAgz=G{9H^#ondS^dtHgIrsk5?&R+WkY?@q22hChhiyTihRJk14JhjEI3i+M$O zQ*FkxXz&MhhBD8%Z188R{kvw73rOvQr{TOKb=9oT=MSM=gUP(+AY3Rditik?e{-Cr--RqE7q+Y)NleJY0A4=9Y`#bs) zYe=vWnNP~}DOrz6)VErXz30rYxl=vLI_>w@|LEFJ;tyK#-M>48ntZKTOG~g583*M0pPhV0K1bh_b?AS-U-sH^hQ2lVUKN`c z`aIRWP`|-_r3vrjdp(5h|Lt$QMb_}Xxjk@i6L5uz$<&DRlQ*IhX@?yD$<-s?pBi~` zO}_i9z5iV%!7GsCC)FR6-~5e77&etA>i8Pr2OsrAn|?+=ku|a0_i%kLwFzm&2h<-7 z@2B*m-}E5QMJ8n9A{dD4qJMdwjUkJ&6ExIFSdWk44~iUr+P5stqc*BhTb8TwZEvw$ zHO`xL`Zb6Z$xWF5ApRhISaJ`BhbZRT^8<4P*rDq+^h?kDz(?S( zeF%S0y0_Tn*YVbkP8GOpwLY1XH;SBzY2WVRs}@XTO@t`iEW4S7lK|i7GwKgYzt<$! zf?zpe-X$KjM1S5UeEL@9p0|i=$KPufR6asGMJ_6Q*nTk%L3Jl8o1In|WPN zSm)P(y#LBC2M@=eCGnLaOBJlJX}SZywqB9YYYQJz>aTqQe~@vLwlhboyqq!JqW++> z#yJ?4NFFFKguCJb>W2@O{wx-wA=kN#H%*AS7j<2VlAblK|nsAuG z(*}~WR(OiLwB)&?j}2e$z{^z*g-datca8M)bNGY8X(oR&HX*ekO6Lqo?7;to>*Y5Y zlNgVT9d)owYIMdrv(~e*Ufo*6hf58#$>;C~)p~_Fq#)}YtvxG{qoj)tVja(e3+dV8 zz&xg@YdN@X%|xw6Z7+p!icgn(iJ!tBRQo#_uY?at{>%03zXhc`h}9%ZZ&EmD%G+EX=Ct4080j zi~lm?71xY+G`0Rqq&|l~C_Y1#w;;D&UFR}KV9zo~6jz<=9@3iW>}DCKkn~#DCpG%g zCK%L7HYb`kO@0i2P<)8Y9Z7AeJ-0qQK@&f&(RBxQCUY!z%*Ei~?4J2+FL|v@8#=id z$1|clz9*vUp-gC^=GWb##LVMoV9+Atoo&Wb#^H9;nn&F&derDlHg_-FKg==J8o8Fi z6V<7a9H_ z;{dtTE~TkfnLPYTzm+BbG?+nvpSnca>ZtGsLpe_6OJM}jZqGld>ji&s@4}Oc5PuMT z1ln=-tR`tUpaFUaPcRX{!4hW#>JN%PEik6*OJPro!~O*4PM}WI1FthO{6X=mNttl$8gMIJBU8eOeFY&%pLFs#m6N+YM#lVa5ahH zkn7Pne#!A!ditf0U;6kv?!d2p^>^IWKlx5e_Dvk(R}{?njUiCaNMXT&(SA`!jyDuy z`avcV$ra3_r6uZ##OLq_rQL$7g}66!o9uIyFcNnW^M~4A^33Q~JzlBRmy*-#Q2Xw^`^VSE_$Yr;!`}?H~?@m<7Q(WvwJOko^q&LH>!xTfDBzuL?2ZL>!|Z&Qmem8ncq*J7*e7dP$C z;SbWU4l>S4y@GZuS9bfaL9RfqIDEH8(=$6@gHpdQ)uaYfp1P?EJL|)j>Va3?@l$_D z{XuX8CN^wbjkoDlW(PlI-NZJ)22a?<6&_?v{MP2JfAnz1F^27ltIkV}K74W?!XLCG zUYdhPgo)q#1J~c#U?DN=!(KOWkJkKqrhH6Za~j8iXf4zHOx z)vwmcZP{;5`*YWuWnP1B?%K<`^;r>qaGG4ILAP_=4MdM0#ve>H>TQC&yF=zU=IoTr z7rk~evv-S~ofR+^e3>JLUNLR78#!;M=El} zm^WfAyL){)UL$tM9iQ$Xl`7Q>PsS?nsXMszdEy5x^6Y*He^B_^tko;=euEtC8|0ww zpyV=;@hV4M>SIiDeUJvc-l)07`_?hwv&@4Mxl+M7KZZY8E|6!Ou^0O&RLhn5V>Wpe zrKa<37?>wLVy(Ii4)8=}j&*ggaQf_8sEI)%@`p{6X5U_EBZ;0i1n@cQy*_%J6FcrYW%5Uhjr}yQ}~0rTI;ebk@;NWq$SRhTsgX> z#n|Mg9A8hPE2)i2MD@j#HKk+j4^EK3LkQV@41ZAil-16l2c~o6K_473>NH5~bk_B) z3*&1VxeC*4EYnS0sTUVG;DU53PVj_J;15ch)yaHLKhbqdV#(#8({KjE!k!1}+inFd zIEHNxz-kv~c@8(~Gx&pF{mK$us2KYZ1I|eHVRb)PJQb$-aUkqoWINsEy;6>S%eLxIeM`kW(x^iLgI%L5mdr17zAw!4aAF)`{C~1O@Z z2Dee!hN{b_E^7oU8XKaTq&&olbR@CRup_miVQ`&IlaoIq;a zp#$a)YN-jwg*S=ms6Hp_7d~^4|3&|zM_Cm7yY&anA05$(73(Z3G$l4q7@ zv>%=wZ5CWa4QF!y+sW|}{6W#b8h>cJ%Eu!8U;3367#93s`c=r&ls8IWLT#flkw5D2Py!MC_^rp(ggfC+F(*EFmBPUUn^NaXcx)0^4rV1MHK%_28yMD$^XqT&D0SrUF?lEa z;9z!s6`Y9Edo`u5jq*VaUU|Rh_Ya#`CR17FbW6r}8YurPY3sLxb-~-t)fg)ES+sP2 zaT&PYsNoLGxWA*_o{yjB{hP}FF5Iaqxw1ZkKZqU}Q|kyOYj*mRC0ykU`LGgfyuqUU zR3B`r5#IM(-!~1p1~*dT;8WNTSf=0X3nvV064~HXsXAs&e0p8s#Nb2vlhd>LE~$f- z>W~)@|G4mg@MkLBNj)@v$GZ*T_LajLj=8S%Z`Ok`-TI~rHNMI#`cYUfkNK_~UrwFk z7+-sXxlm%=$+fH6NM1|d?7DpSrgOA!1tW((YQpOb`Kr|VlX``|U?*$Av%o?{&ObY) zo?b3<+h!l*R>nO!jpw~Ejyt<%)hXsO@c#G?YNHkDYskm%w5IJ{PjDyQl6uDPL*_Te zSWecd7+P&kuj7pz$D2f-QtWC1 zq3e;R)ko%3%_$mPUCE&E{;C2wcbw-~3u%O}Dg z?D*vQX$=E=vvEtM`jVtx89h_!Tq~)4Zt$XR%kkEqUGDDl|4@H0SAX?Ssa4yvW{=J# zD8(&5$WL5*NPedYo2&HXw#z50i3BBE8#nYUV`QV#D6`f`sL3uAMD{^y{6e0D-kWPr z>Y6rG(Eil3j{x~o~pFE@fed^lr<~loXR%#>RhYH5U zUVwo^)|Y>Ff)U54iw0>wx#^B=zm(>CH`K$v!|!uU-<~YJVSaNf4wHp(W_;@DFUElS zp}V6#v*Jm-#gGSCLuu(a>%V<>a3yv@#u~WUv)IEG{+)2~#y#sk%B^0+m<;2?Yu^a2 zgQiFBJ_2ADJI{9psz&6nL@w)6$F+Oi*I;k_sQ#d5q$keKF&?{k0{zOpnfk_}4jwG| z3@5YYyxeQ9MlZitK5Wc$N+6^v-szmJYG1}(Gj zuY>r-891%-q~3UW-GQ@<!nt2#QdN}Oh7PeUssKoRZiUo@jUI{1;&QBoS|?FiG^=be>6Yx_9bFb0^zZa zf?;|Rau4C;3I~zb>bk-G7da(2rsO-b9qMDo`5xp)H^-i7_vb~^Ucbg(Dc{2{yO^{a zkHeaufzP~t9*;5clc@cWmLShDSXz#`IyWa5a{V=sF?2U>H@xZ1o$L3)T5C?dBELa< zgUMr8GLD=1*)Np_*vCTd+VCZaZo<9_n0lo+CMVZ7s6b;rw|V zrjGl5Yp`q0JDq)gjbD%ZfeyT&HTO!?`V9E3a4f-Y(%50EFS#eTYjZ^E=@>&-?cfYN zY=c953w4eBo9MF2m?kkLW|uLl{U{tZiL#Zo*Nw+>m&;dc({*4tJ8BQocKoE+dr;~v zRsF#rzMij)Y_qO8hn62dwmQ#4#?e|B-RZUm&4S0ewP|mXk5G=#&du~7?e3&@?o0X=^1OQP z?iw52XVv9nW|KFy+?du|_gx&nJM~2UGjimaE5SWgKEk+t-{tFt>fyvXl-Qdxr&>2) ze`15*pOSM&VhJU`MMldWAFbygUkHpn{b|FP?(i6&cs4vs-x1kXo_)6P-$@(=uwQ1n zTFy4UcPb2SUXCvpf0%q13xSN58y!lEOr7N51rmSBxsb=+EBSDjn; zx+}#V#WXfwTFDsVlUEo_eH`pt)O@Wqo&%@g8l{?VmKv^^@2S&BcO5_8QRgmbi@iF< zd-GAe*F8h-$C)~f!RqO8eRpp}6$eS#}zeQ-0*GGRJwm zywn&6;Bv}ZM*Mp?s>wMfI%*{g7iv5=p02ycrds*2RbFPZ8{)EFyje5Ok88|g?qp4t zv@X?BZR=JN9ldm3-l)U-sKyU&xwdsmwZluU$yttX@8#OzQJ!3$<@4jE9(kTWPi;)} zkv+Qon8m)DF;>=2%5PqlUkm@!SreAy{qnART+JTO8LwHJi;qV=O0kSL{zSW^ZEF2q z*Lt_5;S9=q-4gsj`RY_1Zr+e}g4WqJ&X#bE9N#$~cBLX2NOP0Z<#n87bM{2n?Ak1~ zudz;a8j__aE%j1`Sm2pjdJ<6A_xL1M^$E_XgX z{L{%xoF{|aaYE|xb0fKrS7O_$>ue|GU_E|3Cb7hMn0^Wt&sVWbEn$0NC!wu`Fc>eJ z%0@gFwwCC7h^SIYO6@Xfj{HqOXY`fB@^E~NFS=%wsL%yH-hgGUoPlznAc z{9$y?GX6Wk8hJ|J1Q9#5u2<7)UHwJJ>}=NK^{(H1IEK_%7IlN!Vdsp2LPVCDtm>YL z-sjn|+9c5&@h$TkzdMv&)30Q_lH+T<;>X?HW09|3cHAN1ISaU_j&IMyaqBbqgR0#k zgWv%2FM*$3>T7Ss#zWbZfFJ(fFF8I-LBI6zOCNv79r)F+{*Jr)zkjD-XyG*R-WwLO zfoWZtL-29&H_?~HG$Qjp&)@Y2nN$Jc64MXj56U``Ij~%&CcWH_jO6*SeZN4?UG*9v z)O@d%&xh@-J?ortO*uuCmk{jYL->REbrqH%vS@IO%6)RaZShp?G~Hs;iw>-GHh=0J zAJEj=z9HC+0S+bH3TjM!O8r6E=Sts^c(}4)gXE(&t=DyPxQtuJzFRoaX0u71JMgU+ zJ|4*}iX67l_XJz`82+Hr1A8g*u^+4&5|L{uQ}lLEumHjAUid+UmjlPqyGf2$e80^q zm@W8@)VBN_{-91S?U3h1Tm!LKv&DmWcJdMVYq&V$F+Mna`qcL#ry?ghiLJJ)fpzO= zePsF!{va_U*adq8>0C-Tv0Fd63e434j4%)OgMU#l+A6%xWo4o5}}Ie}WT29VP>OaIwpE!Gh2D|G_Qx!XGq^%+X4PNzZ<{1RsHwpqtJ{!$n)tHPVComjm2X%fD=w0z1oz!hfmhQSB=lT z)N9_i=S(%eE38(l3-=YfG+M1$AyD(0+JDlOEJQfS93sik%Z1KNTli+u^X(b_;aE*- zDk1~;Qgv{38&0*hyelkCYGDn9{{dEE>_<*903Y<*;`>zdkQxK=M~mO;>r{D);buq& z{&osSIT6FJpWnSqcs_f+GtVY>vh_^7W2J?>Ufl=jWd2m|pFxPZzkPc>yNW5m_ka7e z_)7Urkpq6M-R+=*c`Ptzc3`I(uK{)}W7N(!M~guL>|qy_(wob6{<;nF@QBfi;1&V6 znz6vg-`aRaspAaJRo71Ai*~??IR`=A@zYJ$$hYM2+vzz?&u$IKK*etcW8c^eLOe%& z@A=*6VUU}7)_r+F<>L!K6mFbHKhc1*Y1OOnzq9MrB;i17Hkmyl=KPuhu|YY z9;^ur2K?d=&r-SvE<2!)5_B%O)DXXGehqdf-?6IJ8HTved#6iYp^`NPQ`vTAt6*o3 zwz=XKf0d{}^eeiNI94#K-5Ty=iF=>8_m5f^^h~$F2Y1c%b#wJP$*1WLdxFodct2~b zO!6_9WED0ccwf-6sUauWk+kIqc8tFhJgpS}hOa3sjn{Hbop!LLy$mdThB|s+wc}8R z9{2QaTIuALxj8+BKF@nrj+t&$C(F&tOEsNcHCKs0=G;&8A#p$nEon{5jyGp)jfpMf zE``i))v4xEqh%lFaQ%{>-D-(rf<7xYIPBc?CbFb&UOE}P|dv*C72qqx0&)9hxHu)&S*u-3sGlRj=JLj>0XR6dpUOP^~tlqcHWWA9U ze2_kJ9^Q$|I661nObWwW_=YpR4NB=nwwWI-uD4NZbi$sy-_IPd|-S|F}iXYOi*#7PX2i#`zsGhe|`Y}^Y$az@iV)othN3%|S zmFXt9-+Qq14KW3R0}3uY`VLzgDxC-M-s(B-^;21O-|h8k3tlS&uJTjQgs&|zNc1V> zAzo>)di1LW@WIUdQ5+HTh5T|3sCq_2tf z^VX;T#BW|HMW4o=sa57LL?4Vb`3e^9wiRs1w-M7crQs(o2K3J<#wYv-+{UMyDIqxsTn?YdWA#}8btQ`dy? zj8IeP+k?k?Q005x!f-QO2OU#3{%jG2XGt+3oFfjpOpMo9XI$Tl6gUEpHbb ziv7}*j*wBC-2HmHyls&{_;$q3=(JrvXVfxF_O*F8Xq_DFjohNdEtGD@!X}fh6snVR zHhCByv&VBWyRTZ#p;k#8;>qM;QcUm9dSV~D>W5l3bvSpj`$;i{Z(cX`={{LLq%Z!k z57xN#iNA9EVE5docdos#A4aJy^8;-usCLj|X;UaO>ssLqitk$Tqgwp0Nsy4y1)%I~~4r0@}dCE+O zRckY;)(_L_^fEndZ|WQ`uj5nwFp6nwtE#OU<)2i4kbPjRTxQZl9aJ_z9%@T$;dB+2 zw4H7y_R4}K*6umXaliT61^d{)yrDSv1vpsvgXKqkbsog+Nyb0L zM%q8gALO1@;H)5+ZEA=Zpm6mgENF3Gj}V$l)C?-CvJCmfqtOkkz=0kvd(vJd`=yN zCzRY_nl%uIU^id5n!<5Dg+EABt*P`~mD8C$VcIvA#Hu9l!>Kt-8$ay)HyOTUkw+yD zNi9EsKZq1Er^=i+HLc` z?D$hARr#K8M>y7gdl}kyA%z?gr=fV}$guUzgM*DH1eN2lUqdbr4mYn}4e^9lE zwqWyCJ58TD1%CU=YiXMj5Dv?4apdal{HJ7)7azhO1n;LY?{!Rq8hzFw@GW9Am(oaN zd*A!FKE7Rh_s@^v4=OvS)-F>vZA|)m4IsWie2g;v)O+osny>!*riZUf=#lxF1-bb0 z81@**nM=dI3fEQE1Yf7}G0A%FyKACy#(R$Ned=p1^*#Kj#t6Bj`m_2Q|9#o`*Q2^F zT}S3~iGL**wS71d$H4wwLd-JaYt-~;@CTVARouSX;|BhPh2QoT_9yOBMEHZc2JctR z>9Pifiz@o?+h_EM-AHalnGZx?(tkup9HP%p;}6Q7C0v`xS{KgX1^)|iaN+(_*6s97 zRp(JUF*YFm_yhTav^`wc3Km67qUqX_cV4ys(61;xpo>rE55hAL8;~)BHDn^?`v-!c zsADPe$+!{~{-DZ>A!8P{fIQTAeNxBLSL2lEK}3uOe~`K#Z(BwVsik&z>#{f3M(xTh zD*Qp_E9N>HeGq%r;=Vr(4!P-dx0-=>h)*se{6RIJ(|s)Z7W>#&(Qh3n0z6nO6>RF~bQQ;4U>kiiJ=%U%EzrY9Zi|Xuc&Bmi(=#k+M9wd)2or{0= z>-h|fEIAZ&*?YgMHD?9o!-@odQ1)Z=CmkHb8FVGK2mZgUkMG6e@@3>B!ylA&;-O!z zPqj68|1dC;4|12sS1Wxq%|M8c41ZAckw{P5Nn&Bh5$r#SSEy?1)P%R_yi1LpNjbVKe4Bh`-ze^5FV zd|x`3*ol_6UrY1s%nI|iXBy*WIV$`?{0O>k$#zNN6voej=TClekc1t<_qF;N`ZNK1b&@euHZUl6;sAMg8%nD zpYWVGOTkIhBH*L=gQ|Waz6M(F+kNM=%zKZyH^nBKP>_3P@ny}vxL zG}C|=CiUT>!5L+w(-_AVF^D1a-Gx^?g5{7e z*Nnj<5gw}K@cVrJAaexxCX<88=kwHF1rHo2hTnY+b`HlpBK$$!LKBunOoNuV^elKU zrl#`j!V6}ssz!xBNH7(#V#Ht_wAg8rA!ez8zuo9a{^t93T#68Xka1UVwTyOlrf|mQ zv@Wnq^bD$nXa(YDFN&=B3Z5RI~N%3h}$K*>g}W)##gXOM>tEd6>;f(*IoiqNoohvhKPWM*2}$av z-TIg3GPA8uTG!4pJKMpV%tVJjSeAKE(=GOc=HvA&7Cezjrg#qWrbdQ8sN$8tY%@M_ zyPjRY%J@a>CG%s3`V$f14@%BXY4;&Pev;`qFsQX8d_0BM%Kl2?1R}s6l>UPp66;O< z6=E{l2NmNd*Oe?X3`BrG$a-DHG|*Q3C2;j+5idFbQy1)6#VJ#N@bmeDw3j6oW0usz z@qFv7^kAu+l%f<+9y?-SU=8qZ z@&`jZXS|g>Oz+?Z(TDgMrGIfof)mj?Qhh4|{6Ue!k~PUeX@VRsn1rm? z6XY=x+ZFryeEy*Lb!jO5s&A8nK=BS#+o>_4Tk;ph-Hby0LHZH;u$O1aYasT)UQms- zanS>kM1()6)`Qe!p!Q?P1CjAd>}0f9ts}!9q`lYz80RBE7rbIlXC1$J?(n_m#E%t; z`h(1MYSQ!U=`gOasj@bvY*yf(2ElF&4>BVBLF_^70{;AIwbuMfZMvd{Xc=D|ygTZX zMWz0rC1b2s3XJ+>+`1H3s|NYrsJ|#R3vmL`x4=82P=AoMAojuhF&!=1!&9%xTmqP5 zSFsIhDMp1qDDlTEbj9a0yt&;&_eg#Q$twy*sQOk!_=9S`)(p=tY)9z=`A*l^N@@}e zUi2-q8x{T_)O6iyisS7{Hv+vc+n4*-Ix&_{vgl?wVbbgZ5G&L`WN{{ zja++`)d#aqDia<4pvonac=YkL+a1>*tjQysvfSc4U#!-fk>L-LD+(J)+_&|e@5k^r zRI%|?U+Mzi-FZ1G{6QJ3B(CpXsISNAb{)>0M?L^}w$-W2JQ5lHpp3i3Wcc>Qon-o3 z_8aNZGMQbj8dhQ4E<}bu2=@^=G&e|$WsGGnC^Zhy5l_onNw>tG6@mJLvTSF+fnSt; zlRMH~sPa!5_)-*2l;52Y)1o^eJTdc>dszmt&J*B@jrNd9AK_ZL2^370dkv$u^5e~^2PZ}))^ z#c*G%HnkbzOtk4E+lmZ-5MQEiCL|9W#=$?U4c;vIAd4&CO!XqfA4DJS0}w>ThY8?3 zX=fYwu)w0o0~s0qpyUX@?1*Df`FF`nHhb;573w|WTO==MMEHY@LmAJXE>S})25!E| z?kFnrlDvJ$ATX)!w(&eEV9C5PvWMmUcNV+t0ZV zKnP#EfL&PQyRNUY>&Wm2sRfzv&4T?XtjpLp<84kboWVMqr6P5%7#aSc8h7gt$D{tA zccTWQ(>o?4RQZglvA)F`sstxn1^W$n(Hon#u7`NJC&$JR13{6PvFvfhmXWAGC^?AOM?G~F z7pG$5L>}}YHSk0>*_%gzKX}OG0$cnH(vPT#!(LG2;B_8OAY%6fMy94{a=+O5Vd)qd(? ziB6)zAC&!|1*cZV+&;1h|At!Ps^&T!3;$dc_=Do7^2~>=Thzl6A*2qhM#c~Ejnc28 z!XNa^t)t6WMVnCw910nuRNXj{Bg6{j&%#?nH-g`)=W-T z#xj0kC+eEmK4-|g4WFwyM#TU9DP#Bl<(gphU+V@LYQXR1x88V5$d}`L=o+*|xXV%x zRbt!TpW|mZ6!xL|4(}D6i0vxQ6d#n=5#bNwW5CYE79@60<&ff~+{n64{c6^V(clj% zeiu3ve}m{w`V;F#{zKQIL$2u&s6QyVK4>edkg*pr4wj5hoHCza=c@mIK7SCO=tapv zSJKM`bRsq(%Gh7vDMG1s4#$)1fzT z)t(Rg{W=)0sB^B&8Jp;nuXZ&L%#?x8dK{QJJ{JxCAnRS(n{xx;-&ut;eo>eHBsMVg z4QwGI{6Xr9?!vj7n#X0Wynl^O=nh>stG?1>H28z$!Xa;0UDL6T%yCnUt$k; z=C>}pglqLb=NWOMe^YPppJ()vgysz-s zTz0an$;v21g+B;p@WRHmrzbUQ8Jh+t#;R2FxqTUh)1wj<{-94i18ksh=&df8#n?B* z#%qv$}8wm48?52_wNDRQbEqIuUWoA`XYzPpSQS zWcY(WlmoHEH~s1S!5_+@eCq72GN(eYcl=;@_X0Ueu%^s)sh+e zoJ}06Q~wmNU^%GE|Wp_T+1dd@j>=-J{FIYV*FGarI*#6zR8`&e2@A*{`0*3 z`Q;4**XO(CSawq*)lXDk!Qc7)+#mgm`zs5(&`{Y`>ov-zK{MoqH2FCR~E8l9n>UFXzU*o$n zx+&b_yKec|Z+iY>rM|r+-&b=)>FC3kYmV(mPAl;zhsW=I=Un}v9K0tA{J|f|AvPWb z{@{<~hz@`7-RFKi{JI0b?!d1*@aqozx&!|&cK{y)hhQIJYzeP*OYj`Q*HnBWfRx&s z2+o7w@k8qms(l~rRPE+b*6FgJf)~R7f+g@M_&onUn?IOU_nStCc(dB$lIt}?&5S7V z2L-1kUMY-wMHq$Gs^FOELvKWdKZtJ^JrLh2r@;T@pC=AkTV)$-{8KhI$6YMqsSLEOYo4$79bhNK9+zkGBN*J60}Z&sukN#NM29~pycO&tbL_WDv3~Q? zyTynVW6jhZ6NA-=4u6o?601!ObodgCO%jhdT3nm+XT>s3mvUtIgABWBzsDnW4Ty8) zAYPIAM6G@G1M|GabLM=bmRYi|&AUPCIrfWN@YH{JluLI5LE_!(}>QjUt>o#qZ)f zqQM`OwUycnN|%zoVH=-=$b!+RxOdr`mmz(%dyeU>zA&6%4*(YI1^)tg;YG0U%agvN z%N{_+K#3ESwRHIX+$Y)JaJ*l~%iBVB+@24YRqej7oq}Kz1jBvc4h6Yk3MloSf#7N- z=h>cTr_vnSquTOrC-<6ms`X)*V;ihTn$3DKfx<)vIluNOvR{t?e~|i#s?BBYpUBJ^ z-cw{De+KtY^{qEU?p1)%XK7~K{LpgpQ1EKoT_n%^(WR6BK ze0%>Me^B{!X_kuLkh#zzB>6obsyR{q76JaCy0Zsj+rJK3uYA{UkR>AZ2N_x42Rixo zT-IN@CAlV|!5`#)%lb-V9nXU5y+%AJo~^uy41Z9`A)HnTiEZ|2NxVL1B>01>_9H@s`*L~2*ZW9L zJ)in&p5Ri^;19~Z*DVW4go~knj7u0h`9)XMvrOf| zQNcnC^brmIV7MR=*dMzf9^lO%EFjAS|0sM&zvS(tp5mCZ+nKbUjdjPjf}k}F?9Ik4 zmFml{Xa|udu%MbDs z*B*}W1>sOiPj0(>vYJTj*Q>@2?6OLm8l6V@MjsM@Hax__6~@`tbxZLFFCnJZ1Vbl( zt#EWqV-6-#yA`^bO6@?1aO)WO8{&rZv%tT@N4-y7JKkJp=gmrOBx5!?rzF2J4x=z< zgkar&eBwI;CuVVKB{$u%?U&Mg?`G+n_mS^Arf*M{-Y~zp6^F^fI5R%=^cOz#`k}i! zGDnC0PZ2>5i!~JMlkCVUh5SL`D#L}Oj$%~!gZQY3$B^}vmR_u~ZTN#F^hW$ZZ2l}5 zT2%Oh=!SW(uO&F)dUbp_cY)DN-nToqU0*SlMT0*mwn2YRf)5S?yNg{5_pUj%()Igl z_3A~1Kd9kXmo?PM>3H-fiNmOnm$S9ZR@T#ODl+^*u@C(Ke{j%DGd2yGH&}~QJC9w= zD2@-csPG46Jk$?~C%0 zDdWFBe)-+-$9;DF!T&13w?D|H_tW`<-x~Yhp1k$(>HNX}*8Kmtjx3+fAN-H@{?QBk zTH;OlbpGHUHU0P3qQD>geVc#(T5LQD{K4P1`}ePZ@dtl@M}EEjbq9XkfnRsv*B$u( zt2=;?f#Vl{(C<=H$E=6=f^em(b@)66d9>hNbS-?tO?4V@t-emVrgA^Z`(t%{8{~2u z5BXfmD;lOdNYx$pR(|wu1f?FIX7iZS@psA^Da2ig8wJ0_@Akca_ZNRq@@9Ir)XcJi z;{V6qyT?YJW%qs6Gm^X*S&!8&u##5Du=##Ji_ap9MY8y+B3XPC$s$>-s?p47cf60$ z&dh3M?8<6M25dw?td0c;iU4a88L_pFAsIoCG$7lfD1XF(4M$qb&R+>X9I znON)2`P^T9iAspNpt^TbN`_6A@jgix9xJaGgqh5sg>kd`*N`@SWA4rb!VD&2)&7}c;88U zEQYG?QO2t>EQ<-8ZYUe%KBJoV#<_Ei% zO2f00xy@|PSo_vMDwSf+kF%|&rd9?@?CWy#%=Ukkv{fp#ua}0_mTV4m zqcAi)laFV|PBYz8`N4eDUGdU*zSuo^I@CXfTe%AP$wFo-o;xkImF7!kFK{Dn?s74+ zy=?QSTZ>0S9doNIv6Dh+boaFFa5TG|$PXO$6}FaQ!|ij6RvtFL$zK2F{z02_=sb!i zdkdNDLMhR{W@V8n+1?7{>x^N!Yjek2r9^kq=ERqZ#gfe<2N%zkD^uFE^4xV{G9}yd zzP41%WUX$@rb_cU+yB?OX}U=FvNeC^CzYS?o)}B6Z=4jmCi7ckeWUG1t0vd%+?eM6 z!QK3!nR9DjHSE`lL;2;y_;B}H?_|I2uR1iF>3fT7@%@Fhl^u7P4fRBBW-GBav6+|} z-I$+hU5iidCTF`lw_;r@$(@bW9qLCZlbyHCE32i%u-W=9+1e1wYZe){YWH)N-rmN^ z(q#NF)nj_l)ZXl#?bqhl+&@^#jy*8&BNj4`}u)r&(=`#^tg9ve9`1ipo;G>r^mXm z@qYJ?{*sORk7iG2xBDh`*N?VV0^Pm5R@ZFYxOT*?ZEfx!EGBZr^z2w>u=W1f^zP<- zylr`Pey?XaF}ARg92?(R9$VgD-rGEM*V6jI(%$&aV%z=n!r1-P#K`o_W`1b*v}7%M z@UwMM+efzN&TKSp6!P2cCENEH^qn}r&aG84UD$qB(d>*U8g#2`l%?s%?%rNC_Yby@ zjE)?Qr?T<(OtPoA*S2^+n;adwVil(3a)WwdsjO81!_#nLzSIc{26SP>ZhtvfbT=8D6foBIci zjcrG-?MY=X>C)8J(W==O&1EM>a%S80pgq-*i*9utwXY23vWo+`XuLnyzA|u_O${7c zU*aH}G8?2Ty@%P+v9Z?aseGc}+U=}09j;)kNId(Zwiz}U^RXh~r#XGO!P_hUUpmV4 zyNDg#b|=@_u-z`%9^2EMxxUk3vwyPH-rIN3J~(!mU7Xra_73evXL@#$6J73VpXoB2 zwryK&`=^^rnoK<;07~=#_M3>>eun^b@b^4*% z6Xe5AdGD69$$?+$SNZ4Cv~qHCskwj9&G(tzNH^zX<1viM*qqdq?dh@kKkq7zVe8E1 z4eVQSp7}vrE6kk067z~9&Te9Svj4>FCmwAc6nAa7da*k`(Mp*ymf-A>*cd4L9NAN% zpDX9){z0>IIbr8zjk~#6&B5YktUQLyW}ZJs%e(N!{2}FIW#;C1=Q#(^*4bz5d>eOf z_Ug=TpzY@v$_*^_#wIq4tqb?>+gaK+SAM>&$O*>g{=q&gk0=-y3x~$zL(JLQW%IJ` zjK4kGhXKBqU43?rTVK!NX7AC`RL|*Ne&X10Z_jT{j^zjYdJ2UTi^I-I8$4kyZrswD zTAtpTwKLAGOwQ-e?Y^URVd1`sHP;q3_YbBH3uf!jA;oOU zc+Lh7`ctLtZkx-sc?@05C6=$^w(V_Y{-n5JbAlE&(Qk9UQMcFC=2uqca*K98;{E&U zy|$08)V`mO=cmkO^TbIZ7SC_B^^InyW33CUA8YO(+}&8s7Kex9HU_%}jt7Ng&-(G| z@KRS{V`(kE6VGjJE>2Axxod6ac#+GV7uI?Y6066%iLTx4xvBWp)auO4c7NLDcx@iu z%Aio1S}hFQT83cmk-f;w0W%*wXY*f+o9X#QTV`VRD#xNb`FO#};O73pol>IT_ONc7 z9S57sE462GTm9n$V>^4+m$AM1oMo^12-n}C&r`nWm)aVH1+&3p{nXywqp9O~|3GPo zH4GcJCp>R%d$N!znN9RObtUEI=!Z9wd#7V3gJV6*sr8kOVqtF}epu+UNNtT@bN?Xy z%+7`VvEk_E>1fAH>u`4ca5TDpG-d|=MxvW}n+rVQ9oGo+gf=%glH5NYv3Wx0+I@d^ zIb*{KN4>kJb8QRbZLWW7V>r(CA$=q3Eb(8f>4YQgb0b@^-PFp_@rpfLn_=e}@LMni zzPW$U&F9&;^0CcZEMFSm877CE9v6Ms{`*+p*O>Hzv(cbtzvcZfA2gY;Bey^2O8P_8m8ltZ^O2 z-ZcIu*A>du{}Hgcf3Pv<4_;jw=EKUgxqq-R=MUCX9?kuOBYn1B+uCd!E;HW5#^=<* z!TiG1L2+$ner6-Rl-`<~JjxGko9@JMlQv(A4dLxl-h`paL7V5axm3=bTs5P^4s&Fb z=49$AgtDLJ{=sX2)%4m#pou^efhGbk9s)a#E8HaX=o|s_6ZLj z+Ma<)_}(y|HykJRinrKfLmg{Z~#`XxYPw0tjxO>*@y2fpftL;y+`L|MnJ$vb3?_D%CHf~Gp z4EODPY`0h%URds#zrQ)NlCm>d7dQI`H%>17N%(kAIE!45~<2YwMGCyShHP0Um=DnC#>rSOp zwh1_Tbi8>KYv1naYTxNTY1_^fN;|gf1J~V8ceU>JjCFABtoOBLY?y6vWoA6p6YDU% zx6K~%MxmHD?7Nq(E-iX@zU&ESFi1Z>>JOdQ=4tbMw`QHU1**^XtUun3YjtU-tT>wI4>r#qZ0;X)XPjH}ZTlR9a{!v>58B=(j)2VBJPZ4nY|_QH z$gQ0WEiLZuXOE(Tw#V+E`>_4E=ODW~aFAT-J4_x79Y)!27q@+ODf_tqFB@!F#Ns7%8uRM^>>1;p$)W{K4k_ zLH6L;oS|*Ov!Cs|T((B_0_R+FEkpDCLHagx>~lbG2-bwSxmH^;jIAX0vADjk`Lljd z+k%~$yW>3Df7D%mrf`(kmADABCzVgk*ngBg$Z5uZZf&vJH6a98e5*8m|Z@K$5)RE@wJ)G#l@+WQCnxa z)L}RStc@MmxPh(z-LW#D+}t?yKsRFv9TWm+;w7S z%N^Q1`--?um= zoZH!G>**O?H+!kbcUOOC(^VSfGHaecXk+-;HJvNPi<4&C)G(b~EDf6dROSeaF>Fv` zFSYhn$e0}~+c#-`iiHekJ~2l-9+VyNbPZZrCCr}Xh}pk2+lhU#;bhOMjq|j%E}R!f z^Zdc%nW^#P-mO%8zPOb(Ok=h$!1mY;X8MfBnX8SNty#l&$mYl|yO=wV&2G*d?~g?{ zk6IUkeFF|@)4>*Utz*ZV#Q~f5wYXwto49RuXEuK7^fRyhu+2fixI^>&!RGmc%p;lY zt>*cI&HaP6-*3(4Ad_u73(ft5+x^SfPsMI(X(+eq_DR}Ad0?+Lzf|0|IeF#+i@DX^ z+4;=e>fn4PeX>*-?w>6VudUfxX-7M0GnH#L0@BC3yQWj3S~kxgWPW^jcD*z|Yv;hW zr&m)$y_4hj^E*?;_T8zO;~ksp-d^uK-JWjES1z89dJFEd``xwqzQn=e?DG0aXTf;Z z%D}Fq&A<0sIrW=8;e4L$8>5nKOdbqj^_tXhlZoY`QZthD`dWK_H?K_mM^x?xNEC4&3@nfU~ckg zFgI@Vg{E_4ZS7MjbzHFbTe-=6rhO_uzde6ajE-gp=F_Q}VstE9=ta1!&rBru`WH`A zJ-e&zBkR_2w*D4D)@f6#2s_S`?}OYZHT>?V8rGRfBandnN_cGS*EPL6hLM+e)t z+k4w8m-jrkdvwq}a=$&7SxX*mcW<5!<#$huxn0|Dx0g?J?;UOBhC{ab8s z_S;yUjs4KawehwaZHZDEh-#@mHNlXtOpCDHa{yighZN*P^Q7>sc@&mTN0lokx#t!KRA#+&9qG>yAL|j z$A@!ver5Y%VYticiS12p?jLNPKWOuU^g(R7zRiKy{4D2u-5=x(msV%9f%TWHSGK(v z!5I~-!yK~9?E_doZkw5%JlHO7=WTw)#*nu;lP+6oo zG(^q)gRKk349)Wg4TR7yJWuVd?+AQa8*92wbN`_B0ixTXcQp48ij!>J3CkFRU-SGy zcUGg*Pnn*mwFi>-wpY%^T$<+(Hun#jjmf3)(%_!$Q<`t?AN0>4Y@R>Z+&}2fM$E+1 zy$35(6V3gD7tSMWoxrJ)#mr_Gk( z&?;v(9uCBMMx#5nj&o|)&UG_eh<3)C+dq?AKFze7ebLp)(deQXptSt}jPJ1_AQ;1A z9IyJ-+&|bnf3Pz(-P}KDwno`ESQ<7viOv0k&GQFW#@3HkGKEan$i(vaRBo$%#CRiV z`{bJE4>tD?HqRf_xLb4opp92|a5eW2#<~^*rPlt}IIY~uhdOSIx0>evd_(i89M?VFkCI9}-58d#n>o?Mykom$E*4lQ>dPjV%52NUjo zy>)t}r#H5;K03GBGc&*5bG)#6w7asnwmUu6u`ub6O^$Z6vCJ}s`?$={+rRA2=F0TSOtycqkRNQbvERP2Vsrms zbN}GZIWy_5xqq;^f3UfKu(^NG?Dv}O=H~vv{9r!nu6SuYU+kVdwWG^$D_0>uS;$Pq zbEl;?vje$Q9I`X!=1XR8a2s2YTZ>0S9doNIv6Dh+boaFFa5TG|$PXO$6}FaQ!|ii6 zu4T>i0&Vq(wcqTUxZk$cbFgf4+p*GM%xwEkCUSFQZBr}v?fk{niF~1NaCoq1roQ*!M%X10^cd5C5&|$N~F@6k(pk57NYunD{VGD=d z*%e@l{$)09cka8h#a{URgO;z3#h$T~`L&eUmUZSDE3PvuYkNt}U7FfDTFtiJ&t)e@ zj_l0DgZ5NME_={p_E7unc_JYno=X_`&poeO7oX|7hT!GGm%q2vDI(Y)!j!LL$3?6J7LZAqG;+~HDwXRhyb zc;tTfX123;KiN5Qn2b+m_X_>HcIM-5d%R~m+uQDJBexH>Z?)~8ZZ2(}a4n22A1tn| z>=w35C+x8;VCU8BTe=EJ)hqud4&qbptT==eKk}e83Rh;rJXk*V2ir%m9}70c#2V*W z20vFG8)k1a3xxUj(ddZqW?&)bme#VeqXld)}`oe(yv&!pMELw zrPu6zB=TU_5dP%Z%lE#1?>i#D`)VZef4%mt$L@WFrk{)a?%AJP{w>4c%<@J)&Cm4Xp~xe1KY8{WiRo8A zc=<~UmWNO4`A_eC>9_AivS&jsot-oD%RO=bk-d*ZBEK1le9yztmm|OE`}r8*hm3AZ z1G+!7xQ!pDN#kc;s`&jl@h$ND8^O0%yCYxv?SKC`o4EI2_bbldc^uG6*?sG)zY~;e z8N&}>w!9cVhJ(ZO?B(+P`TK`pU4H-2c)@n-1$i4b01p1DGwKyy(5o_mm=Bk zAukqx*#FN4W&Hz`1Nm*Sa_9a#@n4RYI6k!e_+?;a5tO}^!FS--Ff!VMG9ewi|Ip}# zF2dh4p2p948U8(2h7Ue&>9raEbVVMOBEPWvAoBh@XMI+W3_Eaj?wGj`?0M4MlDV-ET^_Z8n~h}+WmT-klw{C{Ozk{_opol!u(v|x;*@qavDEhcK@2Wk)Pc?`|Fn8F9q+Mzh5cG@vCL` z*X;Y>vg_|y85+MEUwj=5{;KgNIDTMddG@aH?gOhA-2e4}k0a&#$a|3=AdR!h#G|u+ zYi`WkKQi}knftHI{W)|0z+4MwJk)#kc2It<4zzsF!~gAGj&)*+BxA1KB-DvG~?-M`ru*K@jS&{NT_xIr+B@CxX z`rg;>?VbHAFP?I|-~6|UM+y6m%rJl74SgTJ9@IVPc>ImXqf?{n@xO>XT7$k~!1s~A z9N8iLdp{ESgnMVa2j98(U;B>S7C&PcH9Nzc$ z#t)x||MOmWOYe#FKUWU_{Z?NLqq9E<%J6~JMWfAO>}1dDCU0iHfA8!wmY4hwf=Ta( zpR@bOJ>l}`%`S&VKIk<4=9-tN+l| zc^B8&_dHA*uSLG{GrJ=ehkIB0-iPz{E|8DE?d0RPzWQIChk5^dAO0iz4n{w1VZQ0G ziu~ri55Cvr;Y(ltyY`Mc@}E1IX8An(-iLkW|DPDIRQx7B<^28^Wxw}K{#%>(i)XLi zd-UO}3qd|hpL+Nk7VaPV;oc9z{bD)XZ(ADoA`gDg(fz@v9{$G`$A9hnKMVZ-Rr$Ac zex7vN?maqdTX1d9&jhk}_wSpZziDAVwD&H)$PYgJYnJ}6`tc=x(9!)~IlkA*VgHiF z`3Hu>&z5PqSHj=RU;p>t3a}u5j;B5udH6{Sd)8&?cP%_3++VTy3Hzh>f_&V25QP0V z<*@e^b~y6zI|PT+_GOdPttN-> zMSj-GoQ$ZX@xc#09JO!wZLzQ|Wj)3J z-fQ1yd>YOI8osYg!_PcH!-L<8LBp>a4ZnI$!w*6O&sAvnc=_9Xmk*N@E?i>Tr{iPh z=Le0B3*{d9VOQ=yRW7?SZy64+{&U*?Z>p}e;P0icf3xflK6=aUX~P{xi64Ggh^P+! zvvM8$2d)nOH_-N~)p66soZt6<_~E}azn^;i_?I5L`W^U#-;Dm>`+N8|8Fu#5mXDt{ zJs=wSQpwWe-t_rTCX6q>_0>SX{nl51%cXJlDZ{EO@(8{4>{HhMylU>f$S*`JEtBaV zp^KSJ`J?x(y)!-MqaPt}mcGgUAHe@T^fPmj|L9>6+C@EE`VZjg^7Ho_?d~4E#nL_N zN<1>XWry^UBMYW?LZj)y&Y!)THXZ1rZ+-QDDC1JrLk$yjBiFY4n)&&)AZ_Zvf@DO? zryqXB@Nl})uLbzL>+noGk}mkIua@z%ygS|7@@n)v{Lr4s&mUSoou1|CRM7Xo+WT`H z&uRMb(}v@xB99`8U*1i;`?uafpK^LiUqCN;bbRt%4|e~F#W7%58Xhk1uI^i&@bf=W zW_E9FM4Iw{|2rS-{fhtCW%@WX$^Fn(-l@coG^^TR!;VRu@-Ur?K}gywP_y@8zqE zcME*^=?9M@|L&*0@!`)Ie|)y||DH`gAWqj`dXs#Y>484(q2b^Bf9HM0bH4mEyKKg^n$VYz|i+uDi=OZ8e?@N)7{?)4KQ>&(DE?HblFFA~yOFdY+_t3ET z=+c*C}H? z|6$}y|L8vieFT@rKeIlY;xRg_ruCcm9RF7Rc6QIz^;gaP$KM;tzWR^veW~w2oCF#o}VgMnfxuwy{@v{vuAkWzqB+>wgkLqxYL((`f-_e{)T<8@R|Al&+uQ3 zH!bXk|3@%}@vX1^qoDu26#3ncnT);{iTpE@Z(nzPZ0o;Ty>Md<>gQVf`%$;=ugvr6 z&-(t>>h$;7%lsK#f7SnPed#lwF8glv?$O^a`*G>dN6-^K`XBvpVLHp<{&m?8x^^Y6 zM!Ic$+FRzDv9PJpe+-N?sUtR(HX z|HapS^z(1Fy!Up?yKlbN^6u;Jy!qxATi$u|-M2sg<@ert`-^-S86J)Ptyps8B%hq3fn^*2lTTAfavu}R> z$GOXX_N{kY?BAE)ee<1`AAjfV*WY~i-BKl&FTV(^uB-}=lKU;BJ99Hffhman|^-e+3^|J@63{KRWteErQgdIn#4 z=grT&_3nFbzH=e1mX=-jy6nH@v#)*ejnBXNjvwxgH@{#nL!nw)lJ0fOkH7Yrx4!t9 z!B@WUh1Y((7>>K8h1V_bz4`8YEhA+=UwI;?b3db$*jw*C;iIKx=gV)sH|Q9|&~Way z70p}k&a`yAVWXn@pAxUB(nAPd&VL^@fs}h`rGE~i*L9J zupO{?%e(Kr_Rf3#j`RHNMP9K6j^FUe=vZ`oVsdKwwI6-`jW>TRck=kM#<9vJS>#XG)prTdDzslNHuWU4Pp98Bwn z#^`tyO^o8jD!QjeF zdUk$ow;&oDjg``!o7`Pr>DhC6o?abH#@AL(4hs2&TKV8T@}2Op)!j?=1Nlp=_qAOX zpT2=B`k83+%YZoazL8id&BM)H*GVBap=VrlNYP%+Rh>gV!CTZ5Frl5I-Xd4HmQ!Oc z-o@#3KYs8_eB7g->RD-2ZpP*pw`cn{xwc}NmGnv99Q7JM1IeC@(!~w)E%nUz z6UGVt6UKyZ1Xe!1y5GzXWhHx|2fBQ@fX+ak!GQW|`z>eS#d<#if?N z@*xoK9>}z0v`r(W7Wj@AArp`jOk}?yHsOr+I(0 zHRbZWus+!-eB_Fsg#|K+Z`Jq+KcfA%T+y-Cw{(!+oLyOra1FaaV_&u068cdY?Q&E4m^w8Ci{ds)vv8t90ao6`1inb<}qteB^=&-;f33 zA!H@8>3QgzqPurxsJ()Z_-T17%Xiux-A5qYI9 z)x%G<{4DjvI!Qm4+IXVRBV7|-5_YsPv?=rzsEdTX4NPjqNqUxUx^JzkSix$g7~?(l zqgFn{@4=BeiH?N63Ll33_|IeeTTYLhPiJ$&Lay4_TK#e9!?p5s8}Gq`zdn;k!ijpw zJNU-WTdjL|%kPsBmb}#R52pC(U2aVzHu_7#N3L{z`*ayL{x{k_<)5(VT>f|6)6a2vO!gFzO{<&T4iDtC@{Sws_xV`) zerwf}+j=h=`&QfL`)KbhAG`yrdUf$aacu#<0weYNq-PQbx&ZnZ@v6?HHj_EVk7rg_ z+?dlqa@_IbWn-k$Ly70M@Te89aO$z~4A=Ip#!@}yF(8+(iOyl#Kl-oIr^!1qoQr-4 z@{GEQ?tp$7&vj;$?@IiZH~!{k@{93UG)+HX>acZzcg%Y-mPy^K)}QftN?{0BD^Iue zKF9&}FV+{deQhV)gPp!z*Co%hYn^*sYR_rsrh6uj{kYI2HAl$U3Vl2um+(E~cM5-7 zcw825khbYlrb9_jpf2*B@fF*`eVR`1Z81hg-H_ZB&A8N6c#nI=X_TJEwS2$ayLr^| zIA<7-YR|}g#$Ke0DE>ye7xIwYiXz)3*TF<%FVJK?KGz2%47$5?1KM=)&OtmeCHlEn z{JqJ87<|R^WwI!YlVlV8$C!)aQyPtQm3A$cKF9G;beXvs{4kdQuWg%$8YdcYc6beaAOa>or`Wk~ubvy_ zDqk8$R9`}RXdvIaioSdaa<9J>Ac%j}tN#9oio&LRKNi(2@Lb7w_9#y(4~PzmF03>d){U ztl+7s-eK2Y;9WKP8}*L#`Gb$3m3Euw3%Y{q2ll!-Joyj1tSivido8Snx(;)GINDPm zEA&qPJG?}{Q1cvoYZNZwbVQeE*4(2%_TqSgajJ6vMqzN#Yor$tmiP<93F~JEWA7K- zO1%r_cf#}Q(gXbXtKEn5(1>TzA-Sr$R8_{5bx`R}wDI)u7~3Tt+I`V{0Uu#j9uo}4 zyaF9T>B3h&KM{{;3%g3AQLdl9=GMd;)R8ChT5hkTBY+d*n)LO2efc6kp*zJ=0XFM< zq>0Y2xiGb};G{8N{4@%KtJ3i?;vP8+t;+9(v0?E8{blnjoWgPF+38R86RXry^o{YU zzRk_-gzM}0Yhe7j=&R^&)OY1cE;v>6IvYE9f|tO`+I#$0a55a|JEL>=E+1Gwnt8y0 zXB02buHV9Vm*Kp45bHW54)(@^ zcCh|D`*iC5CUK}IE~V@D@vGrb&pR+!?d&}DFYtS!9j)k|_2~kl(Rb^~+fDjW+L!W^ zUk`8SUb+dRbfe+v4JP@ za!VMohUIuDm(!TvWqB9vm-+F($^UJ*K|0JASJR7b?%jOf)YNW#EkhrNKAy&P8Q=5k zp`Y*T-roj3ic_>OhD|=S_KtFY7VHSWJUbO~ zKKdz)iz+?(g4ZdBS~w~G+jc8-o19|2o4kM-^Gup6cp4hO93EwUOM8Wsmg^_g(8a1@ z=dUMy8d`2DjOefB(qE(u-x@0gzn<3hYMtE~z3dwG6hT(Fva zG%Uk>bW?eL+IWN!>&Mu~r01J*wO0B(J{z|~1~HHC^!?S0>r2CDZoJCIBdkAp?*D3C z>uK|Top7RuwH7M(TH)olmg|R;AFXZG^L1Q5zUO@}y8U%dH$ju))wn6oidWxix$<{c z+}otHTHJRf-`Am|T0ZpdI`LHVt9X33n!gv}ou7yB{j<;?j!Vza66f;{t33Gbv(n_p z<=;PRyx(r&eQb39?Uu)8ewqk05ojXNM4*X46M^ao{8?`MmG`H0t0VeizkOOPSbH$B zvN)Zb>5H!PuEwGVot6D_;W%GZgu?mIv#n?9WbBf>uce2US<8ph9*Mfz=F3?|d`ZV{#Gdnmu9?zvt{WR}7 zUOuhNp`~NR-NWL|+JdZwsjYi*`}LvWF5@JOs0*oBdNWr{q-y2qw%#MdM8{pjN_62O zcaSYt;Q)_0Ub|wi9P+B3_>>-HBUyhJaPqOyJ!M%h57{blw7epRUZ8Bsvp|}{TKES_f=9@|?4Zymp?yMLEADz-WRY<4WjEo&a*wpber^*h<$-#S-8r7&`GD_( zuk=O4L(sdpp6*v$t?<>{@$rLx>M?W1w&%Quy)N7ReH-vD^X=4gT%OCD-Vdba6J!N!ihn61}wk!L$;dAKIeguV?vb}_>slGw>L}Bj%TMyXZ zfiGnnq#k#7Hk~C-U%qp%bf}L$KdJueyYJpMPOM|nK0?w;&rPjppAPZ`oU}%gItm{3 zU{H@Ac#OP~fAI^r@Xq+Wyl19oPi-mRv>!(5I#)Nci>$w5J)h`D zZXk1zS=dggC;wOa8Okk}>;iYv+1MC!=|cl`ig&ba)O+qp8@-e7em_}xxosC3XoF?T zsIo?Fwau;jLq16Np`Klt{~ESNvAqH&$SGtNG7%Xj`4m5yy09l$?LU~Q{ZrfG%g@`! zNAU+Zx&49h3P!9~EAItBX2(_!-2Q27>_98_t&mHS&GlgC>l{iGyuhC4*;H~u^$u6E z-1bkO@+_%~#M3(N3E;NzzeTF};vs(c>7W?R3KPjFXCI?HrXyP+`1k2=)O~=H?KP-kXH+^ddA=;a z`UZ}Q4;T4=8NUf9>_BCU?K|j3@DlAB>tTsQ{T48kPTMGK{B$b$GP@}kWR%G%*#}TP z5gxT%>)Cc-*EXV2xgcjHaKYc{}vnkP}z&}3U5TAwF!=KWludOgj4;LL)HgCe%_|NpCh?6jiv(ava?qqLg zSfAn>eNe^|e7eZD+VBap8;L)#qVM7NS(*EVk7Og$>?iiJ55x9jxH?MSHMZj8;@?Z2 z-zA=McE3FP(G?602ihQb3XH&v{QF~P^mQ1ASUHYOsNaJtJM@9R!PsuFf1R|5U;Pvx z8{IQ*h#zz)bgJ{Xo)2I7crZpSzN)-8Uei4~!&d*;zQ$$1g>Q_*fD@O-WE7^??5GGA z?w!t7*8QoE!X@m&kBXz3>+^Uc?nOgI&RG3GR}bE=?*(>RhslY3^X&Fqg5t|AA^{cgXX62^&V#@Cge?=}LLa2iS<9R~ZUdUmdpTi#ya)ukDV}xH{2SHx(F02#KKUN>v*CoPqH~Lw5)fggpRoW+H zZ&|mx=$36cl`%k8ffX0+7;#?EFNi19rs{jR%}e%goMMk|b0D_|hP1h&vC-K0=|Kau z_-&8+?=|i9RP@r|+zI6)>=N%>_t2nZ-UY17GKxN&U*}dg`>}C&2v%S=Go8Iq_k7wL zaqs5|T4{sDQ|d2V)Iq)aCmu7q43b;OH(xJ6&pav)CmCZVuNN>Pd>JS7Z6BwAm#5Rw zsi6%0K=9(;r?(OKC=EYd|6b!9ysI{z_e6fnG8x_h8$T}QEJ=^Cfp9q4m&8B(E3Eu} ziXWGMuRJuu_0#q5;VJdgFWMNb!cXvp$!o%clU=SIKu^~_{6v1vakBQWd}f8xMOOkV z=I<}VsS&tbl}3eT8>5!~TWu`wJile!$~IBJ1+0jNG0xcPq8pn+*8;0Rzp(iV>;;>j z!Ljx9QZ}$7CT!3HgfD)sqWO7z7f$Fzj8pR*Zlj*S$dfa)bCOStuek8#eh>Pz^Z?#7 zu9uB2_H!xSYVPyEp`J8Ft8`9Z->Hg`;iUc=I-|ldCZM=3xTYVhwfEllZD)ZQe(Is` zF8T5ERm)D8kD2T(oXhawtP^Aq?IrCY_e-6VoqH37O&=rfRrg+Gte&v>MLi2$!b$js zbqU(^YWN7RwTYQcg}qDsQV%VnJB&%yXB%Tjw+{Hn#slcDcv#9trf`wFvA>d${WV{9 z)kEK1@pCPlJWPCibWeQ)6WsX3-dKRm#koVtIMTf<7}P_@IZm>{^kjV#4mabPJ#x>s zZ9O#J1wR#>u>EoczdY;rq3(_L-FR|~aX_W}qVSdIy*R&j^E?%sNsb-Q=j<%J;Ur^# zO7}&>X>hV_^jZ0(T6p@!^!ZeGq>l?Hy}#?O=w;0uA>PWSG*Ygf+SeHgz z%0F?_S5|tyD?hmYd+z;j&-)&F7)Rs0>Rk8a26iqp7;0( z`oY0C0dWTN3c(o?tlQ8$V5OgAx@)aI;$6YUr$acge&D>1tG7?*26JDGK?U=jtkV!r zUFdh0$2-HR`1IYCd(lWzzpHr7OO zPPD&9P-_M2b-|5u)BU{+q;Y);pKl1^g3Fq(rS-$1oq)|-dh_UB`yv)}8<7whr;y$j(md{f-@@Fwf9!*X5Wac>)ktKt_e z*Wn}DI@)&jN`>*!Gcunx0RFg2{)3~>N9bSBqw|YJ<5hXNt?x=dG5w@nD&@DDi`*qF z~ZzqhwoQr($4l4@#-6TC^|+m)fbfxhFo&Au$IowQsrGpL( z@2kvh9)C-Fm(=dbP6hfDWlFxNH@L!yIFPr#POUWHxrMde9JaC!PPf}-uZ4H`k^K~~ zlAS>KPW6%Z@SNhqy={Dm-%pQwwJYIr2Rmq_zY-2}+4J;DVQzJ%YXG|$*fuH_x07M} zB0Mjzr@M&9m+#=CxWQL-5;{~Sjlf7afep4`uz>|#)B$kOUT8;uxjqP|mGzTe^3Qsb zM0flEmuL87cO$cJYnOVjWAl*sNJo4N7OG#+C%o2Tea=3m+5_I-Hdad8?4C?grm{uE zd*m#2iF@kaPGM~i+C?9ArW#*7%{zE(X+73XTCv`>%3fFMAnzzQWSpHL?Dhqr7pT1W z-YA^l1M-Ir9n#gGWNY*=J(i8V%zrY5<-h-+$k z=#cO11!G^g^cTri+A)Rq-D>vhX#20iPxkDAxQ z%pO83>mm6zF*TW5*oYP-FND+fY~N-+(>{%ip&s!Z<|kym>ay~So>UDpAE)%dMh;n| zFmkDT6+06~n`mx?3k|fp@ssG}*z{CSuz%ouj}ms!R!{qnkrVVABrlLneqE||ul>>! zOGkTL17#VE3=jMFaUwmnwdkwp3S98CbYSRi1U^bbW#z9swl%e`EJr71cHynz@q%k( zm{*c6OuoW-4L@tG?qr+`b!mXfC zwwWm#FnW)UDgL6Z@yiq0qyCxl9d?oHe!m_*1Ycwq?WFKfdhoDpb)u{J80r3b%`b?? zU{4+PcFcCByUKeJWs}LqK%^sA!kAtFUho(B1_%G5KJgx#_Oy}s_4|(8Q@3bK6elkF zwr~l%&s#?ICKs*lUEH4=$aSla_6_>ciUbC* zJyZ9hyaOj>|r|FkR$bILBf1 z7$^A+Y(RK?s&=<*FOa$_Uc%LQg~I!8I4`&PtaQWW2#vhs`$ZdBCimH+kNq&$*9rC* zDjr;9_G)iz0<5Sr=ilgO`}@O=^3-i78_R7h-6kg0;#RuI0iQnZ)h-3~ zqt;%0^a|`5w#}=LNSw@+Tx}+Y|vS$#dE_#w#>ds5wBwSIa{q-jO!4 z!_j8+N$!A?^cLyvuG~ZI;>CBgUFUmRiQE4}U!<*MeB!)sd5*u26MbXGE$I7cOqIAA zfr+1nPd~B@{wywEB}h2a@|s`R>_^aT>;k1M-?O zVmy^`FfRIliUZfr$8F#H>4xvAZ_p|kiao-MdGc@x<5#g!H@>HNQ2NIj4@YK^xAef& ziXW$R1NfP=8QZ)l%g(91ZEV8vpQn8Bj3vgDDz!@rE<_;Q{80|9CsLaA z^88)#2i>gsV|>cDPbd1YQ%Bz(?AH2oi{Pg@dGgNsCf?KU^>LPsHr6*#2E<4FFEUP| z9hY;G7n0W!lKK;13zf1YAmloxLwLDsw8>AkaP znz7wrJWk;i2A4I7-!3>QU&?3L)%Re&>Ae3dy`UOTDGct5T<^fb&kOfqeEetm4c0E$ z9K3gyUNFxP@Ra;r=KAs8_4``+xQuQ;jH`z>E>+>F%2{#ezKHAm>HO}pH16WJbIQ-} zuA=kYXZg;?vfMf}8-wt_DIWiw?)B|OaYeV>>(H$*wOqv&{;v0bmR(`;XBmTL-kS(C z5ojXNMBv3jKy6no_r=Q1%}`qli|f9>8EWocEY)ye4Pk6`cat?sta)SYMk^bACQPwKebK%#{*qz|)W?MQwXy>)G zDNfw$Q+78(_<7)-GdFimFYaZk2cKGgz-{?>%$*(Yr*$`SUmq1d-8Oz*fDe4zAhq)T zH1FX{&URLs^-=izeTiQ9XKQx;!dmX9!J*zT)z;Xi{_hjkwN6& z)~KFd6))|f%8fmF{_|bHiMIZ#JXHIR47;iwM2{lx=vLL@@ZZS}fUsiiKX~c+d0?fq znQOB7+D`cXsyzF7!Y^@9Km7OMd+`La+W$s7N_(1_Ew$=B?})QExiz8nD+P zGbb+DP%l=(N&7sM*RV^yBMsUIDusfS} zYo4fsikGyZk@)m3j1k{&o1cV}-~Mo~_qgzcXrv7yA7F|<`Wcsv0l+UCeM9lXxm;(V zxVGTq628wDyJtubJdsVLNnNE3x%3Vh=F@lE7!g0|F(wk$xrG&VMHu12|2~bn#~+xm zA0In4;Bu9{j4)0-QwNFD?bMxTyvv@?5!+^(=v--|U8 z)E{hvVEd|A%-UY__O)ldu<1s+jM*qn)ji56+@EPQPLjRQ#u%IM8$DP&@NrUq9)5XN zOsHqnNo+?+j)T9Q^Xha2^f>6DJ)qu+Cb^Bkh%}TQuJ|0<{B|jNxH@=HjAm7~(sOPC zCx6|JXaOUwd!jv1y1s7SD14NTXv3vHfxOn3EP4#@r;hp#_6JLqdZ#w+U~a7qxeQN; zudu~)o%#pX@YDKnW&&)mO@>S(9%MP`qlb#8v}c+3%EN8Dq{Sb5Dsj<$)Q;1?lMWS| zS&RBOsegtXfgivXTRh@HbfD{CC5*!^^$@y{O~`L>Qy+o%w~deDCoTTgkJA^%TalIM zPr@wGm&^I}PHhb`B^;LcX!CrW(2;2W$TwG5XA0w^XVpFGo6;1`a+R0cbd?souY1Z% z{LVXMxU+XSpQy|aAjkN&nO;hQ2YjWv19rZSL_3Jiq4;q*n^{=Ya;bYN19*u(ogatp zZxbKIOArn*0)Kpf_qUCW;ukHH9eI)t%zKUVP^Lp26Vvi5oM?Y|NBd2k^<|Op@m+9H zTY=n{%}vtA9-HF7=uW3&GyMbWr->uA8`696r+nPDE1HleJ1o;3!5D_usq z1K+6|*egUv)4n6CbW!hkUmK6WMh&`#+6_lTvgars8#WsuOHLLdGpYA{qJ^Exg%D>R+UAI9Sj44(5p(&anps&A=$ z+_oz!r~~j5ZFNO<8cwpOCx6&Q;vw*%C>9Cvm{ z#YbSoMH`~>Yy?)-a8mg!q_frS@tExjm2d$yPL@#Y!$&{+$$Yico2+yob;Wx z!;ODC`v^f9@s08jM!4t*>L(~Hu4un$S81r;!BgaobkcJdZ47DOfO7+^D)K9c=Sf>@ zyk}fQ^@(TNec`0Oqv((eR&HNMc^|cJN0YH0@t*w4y=i%oSG_Bh`qO-;+%8}f z-tX+NQViBU+Ws*1sUTNeJ$3sFp4_uS9TiSbBP1^Nf#r(kU5$#XrG zr`vFqOZw;MI5EZ+{A$)c!;F1&gb(mxpURW_paP!2z8`JEisL`peR$00C1e=mHr3)F z4P=pU!fo^%r*J~g@o`e!%MTA94|Q)mx%a-JGfZcy*#W7>hq4W(G<_EtMq22U;jr>Y z9~^yicWcegEIXe^SDD_XD;ntA`#1&nLCTD!glU()z@E(Tw_4A#dx)$L*EeJqse!@8 z@Llfg55i;yhxh4=yUY5TYIn)QZDORjg_W-x1ULn93V&Otr48{_px0Qaa+`E9U$t!= z^{#ZfJfm~?V-ZRpor|BkXPdL}&GW|2bCh z{n+8EowE_>PtM+NShipCEP2M79OEY^s~C?`9{|}-KK;6(OiMFfU zihgrRJqu%1!O8Rj;+NiCJ+10GD}HOy{yg4Sr~UlxQ}I)IJ&yPy&?l+0*zpT=Ec%pO z8uL6)@owRBRhfwHppRUiToPY7{xN>wFR*3sq+UupmKl$)V|Oh&w(ey8RW#kj@6Uph zY;HT9%jC51le^S8*(Do(xQk=wb?+`>aT!g*sa_pi7}Vp6kAzh^J5ibcxs0Z}`0X60 zC;6csEH3jyU7qhu55rfwl-^y$;xd{8`#PR=D(I7*7YY zFumZ$m?*f>XY;Y6uWR=H26)fKz5gBl#E<5qNGlxwU4Ir%^!fdaOrMvr0mAxy zX5z0F?k>L*CjJ^1y}Qa~E(#ve1)kN$qZE(dZ@$ZzRHIFKU`>zKZpfd$1@^Ew_r~TG zY}_;G2R}KlApg}|#w~oFRT?jft32sUTb_N|^}T98kU5$1xl!S8ibLUXS@R%%)Atw2 zRbHy)LEpkQ>lu$>en#J~%CG$S?Zs7L?%H?d!FQq2f2Ph=bWr%HeEuJP>dB8ESNOi3 z@OQ;enD+29xCC>boE>|9*4B0C567wJ>%{TA{fg%6xKBfKwfLVVp63-NOutV@_#4mu z_v_yK@m)9UUHAX(oVUA0!;*(2s9CB3<7>zSI>Q8sCvGs)Puuy{XE|s-E8XN zyfZ#Gxw1IP`4OzcFo5D%x>ble%Bno(t#qS)W<^{5)(EJR34WXdfT$ z$;WMAo)GGhf3RbZ!5n~6R%H~t=T?p zBtAaovX$V|!~N6b>88VoCY#GF*ttdxvvKI-qkHPN&WXkLgw~qfbe^vppD?mHp-$VI zG%k8?(xq)9&%1Mpo_gYyZ4UNM+1c2YdBf}G?I!&Tr|^ERdh#PbSIKzv2+~0ZP?*bH z*;s-mbTQF*lli_*TuL8#eHq=CeM`mC&K?r&RV{z;6Lp&OY`^_1eEnG zK@XT{pS0%PpkFj!=8_NMf*-5-gCD?%?@BZ5s(quJ#8Z+>&_P|LFX@M?H=obyk2L9v zh%S{Mds%D-+u3>W?PyiQfOphU;$p22&x8SY+AQ`pNVX`C)TO2M!4msj*vG-%5!(xq zj7<(Y8wv0Z@j#bs(1hb4u4m1EJ>f+&{SoC~ZLz-LO6Ec{GBqq)c&|D^UDcj*KMwW* zEtqLC_5iWY0!*IV*VeuUZiIsl(Ij5=q$<@FYeP~P;WRtE$$g_1Pk@mwRR^uxjO9Qr1na7M=rzRvTw+! zK1(O`F`uo=S}%j+Oh>Fe$kj&7$@n-vSV`@7MFd4Z(^&9m2oEMK+aKj z2}d2|9rBNMM0Co%sr=UykJ6;x!%NVEtl?RD3plYxT=fpVBOLN*EfpIEcQcN2XGKl0(xylP7+AcNtFcTxTYqX`cog_zD@V zwu>~z#}E4TJ&a}e8GovmU<6H~x1PM+v>&C7i!Mmt0-DqY#bf!$q(C&_8G zXL>Ie-uLwe$~>Ik@H6@M`>kfzZW#GYokTAH8_6K0gREq{K=RSnQ}=^apV?!RpPR;@ zp7@luaFQ(Ny|35NufvbzDRvKN=eUsF)IH>pbWis7ql5B{T!K#mn|0~VuwE@1aD5$| zu^0av_x0rIHvEVV;Y2?ly^cEQ+b<^@m(Y#4`+vriVXCsMX~s4-3CpwbSzw~3RVmT*GnM)$6clgZbz9Cvuy zUa{)_F7CIdZux2X_wX?~ZFnzr5U<%@GuvhON1m$>!1Hb55{}!amwUzs@PiCa_V>?) zF;G3gZ#CH)_OEBv(~Ic^JO)OjnJu>O$iMF@EdElPQCo*`;dg{@-VP>un`3>e?K4L8-Z6P@0K3@ zRr+bXL*9};`4;cXZ%uu{YZHCEJbQ-~oEZP4zf7Nxc;Vl};;gfIG_cloN?YREQ2WMT zwLYHcX*5oZud&aY^l5wHr)oAruWQ>#whPhs#ZT%xtNlPWx^}SAP6Q~Zk0VUNZX+=A z(+H=Jj_vEc`tJ0?8hqpPkbf_%$+K`$e6?Kq!58)3#?&t#lUnz+X!hS<*dJXlUS&N9 z8GbIut-YgfjqPJ=BV4@ZZ+;@}`h(a&^ydtqp%&eD>AkSJZk=;{Rqlf*4%~1&$fVWr z!s$WuV8ZvO`@4iiEm}mY+2DIZr}FF9rT6IO*vEI*(oooMrX#T7hwU|`C$|<|ckR9C zb$0mbt!vlxm+feslYKhPHQY5EuA=80C(m}nHE{^@PxzU!Eo2jQZ`SMpE6uBDyG!3i zbM=1j#lBoP|4;M$qS_J@PPO~TH;k1xCUKYe4{?M73KVQw~7AK~2HO3X5 z6*tCxgTKpYyKCP>GjlBTFMRsIjd@ydyGeedZ6#elt-F3NoN&>pS#wtnGx7nB^mlyx z7ze#sl2JNg>*Ww}`Q!gxD#a6HrBuhw6rALqt{%WLe<`!$O7MXh_mT5{&T zFRmLnxAA7CBtUT7gXzq_#?jryAxf6YQ7tABrJc*67v4%%$QQX{8dCvQ3@}>B3 z;Z@eaXdUa*#3#CM)AeZHB?F+7uV#!rH%~cXFRKjhhNDdVDvqM_;y!>DlG;{oHi=)Nen2 z-QQF?&l->Dxvu-H>H6VorS1E9-uJa=yzKpL&>T+hHqv<7IK#B@TrDo&U$yTy@lI*n zL|iu=hiI#X&rPS-jIW766M-fIO$6=+0>1pe?)}}!!R=9T86J!s+5T9!K9)7I*kt2* zVr6k!>k6uczddRjA9FZ=>{&>r`l6ftu_MOqazoL|no6y$47;pBXYCW=z%CqT<8yU$ zDf)R~445+`!)v_5c+~sMI(qFrQaU$BdE;Ud?QV_N@z_Loy>h*HT;*@0zt7p!Pq!m`xvESu`6ZHWqH5uH~8wVkE?*XFyd?;_5fTr zpEu!udv2KhXKrsJa}(HC5M8&!8P|(dw6MmVcIhVa9FBuFv7UC3dam_{%O)2^+x2pE z^S(vLnAsA!Em_UJTH@#8K8#`bS@H^;wAULtZ$9_+$0(dwTN#=(qX=?o;cwt z{KwZ)r_XC&f)ErwxU4tj{II8yOYq0~$=C||=4BX2x75B(`DI@)dYPVa#ZU2EJV*T6 z2PE1X<@y-W-|(NqH2d^dyU+CJU3m2DYTxxvvWESBP)@lfOn| zME?sO5>3I}Q!uA_9XTbOz(JT)bL9^iCH_#}<Mseh6s#2LniI)+}vnuG9K^10Q66noX#tIvJ~XrSLHy0llBJ|uBauA(3JHu*~F zsNBdGboqJ;eyYhD!oYuFET}`$dEl9JY;S8}eX=vmGw6^Dxr5`K+1L(qzhS!v?2jOA z>LqE2|3tIz-X=!GOIV(maGbvTVp zpRjG7FitwNk@_W`l5JMSciZ>~Bhr&>gckT&?GOAddZyPWbDS9*#)Km{jCMwLFDNrGL%z!2 z_*B;g`*hH&Z*t)k*83n^u!C`38&F^bkAW?5Vp{`zxrcAX^SI~^N>}b};N};4SW1(^Cy6WbEEX@rb-U3r^Un39k`i52Ne^rp+!8 zbf6m`6B6AA&fYZd8i9|}AU*z&-RL!x9pxrn2!2}5=kj5GQaHkJJ}WXs*JbS)vP-gB z_)^Erwoe~23D=iz+)Jj@p3*N;+R8&CT%{>lE?rtW3-W1kWA=hwm|A0KiVHpy24I4n zC-`D{dbJZ?Va_FNe@y1mq zw+IgK6BzmYAo=X4!+pK=mH5<8L7t<#DlX-r5w6k%BlS_R^Q7^ycr2O@*E{qH!l46H zD}Vo;cyDKXVrgY%(bbz2uID;}aA1U3c&+8Ni@cohESZ`W{A zoa~#{4xz4B~!Ha2~Xf_u{2a_tE`r?%FYp?-R| zeJ@&RTa@RX|$$EbIdJ3N&$YpZILy`bTG+*~v1YTw zws&sR3|m=S4$sOMl=bf_bXr*cZW|-wR~{uVM-LXW=-&ftiMA)pIN1AZ_CBKERmq<# z_b2z3A&ZnJc*4iY>_D%RHasKSoQ@V(&-eB#X_swJQBNg1X+somqj4fV(q=y;_#Mtq zZ4KqJ9Tj?Ivq1a7;W@o?F1G2+9uXLVTZrc<2l$P-O6r{Cn!^UJF#m!5mXJNSvfUBn z9peP(ZPY#0X=rW4uR^EMN_jIzpna^2^@g!fJ*dkjjpb4M(EN15_iHvTShY;R{}MZt z#M20jNFz)$&$QdarV1SumIN$1HjDcAAkgUUXApH{*& z`ls~KnbEDq)96#wzW{@C`)lY4m*R4vKHA>KGQQL`#jP}P;bZa~n~9G2@k)>CPcGi~ z=MNfixmWv6nn}TX|Q($;r}nH%C-mU%1Q$2Kzs!-JGS`RK`l^FOv>B zJ86Lv?U+0JtE>w^6Jr(g>1+;rhmwuY3oFv)PxEc++oP8s59M<7yZ8=Y)Wbi%AKE{{ zGBzw7o%l765~LiowYtZpZS?2HhdL%E&H7(&)qGN(zn=Yf&ZtVOrp`+QRGz1iDz^QGb?o&)_fmg+NG}oi1>ZSFXnD-1d&*I^VZ`F|MJmlicR=N_wC?j>))$ z`0uXbBf69~(wi&JL9ZxY*UvtxnH4PSo{J$Ka= zPUJP5x0`%kTAA#WeLBX_l`igG#m1)#I?>HH`fK-zZwfEkfB4FuU-4F^5mFKXrasot0Sf-f3Q!i+wc#$2ca=%0Qc`Kd4o z$#deM-BX%(wXQ*zXmsmX-FTck>%sL|=!-Ew;^Rd>8N4nV*Sju;(z)&mPQpa)1)Qvp zU&&v2Oi}*m_cLb17`TsFVK|ZJg4Y-)+1$+SEcZv}7zelxj+#Rty}N*w@-6oqCp&k; z*K@qFGS)B4zg%P(^9b-7*lCZVcSk{@UCwbKc=F;b;0Dw3Tjctc{T}9ssY^o6ozXXNL0@JWt#CHQqSBWNn$J zsB^4aQds3%&sVv~IK~2)b7q`-wKq1-#riMJGlb{%l*aRP!}&7%x>fD0YJ3F$%w5)_ z4~FBu&NJgutSM8N=ZO(%i;loWE`{bhOinr7&znDCEhShf?6c%SafDsQpIHN?`WL44 zS<<{t*f3p{XYgPw#9el8{8R0Zvi8>r$j^0XsO492k%rb~>YeY_3V&1Y{j{!guk;lr zyqAaf^7E{&(x_Gz`u418)DvE5$*m`h{3uK{SAK57troxD-9-G2h(q-H?oFrb$L-(W zbUL>kpHDmYw~<~W(zp$}n{hS~Xd=)=pou^efj?^qgxl<=dH#0A>@qAEb7Cz%<086v z4)61?6~~K=S*<)-KYnlFXtI;DbZvd_C}(PGooOxiU@O0fUt53H%K8q*@xV5m#*2nm zn0}sFhe|%{!KD^n;rFZwwe_hBm9-kTq}$&H{ys+V4rkA3UqCpYH}y>X{gxJK-$tHp zI!<9UKJovv_pZT_X6Joh&kilJmhwd+%Th^B77d`$XxtiipwVb_<97va_;Mj+~M|h>~5ER3$aDq#dW^ zB$nh#WfM`8=Xc)zHxAxuU~roTh8oQFp7WmfT%PBDp7WgNT;D-=4(K{%=V_SIj#a+z zUN?_d%}=zkhJrqM8eh-iz0IFj&$WskxmV@yy3#`rdg58NvF)zavDMDtzM|7GM%O!B z>{}?pN9~d4>*DpY`G_W+5j>5LtAyuTOYR;mokKn?FZxn<2UX>p!mO*>`b>2_?6N#w zM>^s3G#+a4h75EMG)CzQYrR*P?gFzrB~G04*L%6hoaoWnGW5Vr@39k2xGB3Lj=jDY z(cj_=yFt9xa>tZV3OH|yrQa}B*9+Mnhs zJ+eSt?m)o5w#;U^`g7!)p5Ma1Uo@`DKn{dOE*0E!p?7|}lg!g5 z)W#GKK37MR%ivHbwT^^wc-r%3rrq6l3Y_lv|AkKsNV z*-{%CI~X1khR~`sxU?JO~+qC>3o&X^F{o$KV%TRMGr1>Ezm$ep!;q8_rCu;JYOb`Uxxh1 zw~v+dRNu}}!oQb}_JFP>ozCiA1eb8!Y-^j-fuaMqXDYaFTs8u2E-X)%;rlXae7f*s z?}CBamu$J=wvMEa6YurzymvQ+vGJd2Yw8=3p{4frG4e(C&>ted=%Vmk-eq{cY8r6z z`(w4OwyBAZT)SP*9J=RFw!`q?#E|+j`ZIoW3+bM#>MC#qFX+Oqk{#vO?NxccOnQ}1 zUxK`-PwU@pU*!zt#>!^(eo@|Q+@W+~mwwBa8TvouhP_Oq@tJwPd8_;R{CK{fHZ7gS z9GJ?u41d>^Ml_(K7$Zn;+IidwaN5a_=G7i?W!LbHQTPQH{c7?@ zxY!?Ro7ctjW%ChMa+9&P!LfAr!th?-Zg~8UUL_tl`Fx$`$KE9VN_=9Wm`EoErxM#d zAFS*SoR)@gFn8tHoSonHF3aO}q=O#*sqWh+_Z%;TF<0Wt6Z#&T0X=)3K9Bn%$%pfY z>dR<EzSKMcm`P_a@50zweUi^x*iS#l zIG6j5c!v%;NKVazDbL)25!?Y4tf%_xE?432I?{?4<_U$5?@Fc|AEsl%wlQNc(Q#Pr z-pm*BZro2>LLYO_FZL7Zvvcc3oz0M*R(#v9-o_q(yGz1-8-a3txm6iA^b8xb+S!)qaveU?eyxiQNou$#aSL7FY7M?eS zkIEI_)SZu!KgYw_7M*XQZE#M=?zyPmmx^wqeR8%89QYyY=6r8*K3o{#!V7%(IviV4yalw|8MDefF!=cA7lV29+PYUb$puTv(-Sy3 znQAGKH)WCrT(!o)vrl(D{h}Y8%z6_2Ju;=a$`f~2xI23+h1Gi%C!IOt?9l9_okz2~ zKnzd#4Cal4JAPCSZ4EgCFJJGoet0vRpLU9TaL<#{YQ2X!cyxls3Z$*4EKydNUY<4Ii#`?2&NX@A{blaS z3i`2NT|)f=c`+w|ZABP;rS*n+m8pBOSjR!eRewIs^}@?9^Q1pzI;iPjx??!IS!%X* zq0ODeLM}!e`fc%Y5m!1#dXIh%+g!F2b`<3(Pp$WW4|+=do=<1JaPrIX%csqaAMB=i zPoIxnN!xHZ&7{rFIjxH?W{x{R}u7MHnGt+Vr7FD#x`j!*a2 zSpT5rfc?JdqIVri_M~r)zdwR4ak4-3%V!OPxk8PbZWB)6C|c>mncw7@vAyPzF0G%Y z?RGiKtBSeo3v5<*hu!hLx6Bjv4lbNnD|}iV-^6=iC71CTb0R!nuD|PuVt0{V`uK#s zYHfF5x2ZZ0u5#tx1P13VQ#9hzck2#BH*PtnPEwo0l|7_xIrPPdP)jv+d%t%nA`bVGM&GUl&*Uxc{qcVnLg z{_CVybf^yW?7P=l-bM5B>A)Y1=NYRqc4bX2*=+NVuHWN5Yb82s!ShASJ1u^gj#|&B zrL9+ZEt<{>ldThub5(l7`T5UR&HFmi`}EZE`(@O6uP{H}Rs70N?p5--&a|Qj_i6e1 zal`(nrM<{|<$aMf^@w{Oj6{cckgM<)?h6E7An*c#7YMvS;ExLe>H~fEj|=ao@#$l6 zUjJ!%eJ_Qdg$46=?5DJ?D4p#0Txefhva=vlHV4Pks4xx}d0xxp+Ooq3)%z`!|MMbWqE~La z?K1@%ch7=-YxE*moF^`LkL@m0=P)Vvwqqr1ID3a)q0ZUEeI9w1;+J!pUwD8kwg~a27LM=fQdzjf_49d_So!7Phc@gO^a%3p z)5Y^?b|v!UpZ%(pZ+doca&j-*ywH{(TC{J&t&X-Y^W$u6YP*;rjpT`Pbzc{@yHAJw zyCzd%oBmm01#OhYch;)BRrW|C6JeT=3+Pk0o%xKZ%_u$Rd?r(ECH9=_%>HS2I_U0$ z?d2s~8?-(6HU^T8M^6$)etwzi9W}XMquUsto!bbbx!d?{nMf z3TLOFUnDoutGXXUY18qx+(w68QD}P&e7?`)2OGZ2xS5F`^h^&nk*D^mP;X#`?8xS# zexL`sRKDD2g^`aF^6Sn6hwQlY{NlE7l01p7*@gBl^vY%M5r*OKe1Z{YL(pTCBdpL_ zJR`H{s(RW_;@7|1f%*e8jT_PnOZ|Ma6|AUN(x5BQJ6FL+IHAMQ-($NidGgf#J%^>? zOeVhI_IJ>}p{rI~tA`8;C+bH!QvDfYU*026%b9|cDf(&J9Q`5ps31%5M*X9!d0t=2 z+Zo^Hx$F4(STVOn`QiDOdg25g$P{$2w+$Q^BM?3~bTBY`*ijwl>5iVA%x?7_XW=au zeG|qBT+u=FfyfW(!*Oaovk#5?TF6`dn`{M@S5K_yQ>1^uina$Gc2~}1q*fU!AKj!eo#sjO4%%fu&`%Rin>q~}WJERtvWHGW-z&eTx#$6OfNXKiLy@i) z5A_HW&Hh-ObpwSg2 zXYo*vccMpgWauI0G+5(Sm_PPJUa&=FC(s9ShfJ|MSC9+c#F6fy|H9S`a9hvl4k+1; z!5Q{=(e98KbNjH}UiFiA{L}-Bv&s-or_GCdbJdG}Ju4kpfG2GgocO6cY>D*jgd3~% zOl>*4067#+nm4gKXEyker`^NS(_T4;ZFh~ds~qKdQ?BTMCuGV05vDezdsW~=Y0h$K zFJK~>QC!-ZaH8$G@XFjEy6NP(|9DaJJU4}p%7sp7_wkWmdg_G!sNTQUm~%W?TM2Zq z-B)MxSHYR_)9+zpY*fW5H0Or=NS5SE&Y)8?*V|PcYrGi-ePGrQlwM;O+wdEKra><*+!3(UbQafVIl2<$@XQoH;K)FaJJD(Oqv> z^rBCXZMwvyY)Xy$+#P+UTbYwm8s^uSE77y!_&lEQbN3bP(j+lFf2{EeYg_c2$=%Hu z@~HEEq^UPHDo^~?a%B&Manc-~KfYsJOCGe36S!3REI&;Bm+FK*LgQlHgS%hK%`sN- z<>)ry1b)Iy`bu+%YIm{`u$i=epgAJ+t&d49zxqneJAe~1>CX>HwxH#<*y55c--SNv z79FMefx!Ojh^~%xFKIs)V`0e!X=FFl!bf4ki7|=lq?XGZVY;ogZO7&aeY@YM^QQfx zn>Hprt~NDx&_9G7>Gx9sMo;$V!p3*i?!ZaoM%R~OYgBX>W1_{((k|;5=tE>%G~wPf zJ}Td*>DYgK26nzs9s{f6v6**|Z4I4t0;kHj4V5}(BdV1)ocvkKuq0HNg$7ysyGjm2W9mDC) zx!g6}4SBZi*E+&!^xVd9$rAHw(05So*vBS+s$5(|hC*@8UZ~nmw-J+CGzlkM<`5JI z*?Lx3u}?yEgRbUs$b?+%c)m-(H!X5`~Mbq4i`1Ir8SNLslMIW}N{NXW%!mq<+FAIA-G^c!8 zp0@=b(IGnBI#cETet6KH0lh!3t9)y@$^)#}JLJ#(>YdzL>FXT^Eh#Ji4i{X9;TZTah; zALlmsMVDOWB5Tb@>V4R~4j!IGp4UNFIFB%${xfm?=deGV*Z1;sn0KCiervr~m>=(t zgI|1yF%s|od-?V5kDGfMMt|IJc){-r1YRKU0)g*k1k~4^$NgT$p%!oF!Q?z~YUTaB zht=Y{tAAjd@0QGr%-U9*zG?Oc@LL*f-{L1f@7Uv*n(eC2&-nR0@7O@U&kug)JEr&3 zskP2rVz)H9puMl>b=d>T9v zQmr!!Ps8E7@4;()e(1y*?c0u*kCDxPkI_EP%kNd=q2pBkZN^D7CO5Z=tZiOK_nd|m zd2uH6wD$_Py{pwVVbSBeH;tcYVV&cmGK9|JOoMo>8@f9!G4`X@Bk3oGFhcKOzwuXEwWeZTFLHmUF0)3(3^ zoZ$%`>F=xG>o(r_M;LNaIfIlB%b3ozvG>Zyki4l!Kfh;ugK-9d{L|EXoUXUTP896HZ{?JZa(hlRXpG28{gU1Hh1ofbzRO-ALje3_d*;LcL%xiLBEOC z?S0bw?F+1AA5cfGuB=Y{a^!!O7?C&SP{*oA^+zfnSMsAi&40)DrQnfsW?%u|J|3st z0}&3ldqbMY7di3uqHIp&)t71FK5J~0zxYKzK!bkNoo}lMC*G@mx$gs9xc4H=^JSlP zXARhh7TE{tgC*1T!buq6(oey^WC~s2>qs9bjqQ<}%i`guE99F~8?JX2JX$s&IR`w zsh#;UOxb?@Ju7^auTPu&j3=Opz6*UtxcaZue73NY4ek^}fAbEVq&s-n(}f@1d>-t; ziF^8x5q|8W;!G!UB|XL5mioAGy-~h+sh2C9um5>+U`D^@GyN zMHbG3)6?S6Pm-s`fV4rzLn^0U*!bnBY%q~Mt#+n1Hr&>cwC^BS^}P0N;UWvEnPLWc zV9!_>1N6^|^@Zr@^R`vuK^HnxdR%3SUZ010_*Jf4Y-Gthco9CjFgLK$S>BY6Vy>5P z+FKYG|Cu(VHmv-?&5u*dPrJnaA`N|r()w;au<^_A%LXH1fy*=RGYjQOA1BrE)7sfm zd(zpWOvGb^6B*Hucu!$(9V3EG%g=o>|dD8v>xak`T{w@ z#yrb@vU?)kxPGudvCWTio+eMolG2fXb>6_z))SLjWeKOb#pJZGz?Hs2o+i?Ts_n-+ z#(kutZJj0)@GQ9??&My&xmH|c3~c5W(!Kp#+tqf)7)pIE>1)wm&oJTS+bm$AZ{BuJ z1$Uy--h?BVlJ03b3ar2q9QKN%N#{2`&6p1iPupAF)6%tqUKDM&2`6kL;UGKMrxW>- zoh%(iUxyyTezJaT20wB`-;UjQ`rN>A&eHYNi~3mV2CR-_-5zjQm7Z-O{IGD|aF=S4khjSduvkwQ=$Z z(_YVK%IBZjlw=C~{8(=0H@G`Y`^ITc(z#$#?C!TawaaDB^=Pb&{y`6sH~N^fj_T*N z=H*JZIYF2A?2yfgr<^UW`6g(Aj)20O#|d7cN#hq`rSUoQcK$tA@bB9>w8fp`>L_^e z(|n)!L*~Fq@&iuNONp7G>iuE(NfVyyk&VK;ddiSr7G3rJj<@f28-?yX0 zSKCayiTB_sIbf_W-4&cwuzURM9Ha8_UHAsS@SL{dxcdMr=Y$i}V{T1~c>>8bW2u|e z=c3bheVo*O?3~mJGR1rW{S@uTUmN0G^?a+vP0Vbh-5fhII5pwMYJM5=(-z5Zs-q*L z^t!`9^YZ9O^qOp2rLC7NsT|71ukz`ORgbcN!~=6Iydyq3TlVsqcVvN^m4WO@7X7lw zi}?tZk(eo2?BjWP-)>Mkxum^`Kb4Q%fCv3IVSc-SAMl!NPgbx!z8gxso^YMc3GVC` zPT1wD1N6R+liE0a12ky-B--TO1U@QLG)U&Pc6p**RrPJ4i_VlK7dMb6FhZwM26Iv) zv%!6u*qRO}@O1rMaITiN$ULg#Ni^OTS6E>as2``VtKLNfKhim-b5F=lMHl;F31=4t z>tDXDO*yi?f_`Bhi>KBbKw+r-MvPfQLNYp!97PO?{V_+ zk^gBpsV!0-dHUrhV}nEfIPbQ|lIZYht>x!lu&R93kRf3dxJ}i&#HEvhd)p*GHa0SR zIHNr^I8^hDt51Vyylt*eBjbw8+ykZi?35R}I=KIrJAeY2T#3!hZ*Hzs=bwlR7D^-c zw&CN`BN~IYcJX^coIP)R>!00YzVFMNozLFo-nH%KZ8shyo?rg+&#ye4)V~*zlZ(Vf&#P{pC#*zs(4RlscIWVPcWwlwK94vt56(SS zi%aEHvUREXA~JH`xNclm+4lre&m&IEqcEQW?fc2yUDiL(%YUtSJ*|ai^5Bj!#=^>* zIb@Azo+q53Rc(*86V_I?R)&X|6G6VGLK}K2E|5mpW&x50B#aye=3cH|vItzfR!i|2*O({>2A-;xzY* z%RV4@hIiJu_^}qivwo~MA&ab8D6R67%UTY5>-4O0pEpJ+uJ`Ou2+Ne-)k=3;!$dQC z4Yha2-807ArGB>NqIehKLutUDbwWM+?nUyu$+)7~?M=yPx>BHQ!HW&TgwKH?rQj z+O;&A+?tp_`7K`MeLFcnA64Q(F4)X34$b&y7?|(A=nqVnJJNgFFRT2|N7e0#CA#JE zO?STEa#1|a6CccNJ;$9_Q+c-siPI?&t+<^3p}m}k->b$6_8=aYemaFW|3*|YXTrHW z^vhNGzesw%10x!I_vVo~NddI6NAM#0hx0nMba)sa;-JsN;o;}>?DmQCcef2M(Gxx| z9OlD+=KL43hko(HYx#-8H%-o}gXx9fd>XW{u8L078Aj1}vS#b|r1IsmZ=1eId+uxT ztT5f>qjOgZujOh@(?2`r#|!Hx|2(dLt{OV)hfYwEu)z&~x7_4p<2*WCd&8gB_H-`- z=T>}tD<2=gIQl}|a+PvprnKgv}3;k@dJlk`RPtgC$|DZ$ThQXA3t zq8Hj1m%tABI_;beaamKJoX^JCGqAF_F}vE)zQp}0+_A-vXYOX949P5*AVY+O`vuCa zH%5MWqpgi=IzNefavYIbT#W)@^q^cF!o@z`%9~nAjeGwnC|O zB+UCop2>rJGsEe`W~tfTLkBK8tAz{+CtUhe;@1nOT3D%lL62}67;akJF7@Y;Gw4G{ zT;{I6)35_)^6ehjHl;SVD@>%f*>{hgLf_NRXdiw(aq_X6oZmSyexn^ge>zca11HH7 z_gtLD^JT*Wou68qJ?z*QPPoiVKtrv6H-!`O4Hnop)S1pLXGRJW-~`>!i;lW19<|b; z$FzrPEZu$L`vJA|HZ;^5BVV4VJDmrYzHXmN?B$j^%EC$gGVKojaOJOsL9MWz&dnJ2 zi=p3ev127K>5;jC?R@`+WQw*fTkfXt@#{o%;$r_W--sU_?&G90sA1a(8y`INz6yJBbvnPy6 zt!LyATR=9HyZ@`da;!c1YZ4Uk{@Jmy{0#(jB$PSJc5u5hA{V|=A&-2R=$Y9Az< zhH&nFLcf5K_?4S$4ekr|^Eu0w;OJ{o*=%ncIn5JU%EWkzUypF#!}>sTuEQ@TyJdr z@+hBw)EzooV`AC9v_;udvKeSA$O!3ZgW^{%dYXQacVT%`9JyfV+fZtA*ecL-)A#iV zE8&E!OK0OEU%V4uv`gj)2tzON!_OF4JmVr~np+@kW@md5eGaaSQ_$PUBf6e8>f1=z zwYsxFb5Fj`6wNo`3Mc6CapL)yhrPmKxqB-=I_u65A}bnK&}Nt)L9fd`0;l7&D&Z`5 z-mS4DV`J{VSK7U3L8c_fH-QgjigIiL>JR#u?}kRkF&dxSKKkt8>S&?3I(InRmUjJ< z($;bZ28!LmU2BV@$f4q3^Go*;W_KH8?EJaiSC)3NOBga3UXzi&;{8ovCHm>-WN%BZ zq|<}@FFK+t%cFKbZ}5j~X`KxjQ`Zji5?*XL|@<^CgVfLd!8 zqNUzA2_Lz^{C#j&j^thTX8UYl^1qt8(<|ptUFMAyxOK$++9v?y`jQiI3KV< zez3uOdy06-YBhhmgND4@Y^8^Hn!{APR=yg`=o$A}V^k}Dl`s2Ax)a^uW5nG$LEOE9 z-Ho!%JLj6N5AdsfpP%yII9%t>Rvkp`F=uG5Ea(?2@ zFvCLe?Czfa6Zlozr`^F*#WGkMR2p35LT6=r_xcmnJWOBlp0=jBa(^5J|H|iCV{umg zqM?=@Tsh~Huile2(^9JPSHYjW6|= zn6tYrW0o*(!isuCp3u)v=xAHlQ+pGSwOn*G`AIi1e$m_j*irU$N5@DtZB+*6^UMJ= zci`JvVOnqUSvbkXp26BawNWy!3s`pZkI8fbT>L4KAGPN$0rSQz+fdhZW5ET z$`*aN%mHa^YImO;h_9!)>Jy)kN6QmkzP>V-5AtX_0Dr$s=Dj+n8+#RY7Ogk=PV~uD zpKRx)E4-c5MYS+fKd*Kd+{5Gbg>G%0wi(#BU45z9<*C8yIdheLlQ=xBY-m&*(Thu4 zs)b3-uu9*kxdU)QuLbxWt6efgzj0Z1J%Ksk6Z0Y$lr!c<8OO~QHYXUv?3FfmkQe4$G~fQb$rAKSp4b~feG|qX{2^n= z0>7}VIXrB<%iI9*f_<@@cFow_VUWY||H0^ZuYFMB@!RLeC#)E=Eu_=4K3-uiz=5@_ zaJc_`kSy=9rx#tsI?VAH=lRk}K2P|ClkYP3f(&TgfU^bsm=|R}j_~l0xm~Tr`+4El zUIYB$@}H+?@x>ab_5~>HI$ZWkDWB&Fms+&K2lGlkPvR{Y&)FJ^%}@G2tveC#v^;sI zwfEEF)k=F?!-R>})%A>f+V>MQA9Wi4%7b?2f3y0wVsIY1#FOumuKH~2y}^3S@f<<0 zPH=J_K=DytFvRh zc>4l@7YMvS;MpP|T_pF}mUcUH7w?yKZzosRL)Aqw85nHoWiKi}&hXV5yD87>q3~vN z5ifGt!(wNs2AGRv-_LsIQYZVD+5heTcC#n%kJ>49&#;$we7>(m`=OMl+?(a}a;1xQ zx$K_=n=t>{Pkj-WJisIp^w|;sJ)p~!Ui`tA8$ftE`q~F$2e6=Ue7=-iipXo!P!R>>c8g%E)kS{+De)>$`#;9+L3+6ni ztMj%u`YQOsJ__^VKkIA(xGJ1>h-~=s;-7Q1JE$B^wq?J1{|j5+>4VVIKJDlAgGV@TKP~6b{I)4wN1S@#Lm8rnGndu#gi{G8 z_t-2x{nRshR%bnx)^|D6$+>FQb@~1qcdzI^mG#2L_ELNM*z&>b6#nVdtnKZ!a~f^U z?K{cgYMp=y;jB4J4#WDdf2-)uE7Sug@khTwTS3?KOb<3GJhhkI7yZbN!f{!*<@^&^ zaK>k^IGQY$=EnUq`cLz(v@cGR7dYuGnd(LTKJ5&=h(}xIJ$h3%)U(FP=NTE1T+;{X zd>}YMKkp<%@W!1NPs89m?|qy$x`I26gp=0fc~&0?Hpn!xCHkKwPAbE9b>0-Z@beCw zpkK0-o*g;YJ%(ptR4Q#&^YC%vP9tH2t9qf{c$SUs)BG$kB5%Je{K&XJ#-;BfJUz11 z5B)mZ$yvj*FgWWSY1Mwnn{N!Fr(8MK?iQA(s`vPvz^QUxnJ~#YY54c7aSCI_To82d zqm8NUa|RBa^vt~<+lQ;o=wM_4oy_xD_~>0`F1TApJfiP?c?#pCGm8Fr2pdi5>w%HV zP?>(4lP=IZ-8~GS=xl|{HahA*dD)f6`jNa!yE#*i1o?Sk9-ywBJ8R#R`p)XJ3 zp&qVy6;8gs=B^zuP#k0jdE(9s?vEKCUf-qfKkaTh;vTH*4*2>gjH8d!Oh>`pktIxI ztNUX+=}l;=2RW_h!RJ)cDb<5D-)U);%~C-C!*@s0F(E&1@nkVo_!eZRsP*U;9GIc!#yC!D0G zPn)Merj(|hxYQ~OIggXN->^v>6_4J;w2mdeT-cc zo`2z9ZJkRD&kG12xi@8NhU-AQ*%{rF_w*Q6!io78&Bb9$&`#AiDSg;Qw-mc`g+*)2 z?w!dF_qqA;PHS(%2p7GjG-2B7`79b}V_icBd)m{Ci;U?#YiZkKx$0eP`^kPcM}kao zt_A$4dyRRD-ThnAbI4Bho-)JA_TalY8^*pqCa3u|rh%4vV&j)39B`rE$LaXKqTmh- z;(!PJ5kH>6Pxpx7nmy$1rqehC{DU@qyazwHcP+U4!5`0^h7+<$8y2lT{q^#z?7)Sm zjRE*@cvbGy;Xah04F-1?5m!2zc~KuH-A#8gU!GEKU%Bc*d&@P3s)Z4AEVOstY5j(r z>V=J8j`%q_-?LY6d*yZCTIJpz+NHy*a)%LVndA3y(l}cAI=9lVC2W2Q7n2sfE*R8{fejdQ#&BXa+aJ?QBolmw^+0WU8`OBYfnNANDjjVZWY8 zSFz7zC$L|^$B8*Sej3-1C;8mOpZM`z&1X2ADr2i!c9qX_+jL`&Jp8pt&0{eK0B_h) zej52XyGL4VEFUMv$c+D(qf)QYU4 z@@!7OT*^n5vWuHLV8s|m^o8lJ_p|8m<^S9`RqjwjhNPpIyV5=P*rSXYeT=pKtaAPN zdT^5d?wJ|cpxrB8y>Y2k9<+uk+2Z007YrDmRPKfvP&?(_RCBNn zt#PK=BuBElXNk>R&g@>%9jJ>Etfex?h)fovGinc@0!1U zp!pWXzX?3fDpPd%E_SouW}fiRPP*{~{hR&VystZV?)tRgu2%Yg<~rv#+oHlp_pT8} zdB_m`2sXHMH{oZ|d(-bu;8d~2pTMWuw{L6_AKfIJ!gDm}V&M{Y*PAD*^8w_eyB2Rd zMyexW^~Bg%_*7iRGKwn~`SEcDC;$GwjqQo$rGc3|Kf9kUuK7Bpmn&LsvnyKdJaoIy z^OOE~5!(QL;!qm$#4AWgg&%-i_$27!&Qc^1k96S=n;AJKM<(@EKQ5~nA}GZ&6i z87n?d_}mCi)`oq1K{PxM?y)>Qt=(ONJfZ8V_ebCEJ}z8$$2f)NI752;!fot~^uhW< zP;!`_+xmQr)6?&0zY12__Tgd1HH?*S(|X-`>qR)_T1(N>=8rClPv=~&iM^TJQOEv9 z#>ddZngbWa>)vz9_URNYe%NjDLmy*fXxdNi?o#iIox?N8KwoP3_*(~|w&dfne7HN$ z-dN-%%o}4##z+2~%xM^f!^3&q)U)c4@g8F@>O4#f@&E?N1{gAqt%Zlu@s71E=7=@# zqH=s!@%=FT3cqcxPbcFy_Hi;sWj>ZUUF3mz6Xuxsfh9k}z(Z@JjH`q7g;aHIiM(0+ zV~w4C7_KaDeF7}}^6}p`e0+Msv|jZYI|&<~e88SP32Jxt?HI%Hc3*Gw(=W&69QYsvUJw?o`fg#Kxydbe{JPN5w}rSR=)T^f5Zd z<9MCMjSp>X7|bI-iIY#yZS)`WeA4$cT2IE-6YHne?%aK2!5#y>Igk6aGH>$zY4o3$ zrqj}&6|TI)aTId~Y)Cv*ab5_f7J7U1j?`U3Z?>mEVheULf!S zffoq8K;Q)eH-UiPN6LQ_bkw^{@p|2Ez4>@ncdd@0i=U>m`8E=LUO0XDnYC1C(6^fB5Bl8QA$~l6 z-~VNJylNU@gxo)kZ_!QvPC9>2rQXR!uMy`wXUD4YWbyf@dwP@?F0}b)Laxg9MbihA z)uzp-Q-1O9_UIbz3J<%;9C>rbG5jw4to}~>U~9=BI*e~viC(!E<@Yl2RTge7+QR(s zjLk%RbZxEo3R67Vl)_GP)u!n4kZX6=-Ej8f`+DA|8~X!DzxiRF5HF0zYKfd3_`tDivA3moc?7;#%AG(HS*4^D9VcdClS$;2@F2IR1t-%>o z>?YBLyPD~4VJ|oBK$u?CCGEggvCBV~PCN6<(b+7qb1wZbu;m6%YweB_0y$__NTsw4rLRPdtOnoD5 z&c!o%6`s;}H;L0^qNNB9(7oydn?0TXYno!&f{_)6lDzTwlD1DN2_Pa&|id8 zPv8P>vcZvYbRG3Z9R6Ll{ahxU%EU!B>|Q6ghlFQgG`8E4KM()sjdL1KU_-g=Uy=OK z<`{$fbjp7jelMFwW#S@B>_hUy@N;L%MelwDGuj|BI=z=~#Z~*2j12EJZETnNtM~qb zjdY-J!bPs=AEmFL>9YJ@Hk~jL4|?|RR6q}5`=Nv3m%EP6bAJ|XRr&dD&(xN?&oq@t z7sB^K3Jd8+;f4N2&Xmt(`Mqp9m1`gN9bN6%I9yCGE^HjG+Wo%WQ@jHkcfZ(naKD)1 zgWGxZ)xpZGdce*W_tb_S;zy0wQ_ z_f(*B&!eA-C%r?SXX*a*P;dv7-9Ks8d~hGD=8mynNguYYz)HHHUf6`oaah^i=>9%% zox?m$Zo=59E%k5A=R3_#C(l~#lCYrtr1G4PMvtS5&^?-4CN1qRJa54`!O?2(!#vdE zS!Gx6(y{%KvdzzGKR#CIcJj#&jLm};{#rPpuXxAVXmG-Ql6^_IudA6CP@BWmd;;<6 zflIgy%H^NiLs{7?&wVk3)#BC1M}Bm*^1(&_>z(hS-*`V1pBx=8442?vV-X)C<>l*h zjj4GT=AmBC0bO=KQ|0ax-FbpNg>LqFJ7zrZ`ju<#F`*q!hU7PKS!d;f<{LvDyi zdqlRBzg%pB#m+f*2eRfdYw2zuC;a~XIAI>@@htk$OOh${RWR3bd_UH4yo>qV_sjOv zgX$CM>%fV2#rT@s{5x>M_~`kjbrf|W&ckQ$b-sC}qi+ivl=&yd^7KEdU&exro%zWg zB+k~#@DOJ?$e*+tmoNs#2GKVM&O46^uF8WvZ{kll;a1z9>2;k&MbCnje-=n{)#w!6 zlO^7X3m@Qw?(y^Y{n!KHaf;-pmaBG39yg7X!)m&1ihC|(bBZ_G33J%URd#q{hj8XJ zg%g;$Fnh;1Nb=?KbmtN_wx|beTlE*rU)I8;Rv2~_^QWRmZap!hOxlpfqoM(~jdSsRa>IVnaT_oaUp|dm`>2W2T-@#w z57r-8Z=wC^9x?Jle^Jl#9p%ZB_~;xzI0flzt^fLT+|=B7SWZ<>^e4<~Fy{lEvX}jF zjnA`mvC@ZK>;ulaCR>*(?N%6ZUqNus4{7Kdd|dD|{=;s^*7C=JVcP5U9OjK@&F4!m z9P1~KPuk8bcl87^A-zN&hb^wTOKbzqUiNa4iV72`Y2$uVCF&nIv)S<>DVl^>p;qwM~np*H4-!HV&-;)Z#s z=QA`=9xl2DoHSOj`{eph@L8E#AWUsfI5BU>*q3oJc`=V1;M8}!%=ZF6^+Upq(9a`JhnB(-mov}@D2d2if?z}kmk_-2-3GCH&yQ`Zq-bPDtnY+cd zo41D;w}G?9F!UpmPk8rnswWm_l_i?!>vX3v`ucQv3eJrm+f93g&bg*T;wR$=yG|C7 zN6Ulo*@5C=`0lk#-=3Q{piJaR^>bTfrxsqq30G~YI^W{yCE=#MF30j@>1wpol!a}@ z8dG76c%GXI?();vL^RZ*?>2>r&cJ0}Dr66M&*+(x@l$z!94EP|g^$8E`X}6XUNvt* zezysar_tj0x4S&f!in~Tz3yx*(>=A?DD4fMEnIvT{lvS@sg+yRpFIs5|2;U>ynEb} zr!z4O#Y11w{`6z6T*DyN=qE&5pN2-ZCo7uGxbW2|Aq zw|=x8!g$9z9_v$#{h1G7og$oPu61OC{nDw*zP(_~ZR-uJN!$Hw!93N;@pL#3|GA#{ z_+^O(^oBqGt?&!GZZ4s1O7m8HSC2gkfnJ*5&=~rpE(AB5+jF+)lXs1Y2A}Sm@QV)i zS!kcR!Y=08`U+zk>pQ_i>+;Njk`Hq+C-FHRS33N>@2A}a4o@pnSTOJH&kH>*o&R2W zI6Szk+^qqcTvhrC=T;?_l5XaDTV`4fjkqx4Un8 znCGh7-Q6?TKRDe#<$?!$$7h1~mc+&D?jESPVJD@4AN%w>JzZ~p{xgxt_kASt$yXZg z{_~Gi+&|d(M}OzxE0G70hv|R*@9svv*zVyvcL?WMj_@{FpzVwmE z(FYd(iAXN>@Z*(di}Oi){>hg<`Pug(k)}TuA3ip|AOC3N!4FvcN5-$EX^Xu3 z?{7pRcRn8Z@mDrJxEpDE_@nn9Jo;$vLo4TJBUXMc68U)K{m2@aJ^az!gUClBKk(4< z2*zeKs<`1l(U$M1K)`VarkcMXGw#v6QEoYdoF50kE(wTBiLKY9PIg-0ThzaNRT9{t2eB0ulP`55VwMz@s#-H$A9lgkuk z{N~+i+#evnzr^$33*Nob8u`+%{eO=)b9e5q|6>>LI1gy0?!NogUk~cFg5jgP#*5)& zI5wg=3BxdJv}c35`5zr^RyX%skAB*4j9A=1X>lU=jmCCsYh`l{`$**L z>ks=P4;<}7mj0Jb?yW6Z-rpjx|B!s!a}OR_oqy1md+_a{+=K7jz1#NfyDznUV6tl1 zw>cUfwjTYVmGgKf^5Cx;Pmkl)o_0)TkdJcq$ar}W{aVDt%AUU%JU8%cvR=*Oz3fqg z$;!hfON+euajlKr`P!Y0heiYWd|)*BdFSjs?Zwi6-0HXOQ9O{lhepTagUEw>M$=1% z0paj9Wqds@MIJ1He^Vd>k)MvNLC>8(7x{z>vwENoT=>^M@`;FrTmEgh_WQwy-!Pda ztsn1mf9^Q_$Ncm!J(>PzD(U@rum8w#`tSGBTX|2E|Ff0!f5v3TFnefqgS_0gx;NS! z=B^!n!`j~HpV@f$Gsa8dhry`r(a)Mca;MGdkar?SU$^?UdiW;T{13Ec!zn_(hTp@I zVU3P4ydL5A>NIQZ=I;Ofc=M6fiysb-R?cF$E*>6K^0GR4gx{-U^7{7gKi<6m{rA_u z`bUp{;UV%vxh7LpS-Ky{j*I(m9&f(>`0)>Y_p3pBpgvuG?$aPwxhrCQsn2+2LTUl zM}N(po&Wu|qZs^{{JQ6c_M>;9Rs7}Jk7g^heoFk^Z+HA{dbG}wMtNA8kxH5{f9qbF zwD~W@ALSZ2Uo1ut)p%lg8usj|@X(Ak6Qd_0pJ~fWG_im4?Xg{cY>tzD?cxW!$~{%|H0=lXce~ z;w>)Tavev_@*6Mz9yE!M`yEIBQ-!9gT)rRh@vj^mfn5I2=C7uSbRN0>^MovSI^JDg z6fM#`u=D6AjK`{s!-L7d57&@^ zM|V!j`2S+h)jDeEI{K@p(Drvd+Wy)_Xe)OeZTqz43@fAU_iEJPKM2wGU)!_e@4c?0 zY0INZXC!&_*;DBJhDYb;oF5zO&hPycHWWI*bgJ1AX6OC%dilM7@HTqP*8#s6qT#QK zhH~=gFU$X4@+fNbkY8g(Z(AE#e_drGzaKIAr5~6y8{*-eFXhbt?@U)Z*{-|`3h#eUkIh&wda7g?xQX92R7e7 zaW>y~zxv-f+sD0szx!yJxL^6H_5bS+AOC_2%k>=1Rnz=hCCz_voaTPd(YNgV!`C85 z8Iyqz%q88O_j;UMd^Ri>@An+_Tl{}vdigl+h>KgU#Jyv6`xmK?SMEG`^vZb92faUX z^xs;#-|*8#(k|V4CEc$Xh9*-^-$hKO{)*-CtA6~3ApVTvTRA^ZIZbySJZu_wef>|l zda(Y|;{07p`^drr9MVUB-OB$JKfn7ye!Z3aUah448O!tAh66T0fCcgHe)EB0N*@J( z;AK72(YGw@Vcg1(k3S&Y&sqMY{gia%`$5`oR?!fYJ^B`)r{loV02mg_! zzwgr*8Fl!)EPewS`?)*+)@0DqylwH{_2cJ)_Yuw7pO$`6@he@L^X*hiCrB9em z6WFKa(IW%<=U?~JzZazcKP%~9y&KuQ`;nhpw>GtYC-QZ};_KhKXJtP8C9_9=2^-OD z*Y`({CM=(aJiqs+O?GmrY8jEtQQF=Sx53gjRK{!m`#yU=>C@1VaXkOC3JpK?1P%AU zH3bcS%V_vp$21tO7FL^vAE~^HIzG%sbm>mg`2!XwYIK~a_Z+m`{bpLU1oB}xyz(#p ztWR?}p!q%FX7S?YXPoqb+SC0Y&M$az{+iWm#lHEu$a|TiVnl8GcPj1lAGvn=UqSyX zX7jyb_Fp7oA~tsPFD>q$di?ko9y@z4h=)uXkKg()iT_$I_3$T+*Pk?f*B|*(*=WLV zb0DA0ne2S`tHE5rcfb0pu8fC2WO&9S4;bS={2{a7UWt4dxyyJ7d&BHD8*iCz{@wR% z{AXjr5C0szS@||L_(9^|VJvGd_0O0!V)3faR{nkDzViOh812r_7|+Tz+xo$sk3`le zpY}CwV{~Y=IRh8Z!csO~{P4S9{qHNdRL1Ov3FAmN_V{Is^UFcmzh=CS2W|J~BKOCR zzG8T|apf-u_`Kur%stS!`MY1O;AgzMc?#pz=s9|1&+zjdF>;KI1=rk-14;SwALnRJl zR^mUrYvTsv^}RoFfBn}iK61d^Lc_=2{}CIHnC=PEMhxS}RtE1surT7}Y;0)l&ZTDz z`Q9)7;`;qxeDHR|*WR=FqVjJ?zIJy5`WVwf*L}*gIh3m3^0B#+0EIkhQWZ`P;i6jQl6}_nE7S7@iN)kq50{k+w2T z9^6>icxh-hJ{gNw#&hq(r{&}Hrp1Ln#f>(+|09hqFXO!u?$R55jOD6)Rq$>=E`Rj? zgUG-AiQj(o4U>;I%Ky*9q5I_N=9cckcZDA4!%rUn=KnpOS38!=|0ZZlCO40gkqR5SxC-S9#`bWWh zij(i(vH30KV|3Om>+j!j@>}zr*;e-rQ*5l?{8Q%s=AAE^q%STSANdo zeP3kr^TyvJ!}Q@NoPPPze{N;p>9BhEw?FZhADR51LmL|+Kk$L!@qxuF8TNlS6bD{E zFx}GdwcKB^I;Y+qd@yM`#oFAi)!)H0EF)@VWUY*eXH~{*z{kI~u|uL(8KdXG%8OG2 zE7QLfy=QYAPVd<>vhbf;nWkG#=sh=oQjwj%Y459YX7T?9@oUMP)!C!}J(%zP?pOb* z)8Qunzx6TG(RU(|-!c96O*bF;QJd474CZAuCup|9hpm3Rip*>7&yP2E&UkN}70>AU zi~jqMS{w7}viH{R9{frrjw?SK!RGn!H~e&AIxFe^btMiqe3jSAJM#FL*^OXQ^Zmz7 zKh}Ex>y9QjXK(%YgKt~Bxk@~TExN_p$KziQVf)d@gE#zmVVb`Y@cI|eibL6^TOZk4 zzz2raulRAp<%Z(^##wPG+wyy4H2!NpUYN$acYe#+E~YE6U5xh+zhmh>_L3)CX0KR3 z`r+fdcif!6WTw@R6VA87J9Y8_c%Bt^(r7T;U0kE%+s5~IOppIdEB9YDna+<#K76BA zdeir;xqPg_T9y4JU%&Tb$xpxi>gVr$>dT-0^u4!Tp#ATyFW&n?gBRZL=~v(U+`ZQ$ zUwQNOci$Lkh`rv?@W#D2Kl8@Bf&YtdzWZ7w_|13T{>-NceVM#oo_O`0H(zV$dHLPX zfAQ0n!$;Sq-&Qs*AL5gr zpJx!QnqB1cZ+-a-Myo659gF|@FT8vF(w-}H_K_EVUCGbA_10&<{KcN&F;aP|rs-0I z-XKEozPI{5SxMLB2s_TJ;;Ygh%BE6IZ}okJuKt(b{KA{>S~Y$8o#0in`kXvo)Uz^Q z9)JDEUj4#r_ZljMzw_?vZ+@Yn^^0#Cm<{nCk0&ZQTliaF29V01J>Pr#7}m(kn^qAG z(_eVK^8V$$x4zu)+N)oPzuWNHH$V5ehR=NY?N_7x>3#l)$uy+k_eY)YbFTefvJu9O^NY~4se(UYe)<`sC!40oA zy!OVMpL<=Ajj&fO<>y}g3-2_%`jva{y!H8e4L|ng>-XO3df6d!U}YSh$ZHY6Dn&JX z>MuY<*URs``I#@g`ngg#NsYJ-UwQN0HyVQYt(EG1J<;{@+xI^6<~#4+vr0Shx9)-~ z@f+TF^$V|m?%vyey4UZ0-U36Z8XBftaKjg0{mh$R_)OQ!pa1-;Uo3_5ZfGFb33)?L zCC*o#$muvvZ`aFKFHb};dM(&xL#4iHa`?pG+Lzyaw<{7ctehaNTE)F-IaSn31X17x z6^A<+R1sD0qL3@$;EU_Q&0|F1xd;2-Yj50pjf^G($*2|-zz~VN`ughzM(oF(QnPrX z!@d7XB=YCK{COwm0l1Nf@#nH$dFx#hpdT~k`Fg`^Z&~awyzZLJYS084-g)=cx8Ln> za_O@ddD)Cm{J@h?a`K`cC1u*@b4&%_eaBRr&IHyUjcpZO{$wj{XWyC&F$y{Z$zfo$xS` z8gjqqs2)!6QK3858~m%vm3Vv(+^RfL7Ztfuow#?;0S^v$qu;d;^j3wB>NC7OCwxFN zq&geT`yXMvs~aD^iLuyvsyo)0O2pO&2I9S)V=e2kL8HNr&7=ledV6|eYg?m@r z=v<3N8+)Sh_P*3`W;a$EA6}1*4zf4}48$g)rkfL~m>uJ?U+UWUoJjP>do$^l#?Dl{aXi%=U28|K;}i3l*hJ@W zG&*g>C!&qxv1lefUCehh&g>lKqvd2%uH3aaS{mC(l}kgpaw*wUUMY2zOHKXdu8pZu zsXbmUP3G1|M>ccAjmgIGXscxuZRwr2{w0%%_1bk36N%h)@eyzA>1~Ow4aX;Xvdz)0 zM9ajo)rHXy?)K~1OieAfw;b#h|n9f-dis9jg^a~A#;0-hfI0pV6a?j$3I|v z*!%V=pV9R=EpXnL1 zaRx@B>nz zhRvTTC)-n{Z2N%KNv>R6G@jD!ryxcs zdVA8;!_f5JR-rhXE068;mGf!CISH*slgUumhWYyp^R&6`{6>s7_%!U}$d}36Mt3>i zo-*2dEPUL;EKXCm@jh6}4vqIT4~*D}wbrKI&W`KiBep)>-Q3&R-MsF2XtPTM2MS}8 z!{xDqPAh-7oE(}c<>S4jl~SynPg+=dYHv9`kY8-HJKLK^tWFX}UthVnGh#GbeYIyx zD;xbwBQ1-I3tfvQe>3H-{6IM$?=OuV3>UL~1Jj9-erqqWc;i6ky7-9q_9UApVneas z@$tr<&S*Y8xM}UxuuEE9G#SQC$kLe6XKf%oyuT7pbv8xYriP0fqw%)3-La;|V%FM1 zzRxh995lWI`e#p|tXG$iU8>0*M!A;tHV&uB`XpL_5 z#T!#oP3y7Vj>)w+_#5pe=S>-tacc)A|HU0}9y7Tgp4#2+m`%(!74xgBOYP~Q_Qu4( z^1{MSVXWPBRlLLW*l;PCo{o+8G_EfXtuMCEj-+M=HrEaYSIfn`;n9>hSQ#3y`e&~{?oWFuQF^@07M(LZhFnqEzt%xv`TWM(^hrc!%{#igNg zd33&<>loiH4tJym7uwsW5*>4UD?>Y(!P4R3!APuUKDxF%+Ey-4jqY|%we>d7v@h%z z_e=(pCZoxb?RC>#wD+E&mi5%t`^(;*k$CU;fbr2hu+_OxF6Adn$##>gCZoM%{8$@U zIWT?NH-XtzR?!G-IvL8Y;2QzMj#;u0AK<*3ONtp^@y)e$!@0@0Rg0GBrHdZKt0%3dyCx zCXq&6c|I6Vr3sJsp$FnWeTB>&Ke< z$6AW*>&wZ5;%f8c;PiHEanbA&tAkQ@bHw;DdRLc9$=!ugcGY<5Hh%0|8s%o=ZFp`f zmG7LIUnp7prGu5-f!@u`TyfqJ)^N`XVmJt-T1J6xGA~2 z+`B)rJz?L5nQfj;6-{TQM+Ta=mNz?R_sXlybGg>8#nnRJS~U&xiZ`{%7LW=!4;gSm-($I$XpdU4dAm&>KyrRl`Xem=dhX?32OTNuon4sO0G zA2hYx(7x+0Oplmu+Q}AHnp!*i#&b&t`T5-LO44kLq0DSsVyiR1YxL%}GjnZ)Y`@*} z-)e1QbG}q6+dT&zb1S3S<%!*iLS|=SshsS#`r0%M%JatGbSYn6DCc)g@0Qn=7PA9p zJ9d>iw-%4j}G|i1Pj+(x;kMs-;mAeki{%fC~Oig5(*9PK4Gt(=k zb8~Zv{kipy4bx|3a4nR&TMhr#*>bi#S;{Rf?_>(?(6cZ%xZmHjJiEKR)L1AlEtFQR z&6GBc-`%OwYP0FL?vaIs$>CA6@v&F(2Qy2wH_>xhmpn#iicO_bddB)$q6gtW~0q;vVLP|-0EREJJ*)XFOIG5cFwkTZA{PZj;(fY9qu+BCR>q}6^Hd|$LwKg zX{5B;Jypmyn=P<3YprUkn9XGlyUN2`owKX+>851&)LOZDZMkV?et&#(^q^%vu`m@K zH#@#J)_U1`P`cQ}G<|8tbVdhqF}&TgwXnavm>TSvA8pwxjl>g&{Zm^@_8o(cj*anD zcmIlE7wfdP8As1`G)-^x_wP6NOm`M~20C|o``326He>6JYXb@Nx&5pOM%(DSd-^kG zU(RgKB^D+dtt|Rp-nTYxUAg~gS=(z(G>+TcQ`GoL43azJzo_XjD<^8>(x}lKP4vzu zy81h_bNi)S*?Nt`T)tRY8Ha0ks8DE`h=}k{e&u0^D`-QIE@x$zH-k9pM zY+9_Jw=rQX(X>cX z({!RV;P|vR#%tL|00*hr#;L~fsL9WCkJUkM(s<*f;yNY;v_1)Jg83++8Rh=E{2m zvAyzaQ)17)Txs8z-8Efob+x){@plUg?M*q_fgAtz#fD>znI7gD5~gF!PPBQM#Fg!L zXKylB(woZJxZm6XXGb^p?6tM@W(KfH2X`9Bz}6VpuJEx{Ebp!(R%NS~Vm_CTu60IN zH%EFVn>x2wI+A&qrLM}|bLFj-?!oBVcvEaWHV}`lrCJ-K8Dy!s(Js_%O!dYXQ(v(k zWDd}95A6TS{GXL!brY^8Rz ztu*b&r$;6e*2io+RxDj1U&xz&Z8Ezym|vt!YcZ6qa<1$uZ=)Of9Z!VWkG2ROJ1a}p zuQ{5Fjvx1+{}sxGVY-#qX+h zQK8-8w4OP(oz3rfSnF&~&9<5S8v3JNtUgM)Ipp7Dr(E9d8trdcJM6MsYVB@vQv>Dx zLLiH@_qqM){bWCwkT3Mdd#6YIdUqIt<7I!fWXdqJ&-x`PcilP)MQxrkt$J`gRp{p3mHtd_pGZ%b)rB8U)w|~>;@h05 zF>L)qlg+PLoJ4cX{OE^hH0AzZ{a+)Q{t<+;)3LSoVJSlsH*Wn_Nw66CYy@Cf`@|9{Nt+c5HJr&#FjF@B6*ha1m^rI~xq zUBia0&_&zeN1DoCV^4~@LdOvp{H(rRqVY;P>iPQqVy0sQomwrD%pFZ&-Dbbm#-4=9 zk&~aO(TG48Pl;q>Pb|=}#z#{$WAUA=pc|;X4oi!ywm7-<^;rE_ zK8?|NbBveqPPb-wEvz8p4lkFd@epgadNBN>)?mjSW4YbIzRgVIfvpGFnn<6`BgAc9 z%GRJ(c5H5|#GH|>N3o7mVqGBXT>Lh7UoLI*9ojnKOrm#+xtYd5A6mVr-CYY8h6!VR zBX_)$$`0Cz@z&Oq=$c40PVIMQn~gT+t=(Fa4K@t-cB7j)yZETBof&Ve(ew@5`c%Kw z18WY$=GxkhtpycljW>H|7_2O==R5o6Swl55J(zpACN9XvsvH~1+HHVU%ScP-Txl$6 zYqRlWIh$r)E^FAcKFj)4wp3iSb-{efcH`|H_?E$(M*O?hn5@Xmt!sI9xQ)`{Qb ze`t97Fx|7h)YobAXts7WYwOO7ww`HeiU<8A)^(HVvE{`s``FpaRw+Aa{Kr}A1&@Jp zS7~%A)o3<+XS8uVnxxEY`fH^vxOQjlVr^-#R4VQmmVK-r4;$V#2c5NbR-?h@V-LFG zU0war{_f4?jZ8dtu)Ew+4A!BUe@|vyTUpsz?CP8DZ*GhY%#O57mGa4PTjT6@vQ}!J z+*n#TwEC~~Ie4z&&t$2o2OAxAAB!GzHQD-W6Y_2{WNq5k(@Mn+s|Rc2rPQcW#F(l*>C#++N_OqTQx2X45ViBh4!h5*2dM&rc~G5LgT{W zn5|LU8hc@7GSl2+Hoem^*T92i(KtR}TQSTto@oaot9vW!px@O+mi2L4D=!|H%%ejm z3SArHw)`?RQeN#ymAkw12c_1*rN!APTRK>p-WwZRFLW*M9QH-WhHUt1Yi;G^=={dv zRO6WOGrB#}WO!Ul09M3O&`-*PmIi_8hbe+N<>mrP3sNYKS_q z{V+{S={{SB8r>}Cr}}N}W7gJf?YU#4u(Fw6>xk#G@#3O&)Q$8Pd!06yT^`Msa^0f` z$>E{i&Ar{_gGSpQv6$NH>?&LRJEP$`7;&~7`f5BHT^^ZOWi8P3Xn$$N>Dlq(nDq_W zrk>s9_MSvzPkcY$F|wN}wAy?~-qxRt$AW!Bw0R*|&ta{j+vXXYZC$F6DRt+p-dg7u z)A7!&<;j(e!|Y*eVLc2QenB56ymbCY|$^bK8;!^O_Ej_iib=S)oRZ8U9Unr)7%d-|~4Z|l#6 zNm~ar8)SFBl*w9}9qD1)msJ?e?T&4&c64o6c?h}SGKbn$8F7HYd>Dj+I}O}{>^SGCfkR4nlrOA`?H4EVZr*3)Z)m(#LP%jm(e^_ zC^b**kFEAvo0ztBW^3mrN9B&imBXQ(xx_(NcCNTrNZR^yX>-7H)wx*XUT=D8As&kkG;ek$4{ZH&!rIP+ zwR_fa&Fx>dx|&#O%l9v}%~<{QO>B0omm0^f%7vx3b*Qo3-bULRX8l~;c(FZV)^C?e z@!_Sm-r4?v=;$$#_TKcw%Q|*k(bS=Zd8zTi>*` zbGPo_zht~wy_6RYlC7hKuF+H}pPSmw6k;38?JMgY$>oW;uKl+4`Kiq8d|`8RqFfkD zrdHY})|zd6X080n?IW;9uuTSqgI5FsAQ`+InGWXm)ToH8@_FPfg?& z6JxV`o$R;Yi>24p-Bv%gFtzTqr*A{$MHWxekdd6&B z$O=i=c+l)B!>cKZj-p(;5XMx`_|Mp}@nKW@7 z@x;WiHD{xr`D*(WZRup$_7d3~OJyFpI)7($`~GLl2GzoEt}SmiM!hOW- zRsE{^1~a?=TGv-H$)Et-+|898J7$f|;t&+*=5Agm^&8*BZ;+z;|Jo0~zWzuGb{h_@_2Cui?zI{q;x3NpRR($2mgk|(fe-Ixzy~R8&AYzr`Yte?v16DD z|KYySJ&&0e`&8BEVa9`MXyz-uc$Y5z0UP>-`WoC*I;GFL8y}nI<#;x4e(Ta(j`#C# z?~Oll1MI8If9c#Gx#e%U$v<-ZmS+9i7yYL{{&v&-mLLApAHStp|Mo>c(;wzcsq+kv zZC-wz!qDPDCofJ2@3&0_IR|FIne|1EgPf3IzHO%GY2Vm+5E)l5f7CIN|kqibh*a8B9 zLaE*zPe=B8UYKK_bq$_j_*2EYn>}a6fx-rYtpYo@!EEla^Rt>+%y!H4K9LJXv>)8ZYUa3U?#|cc*}})V?E*Ssn*|>cM{O;P z5c^{l8%oDE7!JG)Q1ZS3=QS}0Yd1k!Eq(VZf8 zD~o5^oj&0`IJe`>bvcgj7Z$$qA?%YeamK3R= z_-+RljUDzu@zbQ|V619e*X#3Ie7vmMw^xhit)i2ekvQ&_5w~{!#fJn>^il?6o;BPN z<1R3p1$zt;t_5$;YmQyZN-k6OT4Rs?&^+=HIi#R||1u{rKOPqSXYa==|o^pHn+gtg)^}RcU^~sajJd6_ObgKZfCz; zJ04%#bbp1tS)7*sW!3k_({(J_dp4X)FtoSQw4H_!R|@$ra1*6HGGX4MjfVXa>e z)(j4B-#geCZ<^dGQLnQd`Y-?f|6B`SjJD34@xe97xJ|Xe0`XG_F&5zG_#D+1ayaW$ zVN@ONg6{e;5I!S*6nMrJOknfu3sR|cO7`MXFKc)rh7$0;0~ z+-|WyT(b)ct30;!^c>t){4@s)fw2VM@hY94*^O`~Y$mw|Sk7v88)x7_g3Yf_`9Ya^ zp~$?v&lZn)VNsEnhg1BIi}7KDZ(cuu^$YvxfrEoPJ0`J?$B3`w~51Lqt5`OJMrjZ(ZnADV?{e=JL`EC z9#5yXzOU{FOzRW&kAg-uhnH&yx6P zAP1I@(c#&2(JNttJI^}^=NS8a11|E4>+gkY0seTeCh4n_qg%@Iyg`5W*x#F#alElks0 z=h}BKjlH)7E*NKh5a%&>?M*|W$}tNbH+)^%hX`0F^DG=&@j>9P!qH>={>;9(eqUfKLLTl2`4VL@rumN@w2oMTkK)sjfm}Jo$4R)Jz#PeJ>i*0-Xg>%-s zlVJGi+FB2PR`4H!sFu60#&Afh^6!bV|A6Og4Yu>b){Y*Jv*~F~T!pz+Oti17B3Ng5 z`&z%?n7(X$Ojzq*$hH`-9;vk&cGh5D_R7uS*rHc3s=DDWcGB+29>n2?Uga0JUlgPG z{Y9cZ2h1^W`H@$s0cibSO&u>KYXG1pE)zF;zRAoNhf988)m$v0Prx8>iKF5nbNh zae;RU(Wgkj^PHJ}{i8zNgARVTW)EHGnf;sIqh6|$&T!Iqv#;9*l8cl#7T)ye zJhl((GP>mkn_;~luI;YlL%32e@20(FbI$xFGS1}j=p5kvXRxnxU9K5+rfJ__n7^I2 zU`YJEhL<17V18_{>(F1Y35h@qA3jzeDLxN+x7_uo&B~_bfvHhT0}GhC8kyjNb+g-L zdsJ)2;M&R7&agRPuD-kqk)+z4W|4pPkk{I;(^!6qBFEwV$KQXZUHm=>1s(LucXwsK zrG9Dq_hg+M)K}E$K^yaL^Mda@z`o9FVP~(+d35jB15PB+y$1Qr;01T^1Mv;r!F3Kz zjoawq1a$VqW?|ZhH`up#+CSf4QQuHtDBokFHCYkXuL%vEaV$B8Fl z2|VF`0!)w#FVFLRB^4&l187y(#}D}IHF+-P>wS><1RreUb0>M|f7(g972*88JW8OS zlpyh-s5^F?H;+Mkc=d%D8|Xp?pUy-)((R;BYOER*0O`^*LX)Sg<6C9VD5<3 zhYofwS<4^mmxJAEhsyI&eI1hSyrQ!i3qNv`joaP8$@9e*e$_g=W(*j4{({qH*zazCtXKaV zxleYDv&2{Z-&pN0vH%|5FRMqpUA3n-?d7F+IkvQB-jWl<;yz0ihkv=3Fld9L=h3U} z2ll&vx%z+kL%hUC=dv<#ys>8U$Cq5H^Jeh?3p8`A280A$b^fkDS2bKfJ)23B7qq9p7eEZNzUl9&*>7k+_%7e$oce#i=Grf> zO-!Kow|@WgyZ(QXV%aF96X+wSM~RoU(C16fBCU~m*BkMT+MX+@1K48 zZ`Jj!N4mED)>GHvR7`Ir+n!jXO%W1IQv`x@UeeO<$~o(I-h|2seWpK6%8 zX)QDle{DBg=@;=56gD*&Vs9(h2x0t;pul+Uc>$7)d^rvLhy2n%A^q1shpDeze z#sqV&Hx+j7w~K!9cgw$;OzmtY!|!G^pQ)|<2m4~0)5sbRI_xh^AMmlyrHTZ%i5Q(n zUA10QH}UkScTn6kBlFiYsLuf?dPe0&1Vl~gxV|P+XwF#lq7)_6|OZDTs@-$gkw$Gzzs&M6Z^nt34 ze#y5o=txJ^6uLG6%04B>77m6ZJmuZY(j&9K29s2Qe=0qoKCN*!x|zGjbGwJHbhTmP zRf^-a2IG(|TO2C!)f5AAU2GDEs=33Bx)--A(jki9J{m*f$|kv7cncG%(Lg%v#SFiBMHfVgIy#9UJ&CE@;Q0#UGMj>Bc+8a zZWo~hv2{{Go$F1b(QdTg$K>$Oul}X|HVUZ&%ERq`vzTYGFA851-bDT6`)+L4P4m9m z-6CeExRGo4XcqRKj)g4`{+-^ZuZ&z?2%Biix@7vvW@Tyo*_r$B<^9~eOMj#8!iAVW zm?jkQZ z93JrQ9BctxS}`JBk62Xq8gZ98{@fMdY(CYV-3%C>|8_xlG;Do2ctL#8&Li8Y8*H*8 z+|MHJ9(bDS;H8SLy)Imr`~3QD5sxzlcMt@D*q5(WAGX8dq1Wm z{URMxoJ_c%gKLA>dJzpu;_4YWREHmy_uRoV<6<*E-LO|@!6$OGH)CKAXGqv_pD|#y z?yF`l8yc2+m)ors-QKUy-tCJgNm~IZ{JG=o z7M!WLmll|hjSnUb#)H<|V7fnqvj}(A>(I7iFtD+(TKeYR0~3!6A0NhV_5L&zgo9@6 zwDH|Czqm(_x91!^BPJX1zdxYmHZjW=z_GJJH46gap zmmELr3;kSNHJ{U7Jw?%1a5cLKUXHJVCv2_5n6TPj_H3Op{Xi*viahKGw)UEhoq8g^ zP`$Fs%GNl(p5PPoQ;)3uj52@hpShrH?(o}6#bM++Puke4!5*!S)u^=ZwP-p1QN7Ch z^K7}Cz*b%4L0o2ogW!kYg^G*;`2qBZZ<*evt2ZzYaDsRXSw@Uxhv(sb(LdU;##r&j z62WCOp1<}U>u?EtYR=~y{9$9Meu8+_7Ittix|`c;?DN>er^2FsJkHf4hO>*l()SbQ zO7Y0eng(B(IaRTDn+;*bm2&*LP~^;dIbi|z5%Cesep&?g%s(xSi(M<#lYL!suOH1PGJvIlZ*FqES1xXgS0`Lb*bUE)ACK@gwJ)pr zOuReZ2V;xPlPi2y&IRy6aKhn(3gCzE(=s&k)ciJr8-&k-yKho&7z0Tw6KXs2TaW&T z5%}!r9+n-(ZF_NU}vJx@C^7n~U`s^lQ%g4RJRG`-AIbK8lZ%J>CjTIXPRw=AAK zZ?U~*bD^gf#t-GS_BM*Sc`(@DdJ&oo;$T?kk@M(m@bMvb?JJ(=A#82vbxT!vk;nPW z8!@?I!0R`^ z*s{{L2d!W8mS=5R$T7TtNhvP-G@iW{L(j!=)nX1uK5v3eTO7Q2g*B&vEWP<`-)f&u zQT%_(_pGx*uYN2CqbpRe9Iwwc*q~x~xNF)uR3f%>2F(0n^_S&mHdNcpgUeB3o_uY( z=#XO6mbxB(49G-a-S~uwY}ilqJnfz9(GmVNjCC{K<8yogzz+yc$oOF1-sJnw#bnyx zI@RXg9xgvKJ~Ev3+8j8pVP||xK5S%>k58w`cu&>4XE(i>_s-YnJe~_jR;N`ia9xG1 zn-|8WPAt2Qu-FTa1CPi2xz4fwn1HRn*n$llIBnVevwE8}I_bh-7Ku6ACXpKN!T zPFKWWJ(@krPiHHw=M?#gCPUa?s;A6y-V9D^<>#_Z0CvSt$(Oe6Q@fc>?}v7-badmp z3>-n`7{*q%U!UZTiCey$zvU0lqhgFE2Z^z;LhU`Ud$B%&v25E3!VAw9DYrkmMZ4J9 zV}BvqF0}U3Mp{Bh)T*ZLkGl*Tr?1mE4L2VeobSHs=p~eQsco z{P_n8_7FuP?9@iLqa81RsR_fuBn{7tC$}?M6o;o+wIA81ipTZCMz_EWgb`w%-Wc24 z8!LF*@KkNy``mu_f7cGnMG9Q)7aT|Ufx!-Z?#*I;o=QiD^?OpWA%%s00dKDw0orw! zx1IFY*MC$F+U=Yj)W73dzWYOhy*5|s`y$?J+UYysPS?OQH{m_SQN4hHzFyOLs{h?u zZyW1Zzx+u#l&D4ZdE-!j!KU!3a=WFQZ0n~I=_>kxtn?89db}ggn%^yS<8T^b) z#uh6(^@r?N-wpNu{9?hr;$M70G+sqxLwq%G=Uw}f%LXI$V`)@ehslwXIHOf8pWTCr zOKQf*o0Ix)xA|jo&~9gYVmPU${`~iAe=wGryK1NEv6AS8w%2679^AXk1zmmH*DJj$ zkCH{^U}EWEL;dOtz5Y{jG^-=xFHkh5zsL43e``$B_6N5GKj9kOq(j6!IK1wgg^zRc zJN4VRF>ZY8)4Nappd3^|&F?=X&$~z_Q-sM5#1nknUva=ew({Tav($W*Iptk_^ZYg5 z|5Shc<=%hi4`V-Oo%8M6dZw6d;d_k#ovZ%&-~1!TpKtU3bjN@C<3F{|pa1Ni{`m84 z{-5sn$NEE{8pNh4kXy#;|=>*nLJ}d{~RB}ZX_O5m6&+soHE!>DB~{AHGFsj zt;#J(y@_cj+*!UfehkQ0XZZoYMAe(N(tqlMZJB!Od}$u~kBTScFA~6SJbPHI!!Fp_ z6Nh~;g&a0CFc{g1$kpU?)UX#3qto!Jgmv(lE56|weqKL0sAs!=Tj_?8sBA

-e!a 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 UK7Zw1jl*ekMO}WXtLW$dAG(TTm;e9( literal 0 HcmV?d00001 diff --git a/lab8/kernel/kernel8.img b/lab8/kernel/kernel8.img new file mode 100644 index 0000000000000000000000000000000000000000..a0d30074c1394dd14751b52f49127f40be6c0d63 GIT binary patch literal 61160 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