以EXYNOS加MDM9x25为例,连接示意图如下:
Exynos5433需要这几个GPIO以及HSIC,给MDM9x25上电,下载MDM9x25的binary,efs同步以及MDM9x25出错的时候的ramdump collection等工作。
下面按如下步骤来介绍每个部分所需的代码移植,修改以及流程。
- MDM9x25启动,控制GPIO配置
- MDM9x25代码下载以及efs同步过程
- MDM9x25代码下载以及efs同步过程
- MDM9x25的错误处理流程以及ramdump collect过程
- AP与MDM9x25的IPC通信相关模块
(1) device tree添加相关的设置
mdm_pdata {
compatible = "qcom,ext-mdm9x25";
pinctrl-names = "default";
pinctrl-0 = <&ap2mdm_errfatal &ap2mdm_soft_reset &ap2mdm_hostrdy
&ap2mdm_status &ap2mdm_hsic_ready>;
qcom,ramdump-delay-ms = <2000>;
qcom,ramdump-timeout-ms = <120000>;
qcom,sfr-query;
qcom,sysmon-subsys-id = <20>;
qcom,support-shutdown;
qcom,mdm2ap-errfatal-gpio = <&gpa2 6 0xf>;
qcom,ap2mdm-errfatal-gpio = <&gpr3 4 0x1>;
qcom,mdm2ap-status-gpio = <&gpa2 3 0xf>;
qcom,ap2mdm-status-gpio = <&gpf1 2 0x1>;
qcom,ap2mdm-soft-reset-gpio = <&gpf5 1 0x1>;
qcom,mdm2ap-pblrdy-gpio = <&gpa3 0 0xf>;
qcom,ap2mdm-vddmin-gpio = <&gpf4 6 0x1>;
qcom,mdm2ap-vddmin-gpio = <&gpa2 5 0x0>;
qcom,ap2mdm-hsic-ready-gpio = <&gpg2 1 0x1>;
};
mdmpm_pdata {
compatible = "qcom,mdm-hsic-pm";
qcom,ap2mdm-hostrdy-gpio = <&gpf5 0 0x1>;
qcom,mdm2ap-devicerdy-gpio = <&gpa1 2 0x0>;
qcom,mdm2ap-hostwake-gpio = <&gpa3 1 0xf>;
reg = <0x15510000 0x100>, /* EHCI */
<0x15530000 0x100>, /* PHY */
<0x105C0704 0xC>, /* PMU */
<0x156E0204 0xC>; /* USB phy clk */
};
pinctrl@15690000{
ap2mdm_errfatal: ap2mdm_errfatal {
samsung,pins = "gpr3-4";
samsung,pin-function = <0x1>; /* OUT */
samsung,pin-pud = <1>; /* PULL DOWN */
samsung,pin-drv = <0>;
};
};
pinctrl@11090000{
ap2mdm_soft_reset: ap2mdm_soft_reset {
samsung,pins = "gpf5-1";
samsung,pin-function = <0x1>; /* OUT */
samsung,pin-pud = <0>; /* No PULL */
samsung,pin-drv = <0>;
};
ap2mdm_hostrdy: ap2mdm_hostrdy {
samsung,pins = "gpf5-0";
samsung,pin-function = <0x1>; /* OUT */
samsung,pin-pud = <1>; /* PULL DOWN */
samsung,pin-drv = <0>;
};
ap2mdm_status: ap2mdm_status {
samsung,pins = "gpf1-2";
samsung,pin-function = <0x1>; /* OUT */
samsung,pin-pud = <0>; /* No PULL */
samsung,pin-drv = <0>;
};
};
pinctrl@14CC0000{
ap2mdm_hsic_ready: ap2mdm_hsic_ready {
samsung,pins = "gpg2-1";
samsung,pin-function = <0x1>; /* OUT */
samsung,pin-pud = <1>; /* PULL DOWN */
samsung,pin-drv = <0>;
};
};
(2) kernel/exynos54xx/drivers/esoc目录添加,并使能如下feature。
//以下是esoc文件夹下的Makefile文件,要使能的feature是
//CONFIG_ESOC,CONFIG_ESOC_DEV,CONFIG_ESOC_MDM_4x,CONFIG_ESOC_MDM_DRV,
//CONFIG_MDM_HSIC_PM这几个。
# generic external soc control support
ccflags-$(CONFIG_ESOC_DEBUG) := -DDEBUG
obj-$(CONFIG_ESOC) += esoc_bus.o
obj-$(CONFIG_ESOC_DEV) += esoc_dev.o
obj-$(CONFIG_ESOC_CLIENT) += esoc_client.o
obj-$(CONFIG_ESOC_MDM_4x) += esoc-mdm-4x.o
obj-$(CONFIG_ESOC_MDM_DRV) += esoc-mdm-drv.o
obj-$(CONFIG_MDM_HSIC_PM) += mdm_hsic_pm.o
esoc-mdm-4x.c文件:
1) mdm_probe()->mdm9x25_setup_hw()初始化ap2mdm_errfatal,ap2mdm_hostrdy 等几个GPIO。这个过程比较简单不再赘述。
2) mdm9x25_setup_hw()->esoc_clink_register()创建/dev/esoc-0文件让mem_helper能够检查几个gpio状态,并初始化esoc_clink和mdm_ctrl结构。
int esoc_clink_register(){
...
dev->bus = &esoc_bus_type;
dev->parent = &esoc_bus;
dev_set_name(dev, "esoc%d", id);
err = device_register(dev);
...
}
esoc_bus为device类型,定义和注册如下,所以上面dev->parent = &esoc_bus的话,device_register(dev)之后会在/sys/devices/esoc-bus目录下生成dev的名字对应的节点。
struct device esoc_bus = {
.init_name = "esoc-bus"
};
device_register(&esoc_bus);
看一下dev->bus = &esoc_bus_type;这句。这个其实会负责/dev/esoc-0 字符设备
然后设置相应的file_operation等的。然后还可以通过bus_find_device(),根据esoc_bus_type来找对应的dev。
struct bus_type esoc_bus_type = {
.name = "esoc",
.match = esoc_bus_match,
.dev_attrs = esoc_clink_attrs,
};
bus_register(&esoc_bus_type);//注册esoc_bus_type之后,就会在/sys/bus/下生成esoc目录。
//之后在esoc_dev_init函数里边生成class,创建字符设备等,关键一步还是注册bus_register_notifier。这样以esoc_bus_type为dev->bus的设备注册的时候都会调用对应的函数。
int __init esoc_dev_init(void){
esoc_class = class_create(THIS_MODULE, "esoc-dev");//在sys/class下生成esoc-dev
esoc_major = register_chrdev(0, "esoc", &esoc_dev_fops);
ret = bus_register_notifier(&esoc_bus_type, &esoc_dev_notifier);
}
static struct notifier_block esoc_dev_notifier = {
.notifier_call = esoc_dev_notifier_call,
};
//添加设备的时候,查看bus,并调用相应的notifier函数的过程在:drivers/base/core.c文件中的
//device_add()函数中。
/* /* Notify clients of device addition. This call must come * after dpm_sysfs_add() and before kobject_uevent(). */
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
*/
//这样在esoc_clink_register()函数中注册dev的话,因为这个dev->bus是esoc_bus_type就会调用到下面的函数,生成/dev/esoc-0,相应的设备号创建和file_operation的定义也可以很容易看到。
//esoc_dev_notifier_call()->esoc_clink_add_device()
int esoc_clink_add_device(struct device *dev, void *dummy)
{
struct esoc_udev *esoc_udev;
struct esoc_clink *esoc_clink = to_esoc_clink(dev);
esoc_udev = get_free_esoc_udev(esoc_clink);
if (IS_ERR(esoc_udev))
return PTR_ERR(esoc_udev);
//下面创建/dev/esoc-0
esoc_udev->dev = device_create(esoc_class, &esoc_clink->dev,
MKDEV(esoc_major, esoc_clink->id),
esoc_clink, "esoc-%d", esoc_clink->id);
if (IS_ERR(esoc_udev->dev)) {
pr_err("failed to create user device\n");
goto dev_err;
}
return 0;
dev_err:
return_esoc_udev(esoc_udev);
return -ENODEV;
}
static const struct file_operations esoc_dev_fops = {
.owner = THIS_MODULE,
.open = esoc_dev_open,
.unlocked_ioctl = esoc_dev_ioctl,
.release = esoc_dev_release,
};
esoc-mdm-drv.c文件:
int __init esoc_ssr_init(void)
{
pr_err("[MIF] %s", __func__);
#if defined(CONFIG_MACH_TRLTE_LDU) || defined(CONFIG_MACH_TBLTE_LDU)
pr_err("%s LDU doesn't have modem, skip esoc drv register", __func__);
return 0;
#endif
return esoc_drv_register(&esoc_ssr_drv);
}
//在注册driver的过程中,bus和probe需要被赋值。这样在driver_register的过程中,会调用到bus->match函数,也就是esoc_bus_match()函数来和dev进行匹配(过程是driver_register()->bus_add_driver()->driver_attach()->__driver_attach()->driver_match_device(),因为drv->bus->p->drivers_autoprobe默认是1,所以如果不改动的话,就会调用的相应bus的match函数,如果匹配成功的话,就会调用driver_probe_device()函数等,调用自己的probe函数)。
int esoc_drv_register(struct esoc_drv *driver)
{
int ret;
driver->driver.bus = &esoc_bus_type;
driver->driver.probe = esoc_bus_probe; //bus->match函数匹配成功就会调用这个probe函数
ret = driver_register(&driver->driver); //
if (ret)
return ret;
return 0;
}
struct bus_type esoc_bus_type = {
.name = "esoc",
.match = esoc_bus_match,
//这个match比较compat_table里边的名字和esoc_link.name。由于esoc_link.name定义成了
//MDM9x25_LABEL也就是MDM9x25,所以下面的drv也必须匹配才能调用probe函数
.dev_attrs = esoc_clink_attrs,
};
static struct esoc_drv esoc_ssr_drv = {
.owner = THIS_MODULE,
.probe = esoc_ssr_probe,
.compat_table = compat_table,
.compat_entries = ARRAY_SIZE(compat_table),
.driver = {
.name = "mdm-4x",
},
};
static struct esoc_compat compat_table[] = {
{ .name = "MDM9x25",
.data = NULL,
},
{
.name = "MDM9x35",
.data = NULL,
},
};
struct bus_type esoc_bus_type = {
.name = "esoc",
.match = esoc_bus_match,
.dev_attrs = esoc_clink_attrs,
};
struct bus_type esoc_bus_type = {
.name = "esoc",
.match = esoc_bus_match,
.dev_attrs = esoc_clink_attrs,
};
上面的执行完之后,就会生成/sys/bus/esoc/drivers/mdm-4x
root@royceltectc:/sys/bus/esoc/drivers/mdm-4x # ls -l
ls -l
--w------- root root 4096 2015-01-13 16:35 bind
lrwxrwxrwx root root 2015-01-13 16:35 esoc0 -> ../../../../devices/qcom,mdm1.50/esoc0
--w------- root root 4096 2015-01-13 16:35 uevent
--w------- root root 4096 2015-01-13 16:35 unbind
int esoc_ssr_probe(struct esoc_clink *esoc_clink)
{
int ret;
struct mdm_drv *mdm_drv;
struct esoc_eng *esoc_eng;
pr_info("[MIF] %s\n", __func__);
mdm_drv = devm_kzalloc(&esoc_clink->dev, sizeof(*mdm_drv), GFP_KERNEL);
if (IS_ERR(mdm_drv))
return PTR_ERR(mdm_drv);
esoc_eng = &mdm_drv->cmd_eng;
esoc_eng->handle_clink_evt = mdm_handle_clink_evt;
ret = esoc_clink_register_cmd_eng(esoc_clink, esoc_eng);
if (ret) {
dev_err(&esoc_clink->dev, "failed to register cmd engine\n");
return ret;
}
//设置subsystem restart的函数,具体看下面函数体。
ret = mdm_register_ssr(esoc_clink);
if (ret)
goto ssr_err;
mdm_drv->mdm_queue = alloc_workqueue("mdm_drv_queue", 0, 0);
if (!mdm_drv->mdm_queue) {
dev_err(&esoc_clink->dev, "could not create mdm_queue\n");
goto queue_err;
}
//设置drv_data为mdm_drv,然后初始化mdm_drv。
esoc_set_drv_data(esoc_clink, mdm_drv);
init_completion(&mdm_drv->boot_done);
init_completion(&mdm_drv->req_eng_wait);
INIT_WORK(&mdm_drv->ssr_work, mdm_ssr_fn);
mdm_drv->esoc_clink = esoc_clink;
mdm_drv->mode = PWR_OFF;
mdm_drv->boot_fail = false;
//设置重启通知函数
mdm_drv->esoc_restart.notifier_call = esoc_msm_restart_handler;
ret = register_reboot_notifier(&mdm_drv->esoc_restart);
if (ret)
dev_err(&esoc_clink->dev, "register for reboot failed\n");
return 0;
queue_err:
esoc_clink_unregister_ssr(esoc_clink);
ssr_err:
esoc_clink_unregister_cmd_eng(esoc_clink, esoc_eng);
return ret;
}
/////////////////////////////////////////////////////
mdm_register_ssr()->esoc_clink_register_ssr()->subsys_register()
struct subsys_device *subsys_register(struct subsys_desc *desc)
{
struct subsys_device *subsys;
int ret;
subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
if (!subsys)
return ERR_PTR(-ENOMEM);
subsys->desc = desc;
subsys->owner = desc->owner;
subsys->dev.parent = desc->dev;
subsys->dev.bus = &subsys_bus_type;
subsys->dev.release = subsys_device_release;
subsys->notify = subsys_notif_add_subsys(desc->name);
snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
wake_lock_init(&subsys->wake_lock, WAKE_LOCK_SUSPEND, subsys->wlname);
INIT_WORK(&subsys->work, subsystem_restart_wq_func);
spin_lock_init(&subsys->track.s_lock);
subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
if (subsys->id < 0) {
ret = subsys->id;
goto err_ida;
}
dev_set_name(&subsys->dev, "subsys%d", subsys->id);
mutex_init(&subsys->track.lock);
ret = subsys_debugfs_add(subsys);
if (ret)
goto err_debugfs;
//生成/sys/devices/qcom,mdm1.50/esoc0/subsys0 ,link到
//sys/bus/msm_subsys/devices/sybsys0
ret = device_register(&subsys->dev);
if (ret) {
device_unregister(&subsys->dev);
goto err_register;
}
//生成/dev/subsys_esoc0,并设置file_operations。
ret = subsys_misc_device_add(subsys);
if (ret) {
put_device(&subsys->dev);
goto err_register;
}
return subsys;
err_register:
subsys_debugfs_remove(subsys);
err_debugfs:
mutex_destroy(&subsys->track.lock);
ida_simple_remove(&subsys_ida, subsys->id);
err_ida:
wake_lock_destroy(&subsys->wake_lock);
kfree(subsys);
return ERR_PTR(ret);
}
(2) arch/arm/mach-xx/subsystem_restart.c文件:
前面已经讲过在esoc_clink_register_ssr()的时候,创建/dev/subsys_esoc0。
subsys_register()->subsys_misc_device_add()对应的file_operation是:
static const struct file_operations subsys_device_fops = {
.owner = THIS_MODULE,
.open = subsys_device_open,
.release = subsys_device_close,
};
//subsys_device_open()这个是用来做subsystem power up的。
//subsys_device_open()->subsystem_get()->subsys_start()->subsys->desc->powerup()
//由于
static int mdm_register_ssr(struct esoc_clink *esoc_clink)
{
esoc_clink->subsys.shutdown = mdm_subsys_shutdown;
esoc_clink->subsys.ramdump = mdm_subsys_ramdumps;
esoc_clink->subsys.powerup = mdm_subsys_powerup;
esoc_clink->subsys.crash_shutdown = mdm_crash_shutdown;
return esoc_clink_register_ssr(esoc_clink);
}
所以subsys_device_open()最用调用mdm_subsys_powerup()去给mdm上电。
(3) kernel/exynos54xx/drivers/usb/misc/ks_bridge.c文件修改,识别hsic的device id并创建/dev/ks_bridge节点,用来下载binary, 下载modem ramdump以及做efs sync操作。
ksb_init()->usb_register(&ksb_usb_driver);
//usb驱动定义
static struct usb_driver ksb_usb_driver = {
.name = "ks_bridge",
.probe = ksb_usb_probe,
.disconnect = ksb_usb_disconnect,
.suspend = ksb_usb_suspend,
.resume = ksb_usb_resume,
.reset_resume = ksb_usb_resume,
.id_table = ksb_usb_ids,
.supports_autosuspend = 1,
};
static const struct usb_device_id ksb_usb_ids[] = {
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9008, 0), //0x9008 ks_hsic_bridge设备号
.driver_info = (unsigned long)&ksb_fboot_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904C, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 2),
.driver_info = (unsigned long)&ksb_efs_usb_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908A, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908E, 3),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909C, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909D, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909E, 3),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909F, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A0, 2),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A4, 3),
.driver_info = (unsigned long)&ksb_efs_hsic_dev, },
{} /* terminating entry */
};
static struct ksb_dev_info ksb_fboot_dev[] = {
{
.name = "ks_hsic_bridge", //用来下载binary,接收modem ramdump的/dev/ks_hsic_bridge
},
{
.name = "ks_usb_bridge",
},
};
static struct ksb_dev_info ksb_efs_hsic_dev = {
.name = "efs_hsic_bridge", // /dev/efs_hsic_bridge做efs同步的
};
需要在cmdline里边添加“androidboot.baseband=mdm”来选择合适的MDM。
//在esoc-mdm-4x.c文件里边查看如下部分
static struct of_device_id mdm_dt_match[] = {
{ .compatible = "qcom,ext-mdm9x25",
.data = &mdm9x25_ops, },
{},
};
MODULE_DEVICE_TABLE(of, mdm_dt_match);
static int __init get_baseband(char *str)
{
if(!strncasecmp(str, "mdm2", 4)) {
strcpy(mdm_dt_match->compatible, "qcom,ext-mdm9x35");
mdm_dt_match->data = &mdm9x35_ops;
} else if(!strncasecmp(str, "mdm", 3)) {
strcpy(mdm_dt_match->compatible, "qcom,ext-mdm9x25");
mdm_dt_match->data = &mdm9x25_ops;
}
pr_emerg("%s: %s\n", __func__, mdm_dt_match->compatible);
return 0;
}
__setup("androidboot.baseband=", get_baseband);
(1) vendor/qcom/proprietary/mdm_helper目录添加
(2) vendor/qcom/proprietary/ks目录添加
(3) android/device/samsung/trelte_common/init.trelte.rc添加如下代码,启动mdm_helper和mdm_helper_proxy和设置下载目录等:
//init.xx.rc
on fs
mkdir /data/tombstones 0771 system system
#MDM requirement
mkdir /dev/block/modem
symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs1 /dev/block/modem/m9kefs1
symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs2 /dev/block/modem/m9kefs2
symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs3 /dev/block/modem/m9kefs3
symlink /dev/block/platform/15540000.dwmmc0/by-name/ /dev/block/modem/dump_path
chown system radio /dev/block/modem/m9kefs1
chmod 0775 /dev/block/modem/m9kefs1
chown system radio /dev/block/modem/m9kefs2
chmod 0775 /dev/block/modem/m9kefs2
chown system radio /dev/block/modem/m9kefs3
chmod 0775 /dev/block/modem/m9kefs3
chown system radio /dev/block/modem/dump_path
chmod 0775 /dev/block/modem/dump_path
mkdir /firmware 0771 system system
mount vfat /dev/block/mmcblk0p13 /firmware ro shortname=lower fmask=0133,dmask=0022
chown system system /tombstones
chmod 0775 /tombstones
mkdir /tombstones/modem 0775 system system
mkdir /tombstones/lpass 0775 system system
mkdir /tombstones/wcnss 0775 system system
mkdir /tombstones/dsps 0775 system system
rmdir /tombstones/qcks
mkdir /tombstones/qcks 771 system system
rmdir /tombstones/efs
mkdir /tombstones/efs 771 system system
rmdir /tombstones/mdm
mkdir /tombstones/mdm 0771 system system
chown system radio /dev/block/platform/15540000.dw_mmc0/by-name
chmod 0775 /dev/block/platform/15540000.dw_mmc0/by-name
write /sys/module/rmnet_usb/parameters/mux_enabled 1
write /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links 8
write /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev 17
write /sys/module/rmnet_usb/parameters/rmnet_data_init 1
# Allow QMUX daemon to assign port open wait time
chown radio radio /sys/devices/virtual/hsicctl/hsicctl0/modem_wait
write /sys/module/rmnet_usb/parameters/mux_enabled 1
write /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links 8
write /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev 17
write /sys/module/rmnet_usb/parameters/rmnet_data_init 1
# Allow QMUX daemon to assign port open wait time
chown radio radio /sys/devices/virtual/hsicctl/hsicctl0/modem_wait
on early-init
symlink /data/tombstones /tombstones
service mdm_helper /system/bin/mdm_helper
class core
onrestart setprop ro.service.mdm_helper_restarted "true"
# disabled
service mdm_helper_proxy /system/bin/mdm_helper_proxy
class core
disabled
on property:ro.mdm_helper_proxy_req=true
start mdm_helper_proxy
(1) mdm上电:
//vendor/qcom/proprietary/mdm_helper的代码,会启动如下两个service
service mdm_helper /system/bin/mdm_helper
class core
onrestart setprop ro.service.mdm_helper_restarted "true"
disabled
service mdm_helper_proxy /system/bin/mdm_helper_proxy
class core
disabled
/********************************** mdm_helper service和mdm_helper_proxy会用waitqueue方式做一个同步。 因为下载binary和其他的操作都是mdm_helper流程做,如果mdm_helper服务先启动,就必须等到mdm_helper_proxy实际给mdm上电之后mdm_helper服务才能进行下载binary和其他操作。 ***********************************/
1) mdm_helper_proxy是通过打开/dev/subsys_esoc0实际给mdm上电的,这个在上面的subsystem_restart.c文件中已经讲过。
modem_proxy_routine()->打开/dev/subsys_esoc0之后就每0.5秒醒来一次,继续睡眠:
static void* modem_proxy_routine(void *arg)
{
struct mdm_device *dev = (struct mdm_device*)arg;
char powerup_node[MAX_PATH_LEN];
int fd;
snprintf(powerup_node, sizeof(powerup_node),
"/dev/subsys_%s",
dev->esoc_node);
fd = open(powerup_node, O_RDONLY);
if (fd < 0) {
ALOGE("%s: Proxy thread failed to open esoc node: %s",
dev->mdm_name,
powerup_node);
}
do {
sleep(50000);
} while(1);
return NULL;
}
2) mdm_helper在哪里等待mdm上电完成并继续做接下来的事情呢?
modem_state_machine()->dev->ops.power_up()->mdm9k_powerup():
int mdm9k_powerup(struct mdm_device *dev){
.....
if (ioctl(dev->device_descriptor, //打开的是/dev/esoc-0
ESOC_WAIT_FOR_REQ, &request) < 0) {
ALOGE("%s: REQ_ENG: ESOC_WAIT_FOR_REQ ioctl failed",
dev->mdm_name);
return RET_FAILED;
}
.....
}
根据打开的节点和cmd,会跑到esoc_dev_ioctl里边
static long esoc_dev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
.....
case ESOC_WAIT_FOR_REQ:
if (esoc_clink->req_eng != &uhandle->eng)
return -EACCES;
pr_err("esoc REQ enginer waiting on request\n");
err = wait_event_interruptible(esoc_udev->req_wait,//这里就是等待mdm上电的地方
!kfifo_is_empty(&esoc_udev->req_fifo));
pr_err("esoc REQ engine released from wait\n");
if (!err) {
pr_err("esoc REQ engine reading from req fifo\n");
err = kfifo_out_spinlocked(&esoc_udev->req_fifo, &req,
sizeof(req),
&esoc_udev->req_fifo_lock);
if (err != sizeof(req)) {
pr_err("read from clink %s req q failed\n",
esoc_clink->name);
return -EIO;
}
pr_err("esoc REQ engine processing request\n");
put_user(req, (unsigned long __user *)uarg);
}
return err;
break;
....
}
mdm_helper_proxy在上电成功之后,mdm会拉高pbl管脚,因为之前已经设置了中断,会跑到中断函数mdm_pblrdy_change()。调用顺序是mdm_pblrdy_change()->esoc_clink_queue_request()->esoc_udev_handle_clink_req()->wake_up_interruptible(&esoc_udev->req_wait) 这个应该就是唤醒mdm_helper服务的地方。
<4>[ 9.766662] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ enginer waiting on request
//打印完esoc REQ enginer waiting on request之后mdm_helper进入睡眠
//在mdm_helper_proxy给mdm上电,检测到pbl之
<6>[ 10.186900] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: Powering on modem for the first time
<6>[ 10.186918] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: mdm_toggle_soft_reset
<6>[ 10.207415] [0:irq/570-mdm pbl: 1767] ext-mdm qcom,mdm1.50: pbl ready 1:
//这里就是检测到pbl变高的时候中断函数打印的
<3>[ 10.207438] [0:irq/570-mdm pbl: 1767] ext-mdm qcom,mdm1.50: Signaling request engine for images
<4>[ 10.207455] [0:irq/570-mdm pbl: 1767] <3>@BATAUTERR@releasing esoc REQ enginer from wait
//后面mdm_helper等待的waitqueue被唤醒,继续执行下载代码或者接受ramdump的操作
<4>[ 10.207508] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine released from wait
<4>[ 10.207534] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine reading from req fifo
<4>[ 10.207556] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine processing request
<12>[ 10.207988] [4: mdm_helper: 3137] [ALOG] MDM9x35: Setting up HSIC boot link
<12>[ 10.208157] [4: mdm_helper: 3137] [ALOG] MDM9x35: configure_flashless_boot_dev: Initiating HSIC unbind
<6>[ 10.208539] [4: mdm_helper: 3137] s5p-ehci 15510000.usb: remove, state 1
<7>[ 10.208571] [4: mdm_helper: 3137] s5p-ehci 15510000.usb: roothub graceful disconnect
<6>[ 10.208605] [4: mdm_helper: 3137] usb usb1: USB disconnect, device number 1
<6>[ 10.208626] [4: mdm_helper: 3137] usb 1-2: USB disconnect, device number 2
<7>[ 10.208651] [4: mdm_helper: 3137] usb 1-2: unregistering device
<7>[ 10.208672] [4: mdm_helper: 3137] usb 1-2: unregistering interface 1-2:1.0
<7>[ 10.210592] [1: mdm_helper: 3137] usb 1-2: usb_disable_device nuking all URBs
<7>[ 10.211908] [3: mdm_helper: 3137] usb usb1: unregistering device
<7>[ 10.211925] [3: mdm_helper: 3137] usb usb1: unregistering interface 1-0:1.0
<7>[ 10.212353] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: shutdown urb ffffffc0b77ccb40 ep1in-intr
<7>[ 10.213146] [3: mdm_helper: 3137] usb usb1: usb_disable_device nuking all URBs
<6>[ 10.214606] [0: mc_log: 3126] MobiCore mcd: 501|SCRYPTO DRV [INFO]: FIPS ECDSA selftest passed.
<6>[ 10.255958] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: pblrdy i:0
<6>[ 10.255984] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: Set qcom,ap2mdm-hostrdy-gpio to 1 //给mdm上电之后还要拉高ap2mdm-hostrdy-gpio这个gpio。这个管脚一般也表示成AP2MDM_STATUS
modem crash触发mdm_errfatal()中断处理函数,然后就是mdm_handle_clink_evt()->mdm_ssr_fn()->subsystem_restart_dev()然后在dev->restart_leve=RESET_SUBSYS_COUPLED的时候,就会再跑到subsystem_restart_wq_func()->mdm_subsys_ramdumps()->mdm_cmd_exe()的ESOC_EXE_DEBUG里,
mdm->debug = 1 后重启cp,等在ramdump collection弄完。
cp重启的时候,会拉高PBL端口,触发mdm_pblrdy_change中断函数,在函数里边检查mdm->debug。等于1的话,就会跑到esoc_clink_queue_request(ESOC_REQ_DEBUG, esoc)->esoc_udev_handle_clink_req()中设置req_fifo的值,并wake_up_interruptible(&esoc_udev->req_wait)。这会唤醒esoc_dev_ioctl中case ESOC_WAIT_FOR_REQ的wait_event_interruptible。并返回req_fifod的值(ESOC_REQ_DEBUG)给应用层。由于modem_state_machine()在开机后会停留在MDM_HELPER_STATE_POST_POWERUP state,每隔一段时间会跑进mdm9k_monitor()函数,用ESOC_WAIT_FOR_REQ读返回值。上面说了重启之后,就会返回ESOC_REQ_DEBUG。所以会赋值dev->required_action = MDM_REQUIRED_ACTION_RAMDUMPS,跑到modem_state_machine()函数的MDM_HELPER_STATE_RAMDUMP状态里边,开始collect_ramdumps。
if (ioctl(dev->device_descriptor,
ESOC_WAIT_FOR_REQ, &request) < 0)
之后mdm9k_powerup()会跑到configure_flashless_boot_dev(),函数如下:
static int configure_flashless_boot_dev(struct mdm_device *dev, int mode)
{
struct mdm_private_data *pdata = NULL;
int cmd = ESOC_IMG_XFER_RETRY;
int req = 0;
int rcode, fd;
int i;
if (!dev) {
ALOGE("Device structure passed in as NULL");
return RET_FAILED;
}
pdata = (struct mdm_private_data*)dev->private_data;
if(!pdata) {
ALOGE("%s: %s: Private data is null",
dev->mdm_name, __func__);
return RET_FAILED;
}
if(!strncmp(dev->mdm_link, LINK_HSIC, 5)) {
if (mode == MODE_BOOT || mode == MODE_RAMDUMP) { //boot或者modem crash需要下载ramdump的时候
ALOGI("%s: Setting up %s boot link",
dev->mdm_name,
dev->mdm_link);
for (i = 0; i < NUM_LINK_RETRIES; ++i) {
if (pdata->peripheral_cmd) {
ALOGI("%s: %s: Initiating HSIC unbind",
dev->mdm_name,
__func__);
pdata->peripheral_cmd(dev,
PERIPHERAL_CMD_UNBIND);
}
if (ioctl(dev->device_descriptor, ESOC_NOTIFY,
&cmd) < 0) {
ALOGE("%s: :%s: Failed to reset mdm",
dev->mdm_name,
__func__);
return RET_FAILED;
}
if (ioctl(dev->device_descriptor,
ESOC_WAIT_FOR_REQ,
&req) < 0) {
ALOGE("%s: %s:wait for image xfer fail",
dev->mdm_name,
__func__);
return RET_FAILED;
}
if (req != ESOC_REQ_IMG &&
(mode != MODE_RAMDUMP)) {
ALOGE("%s: %s: Unnexpected request: %d",
dev->mdm_name,
__func__,
req);
continue;
}
usleep(500000);
if (pdata->peripheral_cmd) {
ALOGI("%s: %s: Initiating HSIC bind",
dev->mdm_name,
__func__);
pdata->peripheral_cmd(dev,
PERIPHERAL_CMD_BIND);
}
rcode = WaitForCOMport(
pdata->flashless_boot_device,
5, 0);
if (rcode == RET_SUCCESS)
break;
}
if (rcode != RET_SUCCESS) {
ALOGE("%s: %s: Failed to setup HSIC link",
dev->mdm_name,
__func__);
return RET_FAILED;
}
} else if (mode == MODE_RUNTIME) {//系统启动之后做efs sync等
ALOGI("%s: Setting up %s link for efs_sync",
dev->mdm_name,
dev->mdm_link);
peripheral_reset(dev);
ALOGI("%s: Sending boot status notification to HSIC",
dev->mdm_name);
#if 1
if (ioctl(dev->device_descriptor,
ESOC_SET_HSIC_READY) < 0) {
ALOGE("%s: %s:hsic_ready failed", dev->mdm_name,
__func__);
return RET_FAILED;
}
#else
for (i = 0; i < MAX_HSIC_NOTIFICATION_RETRIES; i++) {
fd = open(HSIC_NOTIFICATION_NODE, O_WRONLY);
if (fd < 0)
{
if (i >= MAX_HSIC_NOTIFICATION_RETRIES \
-1) {
ALOGE("%s: node open fail: %s",
dev->mdm_name,
strerror(errno)
);
return RET_FAILED;
}
usleep(100000);
} else {
rcode = write(fd, "1", sizeof(char));
close(fd);
if (rcode < 0) {
ALOGE("%s:node write err: %s",
dev->mdm_name,
strerror(errno)
);
return RET_FAILED;
} else {
ALOGI("%s: Notification sent",
dev->mdm_name);
break;
}
}
}
#endif
}
} else {
ALOGE("%s: Link %s not supported by mdm-helper",
dev->mdm_name,
dev->mdm_link);
return RET_FAILED;
}
return RET_SUCCESS;
}
configure_flashless_boot_dev()函数负责检查建立hsic通道,这个函数中如果是boot或者ramdump状态,会走如下步骤:
(1) hsic unbind:
pdata->peripheral_cmd(dev,PERIPHERAL_CMD_UNBIND);
//这个会跑到mdm_hsic_peripheral_cmd()里边执行如下操作:
case PERIPHERAL_CMD_UNBIND:
//transport_unbind_node = "/sys/bus/platform/drivers/s5p-ehci/unbind"
//transport_unbind_command = "15510000.usb"
fd = open(pdata->transport_unbind_node, O_WRONLY);
if (fd < 0) {
ALOGE("Failed to open bind node : %s", strerror(errno));
goto error;
}
if(write(fd, pdata->transport_unbind_command,
strlen(pdata->transport_unbind_command)) < 0) {
ALOGE("Failed to write to bind node: %s",
strerror(errno));
goto error;
}
break;
一般输出如下log
<12>[10.208157] [4:mdm_helper: 3137] [ALOG] MDM9x35: configure_flashless_boot_dev: Initiating HSIC unbind
<6>[10.208539] [4:mdm_helper: 3137] s5p-ehci 15510000.usb: remove, state 1
<7>[10.208571] [4:mdm_helper: 3137] s5p-ehci 15510000.usb: roothub graceful disconnect
<6>[10.208605] [4:mdm_helper: 3137] usb usb1: USB disconnect, device number 1
<6>[10.208626] [4:mdm_helper: 3137] usb 1-2: USB disconnect, device number 2
<7>[10.208651] [4:mdm_helper: 3137] usb 1-2: unregistering device
<7>[10.208672] [4:mdm_helper: 3137] usb 1-2: unregistering interface 1-2:1.0
<7>[10.210592] [1:mdm_helper: 3137] usb 1-2: usb_disable_device nuking all URBs
<7>[10.211908] [3:mdm_helper: 3137] usb usb1: unregistering device
<7>[10.211925] [3:mdm_helper: 3137] usb usb1: unregistering interface 1-0:1.0
<7>[10.212353] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: shutdown urb ffffffc0b77ccb40 ep1in-intr
<7>[10.213146] [3:mdm_helper: 3137] usb usb1: usb_disable_device nuking all URBs
(2) ioctl(dev->device_descriptor, ESOC_NOTIFY, &cmd) 这里cmd是ESOC_IMG_XFER_RETRY,所以看mdm_notify函数中的case ESOC_IMG_XFER_RETRY,是在重启mdm。当然后面紧跟的
ioctl(dev->device_descriptor,ESOC_WAIT_FOR_REQ,&req) < 0)跟上面说的一样,在等待mdm重启完毕,modem的pbl被拉高。
跟上面重启的时候一样,也是输入如下log
<6>[10.255958] [6:mdm_helper_prox:3257] ext-mdm qcom,mdm1.50: pblrdy i:0
<6>[10.255984] [6:mdm_helper_prox:3257] ext-mdm qcom,mdm1.50: Set qcom,ap2mdm-hostrdy-gpio to 1
...
<7>[10.306512] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: stop
<7>[10.307539] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: reset command 0010b06 park=3 ithresh=1 period=512 Reset HALT
<7>[10.307761] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: irq normal 9 err 0 iaa 4 (lost 0)
<7>[10.307776] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: complete 9 unlink 0
<7>[10.307791] [3mdm_helper: 3137] s5p-ehci 15510000.usb: ehci_stop completed status 1000 Halt
<6>[10.307902] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: USB bus 1 deregistered
<7>[10.307981] [3:mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: samsung_usb2phy_shutdown: End of setting for shutdown
<6>[10.308455] [3:mdm_helper: 3137] ext-mdm qcom,mdm1.50: mdm_toggle_soft_reset
<4>[10.317728] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ enginer waiting on request
...
<4>[10.329003] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine released from wait
<4>[10.329013] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine reading from req fifo
<4>[10.329023] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine processing request
(3) hsic bind操作:
和上面unbind差不多: pdata->peripheral_cmd(dev, PERIPHERAL_CMD_BIND)
unbind hsic -> mdm重启成功 -> hsic bind之后,就可以找检测到modem hsic,并根据其idVendor和idProduct初始化usb设备。像如下Log,由于modem已经准备进入下载模式或者ramdump collection模式,所以检测到的usb设备号需要和ks_bridge.c文件中的设备号一样才能创建ks_hsic_bridge节点。
static struct ksb_dev_info ksb_fboot_dev[] = {
{
.name = "ks_hsic_bridge",
},
{
.name = "ks_usb_bridge",
},
};
static const struct usb_device_id ksb_usb_ids[] = {
{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9008, 0),
.driver_info = (unsigned long)&ksb_fboot_dev, },
...
}
以下可以看到bind之后检测到usb设备号的过程
<12>[ 10.829278] [3: mdm_helper: 3137] [ALOG] MDM9x35: configure_flashless_boot_dev: Initiating HSIC bind
<3>[ 10.829789] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: s5p_ehci_probe
<7>[ 10.829817] [3: mdm_helper: 3137] of_get_named_gpio_flags: can't parse gpios property <3>[ 10.829989] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: can not find l2-retention value <6>[ 10.830115] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: IP clock gating is N/A <7>[ 10.831096] [3: mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: Can't configure specified phy mode
<7>[ 10.831145] [3: mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: end of samsung_usb2phy_init
<6>[ 10.831174] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: EHCI Host Controller
<6>[ 10.831255] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: new USB bus registered, assigned bus number 1
<7>[ 10.831312] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset hcs_params 0x1212 dbg=0 cc=1 pcc=2 ordered ports=2
<7>[ 10.831341] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset hcc_params a026 thresh 2 uframes 256/512/1024 park
<7>[ 10.831617] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: park 3
<7>[ 10.831659] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset command 0080b02 park=3 ithresh=8 period=1024 Reset HALT
<6>[ 10.831750] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: irq 254, io mem 0x15510000
<7>[ 10.831786] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: init command 0010b05 park=3 ithresh=1 period=512 RUN
<6>[ 10.845956] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: USB 2.0 started, EHCI 1.00
<7>[ 10.846591] [3: mdm_helper: 3137] usb usb1: default language 0x0409
<7>[ 10.846774] [3: mdm_helper: 3137] usb usb1: udev 1, busnum 1, minor = 0
<6>[ 10.846797] [3: mdm_helper: 3137] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
<6>[ 10.846820] [3: mdm_helper: 3137] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
<6>[ 10.846843] [3: mdm_helper: 3137] usb usb1: Product: EHCI Host Controller
<6>[ 10.846864] [3: mdm_helper: 3137] usb usb1: Manufacturer: Linux 3.10.61-5726939-eng ehci_hcd
<6>[ 10.846885] [3: mdm_helper: 3137] usb usb1: SerialNumber: 15510000.usb
<7>[ 10.848957] [3: mdm_helper: 3137] usb usb1: usb_probe_device
<7>[ 10.848992] [3: mdm_helper: 3137] usb usb1: configuration #1 chosen from 1 choice
<7>[ 10.849108] [3: mdm_helper: 3137] usb usb1: adding 1-0:1.0 (config #1, interface 0)
<7>[ 10.849929] [3: mdm_helper: 3137] hub 1-0:1.0: usb_probe_interface
<7>[ 10.849965] [3: mdm_helper: 3137] hub 1-0:1.0: usb_probe_interface - got id
<6>[ 10.850005] [3: mdm_helper: 3137] hub 1-0:1.0: USB hub found
<6>[ 10.850102] [3: mdm_helper: 3137] hub 1-0:1.0: 2 ports detected
<7>[ 10.850133] [3: mdm_helper: 3137] hub 1-0:1.0: standalone hub
<7>[ 10.850155] [3: mdm_helper: 3137] hub 1-0:1.0: individual port power switching
<7>[ 10.850176] [3: mdm_helper: 3137] hub 1-0:1.0: individual port over-current protection
<7>[ 10.850198] [3: mdm_helper: 3137] hub 1-0:1.0: power on to power good time: 20ms
<7>[ 10.850302] [3: mdm_helper: 3137] hub 1-0:1.0: local power source is good
<7>[ 10.850730] [3: mdm_helper: 3137] hub 1-0:1.0: enabling power on all ports
<12>[ 10.851554] [3: mdm_helper: 3137] [ALOG] Testing if port "/dev/ks_hsic_bridge" exists
<12>[ 10.851813] [3: mdm_helper: 3137] [ALOG] Couldn't find "/dev/ks_hsic_bridge", 1 of 5 ... <7>[ 10.976052] [1: khubd: 686] hub 1-0:1.0: state 7 ports 2 chg 0004 evt 0000 <6>[ 10.976151] [1: khubd: 686] hub 1-0:1.0: port 2, status 0501, change 0000, 480 Mb/s <7>[ 11.036044] [1: khubd: 686] s5p-ehci 15510000.usb: port 2 reset complete, port enabled <7>[ 11.036083] [1: khubd: 686] s5p-ehci 15510000.usb: GetStatus port:2 status 001005 0 ACK POWER sig=se0 PE CONNECT <7>[ 11.037397] [4: main: 3171] SELinux: initialized (dev tmpfs, type tmpfs), uses transition SIDs <6>[ 11.096075] [1: khubd: 686] usb 1-2: new high-speed USB device number 2 using s5p-ehci <7>[ 11.127606] [0: khubd: 686] usb 1-2: default language 0x0409 <7>[ 11.128296] [1: khubd: 686] usb 1-2: udev 2, busnum 1, minor = 1 //以下就是到的modem的hsic设备号。 <6>[ 11.128323] [1: khubd: 686] usb 1-2: New USB device found, idVendor=05c6, idProduct=9008 <6>[ 11.128346] [1: khubd: 686] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0 <6>[ 11.128367] [1: khubd: 686] usb 1-2: Product: QHSUSB__BULK <6>[ 11.128390] [1: khubd: 686] usb 1-2: Manufacturer: Qualcomm CDMA Technologies MSM <7>[ 11.129616] [1: khubd: 686] usb 1-2: usb_probe_device <7>[ 11.129651] [1: khubd: 686] usb 1-2: configuration #1 chosen from 1 choice <7>[ 11.130061] [1: khubd: 686] usb 1-2: adding 1-2:1.0 (config #1, interface 0) <7>[ 11.130791] [1: khubd: 686] ks_bridge 1-2:1.0: usb_probe_interface <7>[ 11.130824] [1: khubd: 686] ks_bridge 1-2:1.0: usb_probe_interface - got id <6>[ 11.132053] [2: khubd: 686] usb 1-2: usb dev connected ...
(4) loadSahara()
走下载binary或者下载ramdump的流程,流程都是按照sahara协议走的。
下载binary的流程:
传一个binary的log,和上图的流程一样
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_HELLO
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_HELLO
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_HELLO_RESPONSE
01-01 23:45:52.880 3357 3357 E kickstart: Wrote to /sys/power/wake_lock
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.880 3357 3357 E kickstart: !@ Requested ID 25, file: "/firmware/image/tz.mbn"
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.890 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.900 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.910 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.910 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.940 3470 3470 W System.err: remove failed: ENOENT (No such file or directory) : /data/system/users/userlist.xml.bak
01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_END_IMAGE_TX
01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_DONE
01-01 23:45:52.970 3357 3357 E kickstart: !@ 275556 bytes transferred in 0.084783 seconds
01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_DONE_RESP
01-01 23:45:52.970 3357 3357 E kickstart: Wrote to /sys/power/wake_unlock
01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_HELLO
Memory dump的流程:
下载ramdump的时候log如下,可以看到和上图的流程一样
01-01 23:45:52.850 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-01 23:45:52.850 3357 3357 E kickstart: !@ Received file 'LPM.BIN'
01-01 23:45:52.850 3357 3357 E kickstart: !@ 16384 bytes transferred in 0.003022 seconds
01-01 23:45:52.850 3357 3357 E kickstart: Opening file '/cpdump/MSGRAM.BIN' for writing
01-01 23:45:52.850 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.850 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC428000, length 0x4000
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 16384 bytes
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'MSGRAM.BIN'
01-01 23:45:52.860 3357 3357 E kickstart: !@ 16384 bytes transferred in 0.002020 seconds
01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/DATARAM.BIN' for writing
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC190000, length 0x10000
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 65536 bytes
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'DATARAM.BIN'
01-01 23:45:52.860 3357 3357 E kickstart: !@ 65536 bytes transferred in 0.002780 seconds
01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/CODERAM.BIN' for writing
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC100000, length 0x20000
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 131072 bytes
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'CODERAM.BIN'
01-01 23:45:52.860 3357 3357 E kickstart: !@ 131072 bytes transferred in 0.004864 seconds
01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/OCIMEM.BIN' for writing
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFE800000, length 0x8800
01-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 34816 bytes
01-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-01 23:45:52.870 3357 3357 E kickstart: !@ Received file 'OCIMEM.BIN'
01-01 23:45:52.870 3357 3357 E kickstart: !@ 34816 bytes transferred in 0.001515 seconds
01-01 23:45:52.870 3357 3357 E kickstart: !@ Successfully downloaded files from target
01-01 23:45:52.880 3357 3357 E kickstart: Wrote to /sys/power/wake_unlock
代码添加及修改:
用户层及内核代码,功能流程:
AP,CP通过HSIC连接的方式,一个特点是CP本身没有Flash等固态存储媒介来保存本身的Binary。
所以在每次启动的时候AP都需要通过HSIC来发送MDM的Binary过去。所以通过hsic建立usb连接,并完成下载。efs同步也需要通过hsic建立usb连接。