/* kernel_sec_debug.c * * Exception handling in kernel by SEC * * Copyright (c) 2010 Samsung Electronics * http://www.samsung.com/ * */ #ifdef CONFIG_SEC_DEBUG #include #include /* cacheflush*/ #include #include #include #include #include #include #include #ifndef CONFIG_S5PV310_RAFFAELLO #define CONFIG_S5PV310_RAFFAELLO #endif /* * Variable */ const char *gkernel_sec_build_info_date_time[] = { __DATE__, __TIME__ }; #define DEBUG_LEVEL_FILE_NAME "/mnt/.lfs/debug_level.inf" #define DEBUG_LEVEL_RD 0 #define DEBUG_LEVEL_WR 1 static int debuglevel; /* klaatu*/ /*sched_log_t gExcpTaskLog[SCHED_LOG_MAX];*/ unsigned int gExcpTaskLogIdx = 0; typedef enum { __SERIAL_SPEED, __LOAD_RAMDISK, __BOOT_DELAY, __LCD_LEVEL, __SWITCH_SEL, __PHONE_DEBUG_ON, __LCD_DIM_LEVEL, __MELODY_MODE, __REBOOT_MODE, __NATION_SEL, __SET_DEFAULT_PARAM, __PARAM_INT_11, __PARAM_INT_12, __PARAM_INT_13, __PARAM_INT_14, __VERSION, __CMDLINE, __PARAM_STR_2, __PARAM_STR_3, __PARAM_STR_4 } param_idx; char gkernel_sec_build_info[100]; unsigned int HWREV = 1; unsigned char kernel_sec_cause_str[KERNEL_SEC_DEBUG_CAUSE_STR_LEN]; /* * Function */ void __iomem *kernel_sec_viraddr_wdt_reset_reg; __used t_kernel_sec_arm_core_regsiters kernel_sec_core_reg_dump; __used t_kernel_sec_mmu_info kernel_sec_mmu_reg_dump; __used kernel_sec_upload_cause_type gkernel_sec_upload_cause; #if defined(CONFIG_S5PV310_RAFFAELLO) /* dpram*/ static volatile void __iomem *idpram_base; /* Base of internal DPRAM*/ static volatile void __iomem *onedram_base = NULL; /* Base of OneDRAM*/ static volatile unsigned int *onedram_sem; static volatile unsigned int *onedram_mailboxAB; /*received mail*/ static volatile unsigned int *onedram_mailboxBA; /*send mail*/ #else volatile void __iomem *dpram_base = 0; volatile unsigned int *onedram_sem; volatile unsigned int *onedram_mailboxAB; /*received mail*/ volatile unsigned int *onedram_mailboxBA; /*send mail*/ #endif unsigned int received_cp_ack = 0; extern void (*sec_set_param_value)(int idx, void *value); extern void (*sec_get_param_value)(int idx, void *value); #if defined(CONFIG_S5PV310_RAFFAELLO) /* dpram*/ /* * assigned 16K internal dpram buf for debugging */ #define DPRAM_BUF_SIZE 0x4000 struct _idpram_buf { unsigned int dpram_start_key1; unsigned int dpram_start_key2; unsigned char dpram_buf[DPRAM_BUF_SIZE]; unsigned int dpram_end_key; } g_cdma_dpram_buf = { .dpram_start_key1 = 'R', .dpram_start_key2 = 'A', .dpram_buf[0] = 'N', .dpram_buf[1] = 'O', .dpram_buf[2] = 'N', .dpram_buf[3] = 'E', .dpram_end_key = 'D' }; void kernel_sec_cdma_dpram_dump(void) { printk(KERN_EMERG "Backup CDMA dpram to RAM refore upload\n"); memcpy(g_cdma_dpram_buf.dpram_buf, (void *)idpram_base, DPRAM_BUF_SIZE); printk(KERN_EMERG "buf address (0x%x), dpram (0x%x)\n", \ (unsigned int)g_cdma_dpram_buf.dpram_buf, (unsigned int) idpram_base); } EXPORT_SYMBOL(kernel_sec_cdma_dpram_dump); #endif void kernel_sec_set_cp_upload(void) { unsigned int send_mail, wait_count; #if defined(CONFIG_S5PV310_RAFFAELLO) /* dpram*/ static volatile u16 *cp_dpram_mbx_BA; /*send mail box*/ static volatile u16 *cp_dpram_mbx_AB; /*receive mail box*/ u16 cp_irq_mask; *((unsigned short *)idpram_base) = 0x554C; cp_dpram_mbx_BA = (volatile u16 *)(idpram_base + 0x3FFC); cp_dpram_mbx_AB = (volatile u16 *)(idpram_base + 0x3FFE); cp_irq_mask = 0xCF; /*0x80|0x40|0x0F;*/ #ifdef CDMA_IPC_C210_IDPRAM iowrite16(cp_irq_mask, (void *)cp_dpram_mbx_BA); #else *cp_dpram_mbx_BA = cp_irq_mask; #endif printk(KERN_EMERG"[kernel_sec_dump_set_cp_upload]" \ "set cp upload mode, MailboxBA 0x%8x\n", cp_irq_mask); wait_count = 0; while (1) { cp_irq_mask = ioread16((void *)cp_dpram_mbx_AB); if (cp_irq_mask == 0xCF) { printk(KERN_EMERG" - Done. cp_irq_mask: 0x%04X\n", \ cp_irq_mask); break; } mdelay(10); if (++wait_count > 500) { printk(KERN_EMERG"- Fail to set CP uploadmode." \ "cp_irq_mask: 0x%04X\n", cp_irq_mask); break; } } printk(KERN_EMERG"modem_wait_count : %d\n", wait_count); #else send_mail = KERNEL_SEC_DUMP_AP_DEAD_INDICATOR; *onedram_sem = 0x0; *onedram_mailboxBA = send_mail; printk(KERN_EMERG"[kernel_sec_dump_set_cp_upload]" \ "set cp upload mode, MailboxBA 0x%8x\n", send_mail); wait_count = 0; received_cp_ack = 0; while (1) { if (received_cp_ack == 1) { printk(KERN_EMERG" - Done.\n"); break; } mdelay(10); if (++wait_count > 500) { printk(KERN_EMERG" - Fail to set CP uploadmode.\n"); break; } } printk(KERN_EMERG"modem_wait_count : %d\n", wait_count); #endif #if defined(CONFIG_S5PV310_RAFFAELLO) /* dpram*/ /* * QSC6085 marking the QSC upload mode */ *((unsigned int *)idpram_base) = 0xdeaddead; printk(KERN_EMERG"QSC upload magic key write\n"); kernel_sec_cdma_dpram_dump(); #endif } EXPORT_SYMBOL(kernel_sec_set_cp_upload); void kernel_sec_set_cp_ack(void) /*is set by dpram - dpram_irq_handler*/ { received_cp_ack = 1; } EXPORT_SYMBOL(kernel_sec_set_cp_ack); void kernel_sec_set_upload_magic_number(void) { int *magic_virt_addr = (int *) LOKE_BOOT_USB_DWNLD_V_ADDR; if ((KERNEL_SEC_DEBUG_LEVEL_MID == kernel_sec_get_debug_level()) || (KERNEL_SEC_DEBUG_LEVEL_HIGH == kernel_sec_get_debug_level())) { *magic_virt_addr = LOKE_BOOT_USB_DWNLDMAGIC_NO; /* SET*/ printk(KERN_EMERG"KERNEL:magic_number=0x%x" \ "SET_UPLOAD_MAGIC_NUMBER\n", *magic_virt_addr); } else { *magic_virt_addr = 0; printk(KERN_EMERG"KERNEL:" \ "magic_number=0x%x DEBUG LEVEL low!!\n", \ *magic_virt_addr); } } EXPORT_SYMBOL(kernel_sec_set_upload_magic_number); void kernel_sec_get_debug_level_from_boot(void) { unsigned int temp; temp = __raw_readl(S5P_INFORM6); temp &= KERNEL_SEC_DEBUG_LEVEL_MASK; temp = temp >> KERNEL_SEC_DEBUG_LEVEL_BIT; if (temp == 0x0) /*low*/ debuglevel = KERNEL_SEC_DEBUG_LEVEL_LOW; else if (temp == 0x1) /*mid*/ debuglevel = KERNEL_SEC_DEBUG_LEVEL_MID; else if (temp == 0x2) /*high*/ debuglevel = KERNEL_SEC_DEBUG_LEVEL_HIGH; else { printk(KERN_EMERG"KERNEL:kernel_sec_get_debug_level_from_boot" \ "(reg value is incorrect.)\n"); /*debuglevel = KERNEL_SEC_DEBUG_LEVEL_LOW;*/ debuglevel = KERNEL_SEC_DEBUG_LEVEL_MID; } printk(KERN_EMERG"KERNEL:" \ "kernel_sec_get_debug_level_from_boot=0x%x\n", debuglevel); } void kernel_sec_clear_upload_magic_number(void) { int *magic_virt_addr = (int *) LOKE_BOOT_USB_DWNLD_V_ADDR; *magic_virt_addr = 0; /* CLEAR*/ printk(KERN_EMERG"KERNEL:magic_number=%x " \ "CLEAR_UPLOAD_MAGIC_NUMBER\n", *magic_virt_addr); } EXPORT_SYMBOL(kernel_sec_clear_upload_magic_number); void kernel_sec_map_wdog_reg(void) { /* Virtual Mapping of Watchdog register */ kernel_sec_viraddr_wdt_reset_reg = ioremap_nocache(S3C_PA_WDT, 0x400); if (kernel_sec_viraddr_wdt_reset_reg == NULL) { printk(KERN_EMERG"Failed to ioremap()" \ "region in forced upload keystring\n"); } } EXPORT_SYMBOL(kernel_sec_map_wdog_reg); void kernel_sec_set_upload_cause(kernel_sec_upload_cause_type uploadType) { unsigned int temp; gkernel_sec_upload_cause = uploadType; temp = __raw_readl(S5P_INFORM6); /*KERNEL_SEC_UPLOAD_CAUSE_MASK 0x000000FF*/ temp |= uploadType; __raw_writel(temp , S5P_INFORM6); printk(KERN_EMERG"(kernel_sec_set_upload_cause)" \ ": upload_cause set %x\n", uploadType); } EXPORT_SYMBOL(kernel_sec_set_upload_cause); void kernel_sec_set_cause_strptr(unsigned char *str_ptr, int size) { unsigned int temp; memset((void *)kernel_sec_cause_str, 0, sizeof(kernel_sec_cause_str)); memcpy(kernel_sec_cause_str, str_ptr, size); temp = virt_to_phys(kernel_sec_cause_str); /*loke read this ptr, display_aries_upload_image*/ __raw_writel(temp, LOKE_BOOT_USB_DWNLD_V_ADDR+4); } EXPORT_SYMBOL(kernel_sec_set_cause_strptr); void kernel_sec_set_autotest(void) { unsigned int temp; temp = __raw_readl(S5P_INFORM6); temp |= 1<f_op->read(filp, (char __user *)&debuglevel, sizeof(int), &filp->f_pos); else ret = filp->f_op->write(filp, (char __user *)&debuglevel, sizeof(int), &filp->f_pos); set_fs(fs); filp_close(filp, NULL); return ret; } bool kernel_sec_set_debug_level(int level) { int ret; if ((level == KERNEL_SEC_DEBUG_LEVEL_LOW) || (level == KERNEL_SEC_DEBUG_LEVEL_MID) || (level == KERNEL_SEC_DEBUG_LEVEL_HIGH)) { debuglevel = level; /* write to param.lfs */ ret = kernel_sec_lfs_debug_level_op(DEBUG_LEVEL_WR, \ O_RDWR|O_SYNC); if (ret == sizeof(debuglevel)) pr_info("%s: debuglevel.inf" \ "write successfully.\n", \ __func__); /* write to regiter (magic code) */ kernel_sec_set_upload_magic_number(); printk(KERN_NOTICE \ "(kernel_sec_set_debug_level)" \ "The debug value is 0x%x !!\n", level); return 1; } else { printk(KERN_NOTICE "(kernel_sec_set_debug_level)" \ "The debug value is" \ "invalid(0x%x)!! Set default level(LOW)\n", level); debuglevel = KERNEL_SEC_DEBUG_LEVEL_LOW; return 0; } } EXPORT_SYMBOL(kernel_sec_set_debug_level); int kernel_sec_get_debug_level_from_param() { int ret; /* read from param.lfs*/ ret = kernel_sec_lfs_debug_level_op(DEBUG_LEVEL_RD, O_RDONLY); if (ret == sizeof(debuglevel)) pr_info("%s: debuglevel.inf read successfully.\n", __func__); if ((debuglevel == KERNEL_SEC_DEBUG_LEVEL_LOW) || (debuglevel == KERNEL_SEC_DEBUG_LEVEL_MID) || (debuglevel == KERNEL_SEC_DEBUG_LEVEL_HIGH)) { /* return debug level */ printk(KERN_NOTICE "(kernel_sec_get_debug_level_from_param)" \ "kernel debug level is 0x%x !!\n", debuglevel); return debuglevel; } else { /*In case of invalid debug level, default (debug level low)*/ printk(KERN_NOTICE "(kernel_sec_get_debug_level_from_param)" \ "The debug value is invalid(0x%x)!!" \ "Set default level(LOW)\n", debuglevel); /*debuglevel = KERNEL_SEC_DEBUG_LEVEL_LOW;*/ debuglevel = KERNEL_SEC_DEBUG_LEVEL_MID; } return debuglevel; } EXPORT_SYMBOL(kernel_sec_get_debug_level_from_param); int kernel_sec_get_debug_level() { return debuglevel; } EXPORT_SYMBOL(kernel_sec_get_debug_level); int kernel_sec_check_debug_level_high(void) { if (KERNEL_SEC_DEBUG_LEVEL_HIGH == kernel_sec_get_debug_level()) return 1; return 0; } EXPORT_SYMBOL(kernel_sec_check_debug_level_high); #endif /* CONFIG_KERNEL_DEBUG_SEC*/