MINIDUMP_TYPE详解

MINIDUMP_TYPE详解
本文详细介绍了MINIDUMP_TYPE枚举类型,解释了如何通过不同的枚举值定制minidump文件的内容,以便在Windows程序崩溃时更有效地进行调试。文中还提到了不同选项对minidump文件大小的影响。

MINIDUMP_TYPE 枚举类型详解

一、MINIDUMP_TYPE 的作用

相信大家都知道我们可以使用minidump文件来记录Windows程序崩溃时的信息,其是一种内存转储,其第一代原型是一种“全用户转储(Full User Dump)”,里面包含了全部的进程内存信息。显然在大多数情况下我们都没必要获取全部的内存信息,而且存储全部内存信息的代价就是超大的磁盘占用,常常会有几百M甚至几个G,这使得要将dump文件反馈给开发人员就十分不方便。
于是在WindowsXP中微软制定了新的转储机制,这就是Minidump,默认情况下MiniDump包含了可以恢复程序崩溃现场的必要信息,并可以查看崩溃现场的局部变量值,此时的dump文件一般只有几十KB到几M,名副其实确实非常mini。
但是minidump的mini是通过删除过多的内存信息来达到的,而有些时候,我们想要的信息并不在默认的minidump转储范围内,这时候我们就需要自定义minidump所存储的信息了。
微软定义了MINIDUMP_TYPE枚举值,使得我们可以定制minidump文件转储的内容,当然随着内容的增加,mindump文件的大小也会增加,所以我们有必要知道哪些是我们需要的,哪些是于我们无用的。

二、MINIDUMP_TYPE详解

MINIDUMP_TYPE的定义如下:

typedef enum _MINIDUMP_TYPE {
  MiniDumpNormal                          = 0x00000000,
  MiniDumpWithDataSegs                    = 0x00000001,
  MiniDumpWithFullMemory                  = 0x00000002,
  MiniDumpWithHandleData                  = 0x00000004,
  MiniDumpFilterMemory                    = 0x00000008,
  MiniDumpScanMemory                      = 0x00000010,
  MiniDumpWithUnloadedModules             = 0x00000020,
  MiniDumpWithIndirectlyReferencedMemory  = 0x00000040,
  MiniDumpFilterModulePaths               = 0x00000080,
  MiniDumpWithProcessThreadData           = 0x00000100,
  MiniDumpWithPrivateReadWriteMemory      = 0x00000200,
  MiniDumpWithoutOptionalData             = 0x00000400,
  MiniDumpWithFullMemoryInfo              = 0x00000800,
  MiniDumpWithThreadInfo                  = 0x00001000,
  MiniDumpWithCodeSegs                    = 0x00002000,
  MiniDumpWithoutAuxiliaryState           = 0x00004000,
  MiniDumpWithFullAuxiliaryState          = 0x00008000,
  MiniDumpWithPrivateWriteCopyMemory      = 0x00010000,
  MiniDumpIgnoreInaccessibleMemory        = 0x00020000,
  MiniDumpWithTokenInformation            = 0x00040000,
  MiniDumpWithModuleHeaders               = 0x00080000,
  MiniDumpFilterTriage                    = 0x00100000,
  MiniDumpValidTypeFlags                  = 0x001fffff
} MINIDUMP_TYPE;
  • MiniDumpNormal
    仅包含捕获进程中所有线程的堆栈跟踪的必要信息。其值是0,也就是无论MINIDUMP_TYPE取何值,该选项都会包含其中。

  • MiniDumpWithDataSegs
    包含来自所有加载模块中的可写数据段,此选项会使minidump文件显著增大,对每个模块的控制使用了MODULE_WRITE_FLAGS枚举类型的ModuleWriteDataSeg枚举值。
    如果我们希望查看全局变来那个值,但有不想使用MiniDumpWithFullMemory,可以使用此选项。

  • MiniDumpWithFullMemory
    包含进程中所有可以访问的内存信息,原始内存信息包含在文件的末端,所以不用原始内存信息可以直接映射数据结构。但是该选项会造成minidump文件非常巨大。
    使用该选项可以查看存储在栈上、堆上、模块数据段的所有数据。甚至还可以看到线程和进程环境块(Process Environment Block和Thread Environment Bolck, PEB和TEB)的数据。这些没有公开的数据结构可以给我们的调试提供无价的帮助。

  • MiniDumpWithHandleData
    包含生成dump文件时活跃的系统句柄的高级别信息。
    使用该选项minidump会包括故障时刻进程故障表里面的所有句柄。可以用WinDbg的!handle来显示这些信息。

  • MiniDumpFilterMemory
    栈内存的内容会在保存到minidump前被过滤,除了重建栈跟踪所必须的指针,其他都会被用0数据覆盖。即调用栈可以被重建,但是所有局部变量和函数参数的值都是0。
    此选项只影响线程栈占用内存的内容。其他内存(比如堆)不受影响。如果使用了MiniDumpWithFullMemory,这个标志就不起作用了。

  • MiniDumpScanMemory
    栈内存的内容是经过扫描的,保留栈中引用了的模块。如果一个模块被栈引用,MINIDUMP_CALLBACK_OUTPUT结构体中存储的ModuleWriteFlags将被设置为ModuleReferencedByMemory。
    此选项可以帮助我们节约minidump占用的空间。它会把调试不需要的可执行模块去掉。但是需要和MiniDumpCallback函数紧密合作。

  • MiniDumpWithUnloadedModules
    包含最近被卸载的模块的由操作系统维护的信息。
    winServer2003 SP1和WinXP SP2之后,操作系统才会维护最近卸载模块信息。
    该选项要求DbgHelp 5.1以上版本。

  • MiniDumpWithIndirectlyReferencedMemory
    包含本地或其他栈引用数据的内存页,此选项会显著增大minidump文件大小。
    MiniDumpWriteDump检查线程栈内存中的每一个指针。这些指针可能指向线程地址空间的其他可读内存页。一旦发现这样的指针,程序会读取指针附近1024字节的内容存到minidump中(指针前的256字节和指针后的768字节)。
    该选项要求DbgHelp 5.1以上版本。

  • MiniDumpFilterModulePaths
    过滤内存信息中的模块路径,只保留模块名称。此选项可以保护用户的隐私比如用户名、重要的目录等,但可能阻止系统定位图像文件,应当谨慎应用在特殊环境。
    该选项要求DbgHelp 5.1以上版本。

  • MiniDumpWithProcessThreadData
    包含操作系统中每个进程的每个线程的完整信息。
    此选项使minidump会包含线程和进程环境块内容(PEB和TEB)的内存页,可以通过WinDbg的!peb和!teb命令来查看。同时,也包括了另外一些它们也用的内存页(例如,环境变量和进程参数保存的位置,通过TlsAlloc分配的TLS空间)。不过,有一些PEB和TEB引用的内存被忽略了,例如,通过__declspec(thread)分配的线程TLS数据。如果确实需要,就不得不使用MiniDumpWithFullMemory或者MiniDumpWithPrivateReadWriteMemory来获得。
    该选项要求DbgHelp 5.1以上版本。

  • MiniDumpWithPrivateReadWriteMemory
    扫描虚拟地址空间,将可读写的私有内存页(PAGE_READWRITE)包含到minidump文件中,这使我们可以察看栈、堆甚至TLS的数据。PEB和TEB也包括在里面。
    注意此选项并不包含共享内存页内容、可执行模块代码、数据段等,不包括代码段节省了minidump文件大小,但我们不能查看内存映射文件内容,及全局变量。所以该选项常与其他选项组合使用。
    该选项要求DbgHelp 5.1以上版本。

  • MiniDumpWithoutOptionalData
    去掉minidump转储文件中不在“基准转储内存区域”中的数据,这样可以尽量避免dump文件中出现用户的隐私数据,但是并不能完全避免。
    应用此选项,只有MiniDumpNormal指定的内存会被保存,其他内存相关的设置(MiniDumpWithFullMemory, MiniDumpWithPrivateReadWriteMemory, MiniDumpWithIndirectlyReferencedMemory)即使指定也会失效。
    该选项不会影响:MiniDumpWithProcessThreadData, MiniDumpWithThreadInfo, MiniDumpWithHandleData, MiniDumpWithDataSegs, MiniDumpWithCodeSegs, MiniDumpWithFullMemoryInfo的行为。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithFullMemoryInfo
    包含整个内存区域的信息,该选项会使minidump包含进程虚拟内存不举的完整信息。
    可以通过WinDbg的!vadump和!vprot命令查看。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithThreadInfo
    包含线程的状态信息。对每个线程都会提供线程时间(创建时间,执行用户代码和内核代码的时间)、入口地址、相关性。
    WinDbg中,可以通过.ttime命令查看线程时间。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithCodeSegs
    包含加载的可执行模块的代码段和代码相关部分,以捕捉可执行内容。对于每个模块的控制使用MODULE_WRITE_FLAGS枚举类型的ModuleWriteCodeSegs 枚举值。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithoutAuxiliaryState
    关闭二级附加内存内容收集。

  • MiniDumpWithFullAuxiliaryState
    将附加数据内容提供者的状态信息存入minidump文件,该选项会增大minidump文件大小。

  • MiniDumpWithPrivateWriteCopyMemory
    扫描虚拟地址空间,将写入页面的副本(PAGE_WRITECOPY)的内存包含进dump文件。
    该选项要求DbgHelp 6.1以上版本。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpIgnoreInaccessibleMemory
    忽略无法访问的内存。例如当指定了MiniDumpWithFullMemory,如果生成dump的方法无法读取某些内存区域,minidump生成会就失败。但是如果你指定了该选项,dump生成方法就会忽略不可访问的内存区域,并继续生成minidump。需要注意的是不可访问的内存区域不包含在dump文件中。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithTokenInformation
    添加安全标记相关的数据。该选项使!token扩展在处理用户模式( user-mode)的模块时生效。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpWithModuleHeaders
    添加模块头相关数据。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpFilterTriage
    添加过滤分类的相关数据。
    该选项要求DbgHelp 6.1以上版本。

  • MiniDumpValidTypeFlags
    表示每个标记都是有效的。

参考:
1.微软官方说明
2.DoubleLi的博客文章《minidump详细介绍》

/* # Copyright 2022 Unisoc (Shanghai) Technologies Co., Ltd. # Licensed under the Unisoc General Software License, version 1.0 (the License); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # https://www.unisoc.com/en_us/license/UNISOC_GENERAL_LICENSE_V1.0-EN_US # Software distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OF ANY KIND, either express or implied. # See the Unisoc General Software License, version 1.0 for more details. */ #include <app.h> #include <asm/arch/check_reboot.h> #include <boot_mode.h> #include <lk/debug.h> #include <stdlib.h> #include "boot_mode.h" #include "boot_parse.h" #include <logo_bin.h> #include <lib/console.h> #include <string.h> #include "fastboot.h" #include <sprd_common.h> #include <sprd_sysdump.h> #include <dl_common.h> #include <sprd_wdt.h> #include <asm/types.h> #include <sprd_regulator.h> #include "calibration_detect.h" #include <sprd_battery.h> #include <sprd_keys.h> #include <sprd_common_rw.h> #include <miscdata_def.h> #include <sprd_ddr_debug.h> #include <linux/kernel.h> #include <gpio_plus.h> #include <sprd_adc.h> #ifdef CONFIG_ANDROID_AB #include <android_ab.h> #include <chipram_env.h> #include <sprd_pmic_misc.h> char g_env_slot[3] = {"_a"}; #endif #ifdef CONFIG_DOWNLOAD_FOR_CUSTOMER extern int pctool_connected(void); #endif #ifdef CONFIG_TEECFG #include <teecfg_parse.h> #endif #ifdef SPRD_MINI_SYSDUMP extern void handle_minidump_before_boot(int rst_mode); #endif #ifdef CONFIG_USB_SPRD_DWC31_PHY extern void usb_phy_enable(u32 is_on); extern int usb_phy_enabled(void); #endif #define NTC_VOL_CH 0 #define NTC_VOL_SCALE 0 #define NTC_VOL_MUX 0 #define NTC_VOL_CAL_TYPE 0 extern int read_boot_flag(void); extern CBOOT_FUNC s_boot_func_array[CHECK_BOOTMODE_FUN_NUM]; extern void board_boot_mode_regist(CBOOT_MODE_ENTRY *array); extern const char *bootcause_cmdline; extern int sprdbat_get_shutdown_charge_flag(void); extern int sprdbat_get_auto_poweron_flag(void); extern int is_hw_smpl_enable(void); static unsigned int get_gpio_status(unsigned int GPIO_NUM); #ifdef PROJECT_24717 #define BOARD_ID1 147 #define BOARD_ID2 113 #define BOARD_ID3 112 #define Modem_ID_0 173 #define Modem_ID_1 130 #define Modem_ID_2 131 #endif #ifdef PROJECT_23728 #define BOARD_ID1 147 #define BOARD_ID2 113 #define BOARD_ID3 80 #define Modem_ID_0 173 #define Modem_ID_1 130 #define Modem_ID_2 131 #endif extern void dl_set_wdtflag(void); extern unsigned ota_processing; #define USBPHY_VDDUSB33_NORMAL 3300 #define USBPHY_VDDUSB33_FULLSPEED_TUNE 2700 #define LOWPOWER_LOGO_VOL 3000 #define LOWPOWER_LOGO_ENABLE_TIME 15 #define LOWPOWER_LOGO_DISABLE_TIME 0 #define CONF_0 171 #define CONF_1 172 #ifdef VENDOR_EDIT extern cdt_t cdt_table; #endif static const char *g_mode_str[CMD_MAX_MODE+1] = { "UNDEFINED_MODE", "POWER_DOWN_DEVICE", "NORMAL_MODE", "DOWNLOAD_MODE", "RECOVERY_MODE", "FASTBOOT_MODE", "ALARM_MODE", "CHARGE_MODE", "ENGTEST_MODE", "WATCHDOG_REBOOT", "AP_WATCHDOG_REBOOT", "SPECIAL_MODE", "UNKNOW_REBOOT_MODE", "PANIC_REBOOT", "VMM_PANIC_MODE", "TOS_PANIC_MODE", "EXT_RSTN_REBOOT_MODE", "CALIBRATION_MODE", "USB_MUX_MODE", "AUTODLOADER_REBOOT", "AUTOTEST_MODE", "IQ_REBOOT_MODE", "SLEEP_MODE", "SPRDISK_MODE", "APKMMI_MODE", "UPT_MODE", "APKMMI_AUTO_MODE", "ABNORMAL_REBOOT_MODE", "SILENT_MODE", "BOOTLOADER_PANIC_MODE", "SML_PANIC_MODE", "MAX_MODE", }; #ifdef VENDOR_EDIT uint32_t supported_ProcNo[] = { 24660, 24661, 24662, 24663, 24664, 24665, 24666, 24667, 24668, 24674, 24717, 24725, 24726, 24729, 24730, 24731, 24734, 24735, 24736, 24737, 24741, 22716, 22717, 22718, 22720, 22721, 22722, 22723, 22724, 22726, 22729, 22734, 23665, 23666, 23711, 23712, 23713, 23633, 23728, 23714, 24760, 24768, 24761, 24762, 24763, 24764, 24758, 24767, 24759, 24765, 24766, 25702, 25703 }; int check_project_is_supported(void) { int i = 0; for (; i < ARRAY_SIZE(supported_ProcNo); i++) { if (supported_ProcNo[i] == cdt_table.project_no) { debugf("The project number:%x is supported\n", cdt_table.project_no); return 0; } } errorf("The project number:%x is not supported\n", cdt_table.project_no); return -1; } int cdt_table_analysis(void) { #ifdef PROJECT_24717 unsigned int board_id1, board_id2, board_id3; unsigned int modem_id_0,modem_id_1,modem_id_2; #endif #ifdef PROJECT_23728 unsigned int board_id1, board_id2, board_id3; unsigned int modem_id_0, modem_id_1, modem_id_2; #endif memset(&cdt_table, 0, sizeof(cdt_table)); errorf("read partition cdt start\n"); if (0 != common_raw_read("ocdt_a", sizeof(cdt_table), 0, &cdt_table)) { errorf("read partition cdt failed\n"); return -1; } if (CDT_MAGIC != cdt_table.cdt_magic) { errorf("cdt_table magic didn't correct\n"); return -1; } if (-1 == check_project_is_supported()) { debugf("power down device\n"); write_log(); power_down_devices(0); } #ifdef PROJECT_24717 board_id1 = get_gpio_status(BOARD_ID1); board_id2 = get_gpio_status(BOARD_ID2); board_id3 = get_gpio_status(BOARD_ID3); modem_id_0 = get_gpio_status(Modem_ID_0); modem_id_1 = get_gpio_status(Modem_ID_1); modem_id_2 = get_gpio_status(Modem_ID_2); debugf("cdt_table board id1,id2,id3 ,modem id0,id1,id2=(%d,%d,%d,%d,%d,%d)\n", board_id1, board_id2, board_id3, modem_id_0, modem_id_1, modem_id_2); if ((1==board_id1) && (1==board_id2) && (0==board_id3) && (((0==modem_id_0) && (0==modem_id_1) && (1==modem_id_2)) || ((0==modem_id_0) && (1==modem_id_1) && (1==modem_id_2)))) { cdt_table.project_no = 24717; cdt_table.dtsi_no = 24717; cdt_table.audioIdx = 24717; }else if((1==board_id1) && (1==board_id2) && (0==board_id3) && (((1==modem_id_0) && (0==modem_id_1) && (0==modem_id_2)) || ((1==modem_id_0) && (0==modem_id_1) && (1==modem_id_2)))){ cdt_table.project_no = 24730; cdt_table.dtsi_no = 24730; cdt_table.audioIdx = 24730; } #endif #ifdef PROJECT_23728 board_id1 = get_gpio_status(BOARD_ID1); board_id2 = get_gpio_status(BOARD_ID2); board_id3 = get_gpio_status(BOARD_ID3); modem_id_0 = get_gpio_status(Modem_ID_0); modem_id_1 = get_gpio_status(Modem_ID_1); modem_id_2 = get_gpio_status(Modem_ID_2); debugf("cdt_table board id1,id2,id3 modem id0,id1,id2=(%d,%d,%d,%d,%d,%d)\n", board_id1, board_id2, board_id3, modem_id_0, modem_id_1, modem_id_2); if ((1 == board_id1) && (1 == board_id2) && (0 == board_id3) && (0 == modem_id_0) && (0 == modem_id_1) && (1 == modem_id_2)) { cdt_table.project_no = 23728; cdt_table.dtsi_no = 23728; cdt_table.audioIdx = 23728; } else if ((1 == board_id1) && (1 == board_id2) && (0 == board_id3) && (0 == modem_id_0) && (1 == modem_id_1) && (0 == modem_id_2)) { cdt_table.project_no = 23714; cdt_table.dtsi_no = 23714; cdt_table.audioIdx = 23714; } #endif return 0; } #endif CBOOT_FUNC s_boot_func_array[CHECK_BOOTMODE_FUN_NUM] = { /* 0 get mode from vol+/vol- autodloader*/ get_mode_to_autodloader, /* 1 get mode from chipram_env*/ get_mode_from_chipram_env, /* 2 get mode from bat low*/ get_mode_from_bat_low, /* 3 get mode from sysdump*/ write_sysdump_before_boot_extend, /* 4 get mode from miscdata flag*/ get_mode_from_miscdata_boot_flag, /* 5 get mode from file*/ get_mode_from_file_extend, /* 6 get mode from watch dog*/ get_mode_from_watchdog, /* 7 get mode from alarm register*/ get_mode_from_alarm_register, /* 8 get mode from calibration detect*/ get_mode_from_pctool, /* 9 get mode from smpl*/ get_mode_from_smpl, /* 10 get mode from bbat,cali*/ get_mode_from_gpio_bbat_cali, /* 11 get mode from charger*/ get_mode_from_charger, /* 12 get mode from keypad*/ get_mode_from_keypad, /* 13 get mode from gpio*/ get_mode_from_gpio_extend, 0 }; void board_boot_mode_regist(CBOOT_MODE_ENTRY *array) { MODE_REGIST(CMD_NORMAL_MODE, normal_mode); MODE_REGIST(CMD_DOWNLOAD_MODE, download_mode); MODE_REGIST(CMD_RECOVERY_MODE, recovery_mode); MODE_REGIST(CMD_FASTBOOT_MODE, fastboot_mode); MODE_REGIST(CMD_WATCHDOG_REBOOT, watchdog_mode); MODE_REGIST(CMD_AP_WATCHDOG_REBOOT, ap_watchdog_mode); MODE_REGIST(CMD_UNKNOW_REBOOT_MODE, unknow_reboot_mode); MODE_REGIST(CMD_PANIC_REBOOT, panic_reboot_mode); MODE_REGIST(CMD_AUTODLOADER_REBOOT, autodloader_mode); MODE_REGIST(CMD_SPECIAL_MODE, special_mode); MODE_REGIST(CMD_CHARGE_MODE, charge_mode); MODE_REGIST(CMD_ENGTEST_MODE,engtest_mode); MODE_REGIST(CMD_CALIBRATION_MODE, calibration_mode); MODE_REGIST(CMD_EXT_RSTN_REBOOT_MODE, normal_mode); MODE_REGIST(CMD_IQ_REBOOT_MODE, iq_mode); MODE_REGIST(CMD_ALARM_MODE, alarm_mode); MODE_REGIST(CMD_SPRDISK_MODE, sprdisk_mode); MODE_REGIST(CMD_AUTOTEST_MODE, autotest_mode); MODE_REGIST(CMD_APKMMI_MODE, apkmmi_mode); MODE_REGIST(CMD_UPT_MODE, upt_mode); MODE_REGIST(CMD_APKMMI_AUTO_MODE, apkmmi_auto_mode); MODE_REGIST(CMD_ABNORMAL_REBOOT_MODE, abnormal_reboot_mode); MODE_REGIST(CMD_SILENT_MODE, silent_mode); MODE_REGIST(CMD_BOOTLOADER_PANIC_MODE, bootloader_panic_reboot_mode); MODE_REGIST(CMD_SML_PANIC_MODE, sml_panic_reboot_mode); return ; } boot_mode_enum_type get_mode_from_arg(char* mode_name) { dprintf(INFO,"cboot:get mode from argument:%s\n",mode_name); if(!strcmp(mode_name,"normal")) return CMD_NORMAL_MODE; if(!strcmp(mode_name,"recovery")) return CMD_RECOVERY_MODE; if(!strcmp(mode_name,"fastboot")) return CMD_FASTBOOT_MODE; if(!strcmp(mode_name,"charge")) return CMD_CHARGE_MODE; if(!strcmp(mode_name,"sprdisk")) return CMD_SPRDISK_MODE; /*just for debug*/ #ifdef SPRD_SYSDUMP if(!strcmp(mode_name,"sysdump")) write_sysdump_before_boot(CMD_UNKNOW_REBOOT_MODE); #endif return CMD_UNDEFINED_MODE; } int is_abnormal_temp(void) { int32_t ntc_vol; #ifdef CONFIG_NTC_VOL ntc_vol = sprd_chan_adc_to_vol(NTC_VOL_CH, NTC_VOL_SCALE, NTC_VOL_MUX, NTC_VOL_CAL_TYPE); debugf("is_abnormal_temp: ntc_vol = %d\n", ntc_vol); if (ntc_vol >= 0 && ntc_vol < 227) { debugf("is_abnormal_temp: temperature over 65 degrees\n"); return 1; } else if (ntc_vol > 620) { debugf("is_abnormal_temp: temperature below 0 degrees\n"); return 1; } else return 0; #else return 0; #endif } unsigned reboot_mode_check(void) { static unsigned rst_mode = 0; static unsigned check_times = 0; if(!check_times) { rst_mode = check_reboot_mode(); check_times++; } dprintf(INFO,"reboot_mode_check rst_mode=0x%x\n",rst_mode); return rst_mode; } void low_power_charge(int temp_status, enum sprd_adapter_type usb_type) { int32_t vbat_vol; vbat_vol = sprdfgu_read_vbat_vol(); #ifdef CONFIG_BATTERY_TEMP if(temp_status == DISBOOTING_TEMP) { } else { #endif if((usb_type != ADP_TYPE_SDP && usb_type != ADP_TYPE_UNKNOW) || vbat_vol > LOWPOWER_LOGO_VOL ) { sprdbat_show_lowpower_charge_logo(LOWPOWER_LOGO_ENABLE_TIME); debugf("cboot:vbat greater than 3V or other charger type\n"); } else { sprdbat_show_lowpower_charge_logo(LOWPOWER_LOGO_DISABLE_TIME); debugf("cboot:vbat less than 3V and charge type is SDP or UNKNOW\n"); } #ifdef CONFIG_BATTERY_TEMP } #endif sprdbat_lowbat_chg(temp_status, usb_type); mdelay(SPRDBAT_CHG_POLLING_T); } boot_mode_enum_type check_mode_from_keypad(void) { uint32_t key_mode = 0; int key_code = 0; volatile int i; if (boot_pwr_check() >= PWR_KEY_DETECT_CNT) { mdelay(50); for (i = 0; i < 10; i++) { key_code = board_key_scan(); if(key_code != KEY_RESERVED) break; } key_mode = check_key_boot(key_code); if (!key_mode) key_mode = CMD_NORMAL_MODE; } return key_mode; } // get mode from chipram_env boot_mode_enum_type get_mode_from_chipram_env(void) { boot_mode_t boot_role; char buf[DL_PROCESS_LEN] = {0}; dl_get_downloadflag(buf); dprintf(INFO,"==== in [%s] \n", __func__); boot_role = get_boot_role(); if (boot_role == BOOTLOADER_MODE_DOWNLOAD) { return CMD_DOWNLOAD_MODE; } else if (!strncmp("enable", buf, strlen("enable"))) { dl_clear_downloadflag(); return CMD_AUTODLOADER_REBOOT; } else if (check_mode_from_keypad() == CMD_FASTBOOT_MODE) { return CMD_FASTBOOT_MODE; } else if (boot_role == BOOTLOADER_MODE_UNKNOW) { errorf("unkown uboot role!!!!!!!!!!!!!!!!!\n"); } return CMD_UNDEFINED_MODE; } // 0 get mode from pc tool boot_mode_enum_type get_mode_from_pctool(void) { int ret, to_vol; dprintf(INFO,"==== in [%s] \n", __func__); #if defined(PLATFORM_SHARKLE) || defined(PLATFORM_SHARKL3) \ || defined(PLATFORM_QOGIRL6) || defined(PLATFORM_QOGIRN6PRO) || defined(PLATFORM_QOGIRN6L) to_vol = USBPHY_VDDUSB33_NORMAL; #else to_vol = USBPHY_VDDUSB33_FULLSPEED_TUNE; #endif regulator_set_voltage("vddusb33", to_vol); ret = pctool_mode_detect(); regulator_set_voltage("vddusb33", USBPHY_VDDUSB33_NORMAL); if (ret < 0) return CMD_UNDEFINED_MODE; else { bootcause_cmdline="The pctools sends control commands"; return ret; } } #ifndef CONFIG_ZEBU boot_mode_enum_type get_mode_from_smpl(void) { dprintf(INFO,"==== in [%s] \n", __func__); if(is_smpl_bootup()) { debugf("is_hw_smpl_enable %d\n", is_hw_smpl_enable()); lr_cause = LR_ABNORMAL; bootcause_cmdline="Sudden momentary power loss"; debugf("SMPL bootup!\n"); return CMD_NORMAL_MODE; } return CMD_UNDEFINED_MODE; } #else boot_mode_enum_type get_mode_from_smpl(void) { return CMD_UNDEFINED_MODE; } #endif boot_mode_enum_type get_mode_from_bat_low(void) { int i; dprintf(INFO,"==== in [%s] \n", __func__); #ifndef CONFIG_FPGA //jump loop #ifdef OPLUS_FEATURE_CHG_BASIC int is_bat_low_flag, temp_status, batt_temp; u32 wdt_status = 0; enum sprd_adapter_type charger_type = ADP_TYPE_UNKNOW; wdt_status = status_watchdog(); if (charger_connected()) charger_type = sprdchg_charger_is_adapter(); while(1) { is_bat_low_flag = is_bat_low(); batt_temp = sprdbat_get_battery_temp(); #ifdef CONFIG_BATTERY_TEMP dprintf(INFO,"sprd_chg:%s batt_temp=%d\n", __func__, batt_temp); if (batt_temp >= DISBOOTING_HIGH_TEMP) { #else if (batt_temp >= DISBOOTING_TEMP_77) { #endif logo_display(LOGO_HIGH_BATTERY_TEMP, BACKLIGHT_ON, LCD_DISPLAY_ENABLE); temp_status = DISBOOTING_TEMP; } else if (batt_temp < DISCHARGING_LOW_TEMP_NEGATIVE10 || batt_temp >= DISCHARGING_HIGH_TEMP_53) temp_status = DISCHARGING_TEMP; else temp_status = NORMAL_TEMP; #else int is_bat_low_flag, temp_status, ibat_cur; u32 wdt_status = 0; enum sprd_adapter_type charger_type = ADP_TYPE_UNKNOW; int bat_low_count = 0; wdt_status = status_watchdog(); if (charger_connected()) charger_type = sprdchg_charger_is_adapter(); while(is_bat_low()) { bat_low_count++; ibat_cur = sprdfgu_read_ibat_cur(); if (ibat_cur <= IBAT_CUR_STEP2_700 || bat_low_count > 10) break; dprintf(INFO,"sprd_chg: %s,ibat_cur = %d\n", __func__, ibat_cur); mdelay(50); } while(1) { temp_status = sprdbat_get_battery_temp_status(); is_bat_low_flag = is_bat_low(); #endif if (!is_bat_low_flag && !temp_status) break; #ifdef OPLUS_FEATURE_CHG_BASIC #ifdef CONFIG_BATTERY_TEMP if(batt_temp >= DISBOOTING_HIGH_TEMP && (!power_button_pressed())) break; #endif #endif if (temp_status && is_bat_low_flag) { if(charger_connected() || get_mode_from_vchg()) { dprintf(INFO,"cboot:low battery and abnormal temerature,stop charging...\n"); low_power_charge(temp_status, charger_type); } else { dprintf(INFO, "cboot:low battery and abnormal temerature,shutdown\n"); logo_display(LOGO_LOW_VOL, BACKLIGHT_ON, LCD_DISPLAY_ENABLE); mdelay(LOW_VOL_DISPLAY_DELAY_TIME); return CMD_POWER_DOWN_DEVICE; } } else if (temp_status && !is_bat_low_flag) { dprintf(INFO, "cboot:abnormal temerature,stop charging...\n"); sprdbat_lowbat_chg(temp_status, charger_type); if (temp_status == DISCHARGING_TEMP) return CMD_UNDEFINED_MODE; dprintf(INFO, "cboot:abnormal temerature,disbooting\n"); mdelay(SPRDBAT_CHG_POLLING_T); } else if (!temp_status && is_bat_low_flag) { if(charger_connected() || get_mode_from_vchg()) { dprintf(INFO, "cboot:low battery,charging...\n"); low_power_charge(temp_status, charger_type); } else { dprintf(INFO, "cboot:low battery and shutdown\n"); for (i = 0; i < 3; i++ ) { logo_display(LOGO_LOW_VOL, BACKLIGHT_ON, LCD_DISPLAY_ENABLE); mdelay(400); logo_display(LOGO_LOW_VOL_02, BACKLIGHT_ON, LCD_DISPLAY_ENABLE); mdelay(400); } return CMD_POWER_DOWN_DEVICE; } } if (wdt_status) load_watchdog(300 * 1000); } #endif /* CONFIG_FPGA */ sprdbat_chg_led(0); return CMD_UNDEFINED_MODE; } #ifndef CONFIG_ZEBU boot_mode_enum_type write_sysdump_before_boot_extend(void) { dprintf(INFO,"==== in [%s] \n", __func__); #ifdef CONFIG_CRYPTO_CHECK int enableDump = read_enableDump_from_miscdata(); if (!enableDump) { dprintf(INFO,"write_sysdump_before_boot_extend enableDump = %d, not allow dump \n", enableDump); return CMD_UNDEFINED_MODE; } else { dprintf(INFO,"write_sysdump_before_boot_extend enableDump = %d, allow dump \n", enableDump); } #endif unsigned rst_mode = reboot_mode_check(); #ifdef SPRD_MINI_SYSDUMP handle_minidump_before_boot(rst_mode); #endif #ifdef SPRD_SYSDUMP write_sysdump_before_boot(rst_mode); #endif return CMD_UNDEFINED_MODE; } #else boot_mode_enum_type write_sysdump_before_boot_extend(void) { return CMD_UNDEFINED_MODE; } #endif /* get mode from miscdata */ boot_mode_enum_type get_mode_from_miscdata_boot_flag(void) { dprintf(INFO,"==== in [%s] \n", __func__); #if defined(CONFIG_CUSTOMER_PHONE) && defined(CONFIG_AUTOBOOT) extern unsigned reboot_reg; if ((reboot_reg & 0xFF) == HWRST_STATUS_AUTODLOADER) { dprintf(INFO,"%s:rst_mode is autodloader\n", __func__); return CMD_AUTODLOADER_REBOOT; } #elif defined CONFIG_AUTOBOOT dprintf(INFO," AUTOBOOT ENABLE! \n"); return CMD_NORMAL_MODE; #endif boot_mode_enum_type first_mode = read_boot_flag(); if (first_mode != CMD_UNDEFINED_MODE) { bootcause_cmdline="Detect the firsrt_mode flag in the miscdata partition"; dprintf(INFO,"get mode from firstmode field: %s\n", g_mode_str[first_mode]); return first_mode; } return CMD_UNDEFINED_MODE; } /*1 get mode from file, just for recovery mode now*/ boot_mode_enum_type get_mode_from_file_extend(void) { dprintf(INFO,"==== in [%s] \n", __func__); switch (get_mode_from_file()) { case CMD_RECOVERY_MODE: dprintf(INFO,"cboot:get mode from file:recovery\n"); bootcause_cmdline="Detect the recovery message in the misc partition"; return CMD_RECOVERY_MODE; default: return CMD_UNDEFINED_MODE; } return CMD_UNDEFINED_MODE; } // 2 get mode from watch dog boot_mode_enum_type get_mode_from_watchdog(void) { dprintf(INFO,"==== in [%s] \n", __func__); unsigned rst_mode = reboot_mode_check(); int flag; switch (rst_mode) { case CMD_RECOVERY_MODE: case CMD_FASTBOOT_MODE: case CMD_NORMAL_MODE: case CMD_WATCHDOG_REBOOT: case CMD_AP_WATCHDOG_REBOOT: case CMD_ABNORMAL_REBOOT_MODE: case CMD_UNKNOW_REBOOT_MODE: case CMD_PANIC_REBOOT: case CMD_AUTODLOADER_REBOOT: case CMD_SPECIAL_MODE: case CMD_EXT_RSTN_REBOOT_MODE: case CMD_IQ_REBOOT_MODE: case CMD_SPRDISK_MODE: case CMD_SILENT_MODE: case CMD_BOOTLOADER_PANIC_MODE: case CMD_SML_PANIC_MODE: return rst_mode; case CMD_ALARM_MODE: if ((flag = alarm_flag_check())) { dprintf(INFO,"get_mode_from_watchdog flag=%d\n", flag); if (flag == 1) { bootcause_cmdline="PMIC reg reset and poweroff alarm"; return CMD_ALARM_MODE; } else if (flag == 2) { bootcause_cmdline="PMIC reg reset but Shutdown alarm is abnormal"; return CMD_NORMAL_MODE; } } default: return CMD_UNDEFINED_MODE; } } boot_mode_enum_type get_mode_to_autodloader(void) { int key_code = 0; volatile int i; dprintf(INFO,"==== in [%s] \n", __func__); for (i = 0; i < 10; i++) { key_code = board_key_scan(); if(key_code != KEY_RESERVED) break; } if(key_code==(KEY_VOLUMEUP+KEY_VOLUMEDOWN)) return CMD_AUTODLOADER_REBOOT; return CMD_UNDEFINED_MODE; } // 3 get mode from alarm register boot_mode_enum_type get_mode_from_alarm_register(void) { int flag; dprintf(INFO,"==== in [%s] \n", __func__); if (alarm_triggered() && (flag = alarm_flag_check())) { dprintf(INFO,"get_mode_from_alarm_register flag=%d\n", flag); if (flag == 1) { bootcause_cmdline="RTC poweroff alarm expiry"; return CMD_ALARM_MODE; } else if (flag == 2) { bootcause_cmdline="Shutdown alarm is abnormal"; return CMD_NORMAL_MODE; } } return CMD_UNDEFINED_MODE; } static unsigned int get_gpio_status(unsigned int GPIO_NUM) { int value = -1; int ret = 0; ret = sprd_gpio_request(GPIO_NUM); if (ret < 0) { debugf("cboot: gpio request return ERROR!\n"); return -1; } ret = sprd_gpio_direction_input(GPIO_NUM); if (ret < 0) { debugf("cboot: gpio input return ERROR!\n"); return -1; } value = sprd_gpio_get(GPIO_NUM); return value; } /* get mode from bbat detect*/ boot_mode_enum_type get_mode_from_gpio_bbat_cali(void) { int conf0 = -1; int conf1 = -1; conf0 = get_gpio_status(CONF_0); conf1 = get_gpio_status(CONF_1); debugf("cboot: gpio conf0 = %d, gpio conf1 = %d\n", conf0, conf1); if (conf0 == 0) { bootcause_cmdline = "autotest mode from gpio"; return CMD_AUTOTEST_MODE; } else if (conf0 == 1 && conf1 == 0) { bootcause_cmdline = "caliberation mode from gpio"; return CMD_CALIBRATION_MODE; } else { return CMD_UNDEFINED_MODE; } } /* 4 get mode from charger*/ boot_mode_enum_type get_mode_from_charger(void) { int shutdown_charge_flag = 0, auto_poweron_flag = 0; boot_mode_enum_type bootmode = CMD_UNDEFINED_MODE; dprintf(INFO,"==== in [%s] \n", __func__); auto_poweron_flag = sprdbat_get_auto_poweron_flag(); shutdown_charge_flag = sprdbat_get_shutdown_charge_flag(); dprintf(INFO,"get_shutdown_charge_flag flag=%d\n", shutdown_charge_flag); /* add rtc helper function for power-off charging wakeup alarm debug */ sprd_rtc_alarm_status_check(); if ((!charger_connected()) && (!get_mode_from_vchg())) return bootmode; if (!auto_poweron_flag) { dprintf(INFO,"auto_poweron_flag get mode from charger\n"); bootcause_cmdline="in charging during shutdown the devices"; bootmode = CMD_CHARGE_MODE; } else { dprintf(INFO,"get_auto_poweron_flag auto_poweron_flag=%d\n", auto_poweron_flag); if (shutdown_charge_flag) { dprintf(INFO,"get mode from charger\n"); bootcause_cmdline="in charging during shutdown the devices"; bootmode = CMD_CHARGE_MODE; } else { bootcause_cmdline="Charger connected"; bootmode = CMD_NORMAL_MODE; } } #ifdef CONFIG_DOWNLOAD_FOR_CUSTOMER if (bootmode == CMD_CHARGE_MODE && (board_key_scan() == (KEY_VOLUMEUP + KEY_VOLUMEDOWN)) && (pctool_connected())) { dprintf(ALWAYS, "KEY_VOLUMEUP + KEY_VOLUMEDOWN trigger to download\n"); bootmode = CMD_AUTODLOADER_REBOOT; } #endif return bootmode; } /*5 get mode from keypad*/ boot_mode_enum_type get_mode_from_keypad(void) { uint32_t key_mode = 0; dprintf(INFO,"==== in [%s] \n", __func__); key_mode = check_mode_from_keypad(); dprintf(INFO,"cboot:get mode from keypad:%d, %s\n",key_mode, g_mode_str[key_mode]); if (!key_mode) return CMD_UNDEFINED_MODE; switch(key_mode) { case CMD_RECOVERY_MODE: bootcause_cmdline="Keypad trigger to recovery"; return CMD_RECOVERY_MODE; default: bootcause_cmdline="Pbint triggered"; return CMD_NORMAL_MODE; } } // 6 get mode from gpio boot_mode_enum_type get_mode_from_gpio_extend(void) { dprintf(INFO,"==== in [%s] \n", __func__); if (get_mode_from_gpio()) { bootcause_cmdline="pbint2 triggered"; dprintf(INFO,"Pbint2 triggered, do normal mode\n"); return CMD_NORMAL_MODE; } else { return CMD_UNDEFINED_MODE; } } #if defined CONFIG_ANDROID_AB void do_select_ab(void) { int ret; char slot[3]; #if defined (CONFIG_FPGA) && defined (CONFIG_DDR_BOOT) ret = 0; #else ret = ab_select_slot(); #endif if (ret < 0) { errorf("Android boot failed, error %d.\n", ret); return; } /* Android standard slot names are 'a', 'b', ... */ slot[0] = '_'; slot[1] = BOOT_SLOT_NAME(ret); slot[2] = '\0'; memcpy(g_env_slot, slot, sizeof(slot)); dprintf(CRITICAL,"ANDROID: Booting slot%s\n", slot); } #endif #ifdef CONFIG_MMC_POWP_SUPPORT extern int g_part_protected; extern char *g_part_name; static void do_emmc_powp(void) { if (g_part_protected) { if (common_set_powp(g_part_name)) { errorf("partition %s can't be protected, pls check it\n", g_part_name); return; } debugf("do emmc powp success\n"); } } #endif uint8_t check_payjoy_flag(void); uint8_t check_payjoy_flag() { uint64_t offset; uint8_t val; //PayJoy Control Byte is 12,025 to the tail of persist offset = 2048*1024 - 1 - 1000 - 1024 - 10000; // read payjoy flag from persistent partition. // you may change the actual number of offset according to the size of FRP or persistent partition common_raw_read("persist", 1, offset, &val); // call mmc_read printf("check_payjoy_flag:%d,%d\n",sizeof(val),val); return val; } int sprd_boot(void) { volatile int i; boot_mode_enum_type bootmode = CMD_UNDEFINED_MODE; CBOOT_MODE_ENTRY boot_mode_array[CMD_MAX_MODE] ={0}; FTL_Savepoint_Private(PHASE_SPRDBOOT_INIT); #ifdef CONFIG_AUTOLOAD_MODE autoload_mode(); #endif #ifdef CONFIG_ANDROID_AB if(adjust_spl_slot()) return -1; do_select_ab(); if (ota_processing) dl_set_wdtflag(); #endif if (get_boot_role() == BOOTLOADER_MODE_LOAD){ #ifndef CONFIG_ZEBU reconfig_baudrate(); /* switch baudrate by following kernel menu */ #endif ddr_eng_mode_debug(); // config ddr paras from eng mode #ifdef CONFIG_USB_SPRD_DWC31_PHY if (usb_phy_enabled()) usb_phy_enable(0); #endif } #if defined CONFIG_ZEBU normal_mode(); errorf("normal mode exit with exception!!!\n"); while(1); #endif #ifndef CONFIG_FPGA boot_pwr_check(); #endif for (i = 0; i < CHECK_BOOTMODE_FUN_NUM; i++) { if (0 == s_boot_func_array[i]) { bootmode = CMD_POWER_DOWN_DEVICE; dprintf(INFO,"==== get boot mode in boot func array[%d]\n",i); break; } bootmode = s_boot_func_array[i](); if (CMD_UNDEFINED_MODE == bootmode) { continue; } else { dprintf(INFO,"get boot mode in boot func array[%d]\n",i); break; } } #ifdef VENDOR_EDIT if(bootmode != CMD_POWER_DOWN_DEVICE && bootmode != CMD_DOWNLOAD_MODE){ if (cdt_table_analysis()) return 0; } #endif board_boot_mode_regist(boot_mode_array); /* Don't let phone get into recovery mode if the payjoy flag has been set to 1. Attention: only prevents users enter recovery mode by command "adb reboot recovery" or pressing power and volume buttons, should not affect entering recovery mode by system OTA upgrading or factory reset from Settings. That means the bootloader should check payjoy flag in persistent/frp partition at first, then check BCB(Bootloader Control Block) in misc partition. */ if (1 == check_payjoy_flag() && bootmode == CMD_FASTBOOT_MODE) { bootmode = CMD_NORMAL_MODE; } dprintf(ALWAYS,"enter boot mode g_mode_str[%d]:%s\n", bootmode, g_mode_str[bootmode]); #ifdef CONFIG_MMC_POWP_SUPPORT if (get_boot_role() == BOOTLOADER_MODE_LOAD) do_emmc_powp(); #endif if ((bootmode > CMD_POWER_DOWN_DEVICE) &&(bootmode < CMD_MAX_MODE) && (0 != boot_mode_array[bootmode])) { boot_mode_array[bootmode](); } else { #ifdef CONFIG_FPGA /*FPGA has no power button ,if hasn't detect any mode ,use normal mode*/ dprintf(INFO, "FPGA use normal mode instead of power down.\n"); normal_mode(); #else dprintf(ALWAYS, "power down device\n"); power_down_devices(0); dprintf(ALWAYS, "===== after regist, loop forever!!! \n"); while(1); #endif } dprintf(ALWAYS, "==== [%s]: Power down device. Do not run here forever!!!\n", __func__); power_down_devices(0); return 0; } static void boot_init(const struct app_descriptor *app) { console_init(); sprd_boot(); } APP_START(sprdboot) .init = boot_init, APP_END
最新发布
08-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值