/src/core/mid.c
C | 1156 lines | 932 code | 113 blank | 111 comment | 196 complexity | 7877b349e65c683d90ec71f62d784b2d MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1
- /*
- * Copyright (C) 2010 ST-Ericsson AS
- * Author: Erwan Bracq / erwan.bracq@stericsson.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * See the NOTICE file distributed with this work for additional
- * information regarding copyright ownership.
- */
- #define PERF_MEASUREMENT 1
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <getopt.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <dlfcn.h>
- #include <time.h>
- #include <assert.h>
- #include <sys/capability.h>
- #include <sys/prctl.h>
- #include <pwd.h>
- #include <grp.h>
- #include <apr_general.h>
- #include <apr_poll.h>
- #include <apr_network_io.h>
- #include "mid.h"
- #include "mid_caif.h"
- #include "mid_conf.h"
- #include "mid_dev.h"
- #include "mid_error.h"
- #include "mid_flash.h"
- #include "mid_gpio.h"
- #include "mid_ipc.h"
- #include "mid_log.h"
- #include "mid_mfa.h"
- #include "mid_power.h"
- #include "mid_settings.h"
- #include "mid_statemachine.h"
- #include "version.h"
- #include "atchannel.h"
- #include "crash_dump.h"
- #include "mid_sys.h"
- #include "mid_fw_upgrade.h"
- #if defined(MOTOROLA_FEATURE)
- #include "private/android_filesystem_config.h"
- struct mot_mid mot_mid_info;
- #endif
- /* Internal mid structure */
- static struct mid mid_info;
- #ifdef DEBUG_TRACE
- struct mid_dbg mid_dbg_info;
- #endif
- /* Modem firmware */
- static union mid_modem_firmware mod_firm;
- /* Primary link device */
- static struct mid_dev prim_dev;
- /* Secondary link device, used only when link swap is specified */
- static struct mid_dev sec_dev;
- /* Configuration file processing */
- static void (*moli_load_cfgfile)(struct mid *mid_info, const char* cfg_file_name);
- /* Default settings for device and modem firmware */
- static void (*moli_default_settings)(struct mid *mid_info);
- static inline void lock_mid_data(void)
- {
- apr_status_t status;
- if (unlikely((status = apr_thread_mutex_lock(mid_info.mutex)) != APR_SUCCESS)) {
- char message[100];
- MLGE("MID: Unable to lock internal mid data mutex: %s.",
- apr_strerror(status, message, sizeof(message)));
- }
- }
- static inline void unlock_mid_data(void)
- {
- apr_status_t status;
- if (unlikely((status = apr_thread_mutex_unlock(mid_info.mutex)) != APR_SUCCESS)) {
- char message[100];
- MLGE("MID: Unable to unlock internal mid data mutex: %s.",
- apr_strerror(status, message, sizeof(message)));
- }
- }
- #define LOCK_MID_DATA lock_mid_data()
- #define UNLOCK_MID_DATA unlock_mid_data()
- int stub_moli_get_crash_dump(struct mid *midinfo, struct mid_dev *dev, const char* dump_directory, const char* dump_directory_header, const char* dump_filename, const char* dump_filename_header, int dump_timestamp, crash_dump_report_t report_type, int max_dump_files)
- {
- UNUSED(midinfo);
- UNUSED(dev);
- UNUSED(dump_directory);
- UNUSED(dump_directory_header);
- UNUSED(dump_timestamp);
- UNUSED(dump_filename);
- UNUSED(dump_filename_header);
- UNUSED(report_type);
- UNUSED(max_dump_files);
- MLGD("STUB: Call stub moli_get_crash_dump function -> this function do nothing.");
- return 0;
- }
- static int stub_moli_configure_security_data(struct mid * mid_info) {
- UNUSED(mid_info);
- MLGD("STUB: Call stub moli_configure_security_data function -> this function do nothing.");
- return 0;
- }
- static void * stub_moli_boot(struct apr_thread_t* thread, void *arg)
- {
- UNUSED(arg);
- UNUSED(thread);
- MLGD("STMACH: MID_LONG_OPS_EVT event set");
- SET_FLAG(mid_info.event, MID_LONG_OPS_EVT);
- mid_info.long_ops_result = MID_FLBOOT_OK;
- MLGD("STUB: Call stub moli_boot function -> this function do nothing.");
- return 0;
- }
- static void stub_moli_default_settings(struct mid *mid_info)
- {
- UNUSED(mid_info);
- MLGD("STUB: Call stub moli_default_settings -> this function do nothing.");
- return;
- }
- static void stub_moli_load_cfgfile(struct mid *mid_info, const char* cfg_file_name)
- {
- UNUSED(mid_info);
- UNUSED(cfg_file_name);
- MLGD("STUB: Call stub moli_load_cfgfile -> this function do nothing.");
- }
- static int stub_moli_fw_upgrade_flash(void)
- {
- return 0;
- }
- static void stub_moli_fw_upgrade_init(int *error_code_p)
- {
- UNUSED(error_code_p);
- return;
- }
- static int stub_moli_fw_upgrade_status(char **status)
- {
- UNUSED(status);
- return 0;
- }
- static int stub_moli_fw_upgrade_img_xfer(struct mid *mid_info)
- {
- UNUSED(mid_info);
- MLGD("STUB: Call stub moli_fw_upgrade_img_xfer -> this function do nothing.");
- return 0;
- }
- static char * stub_moli_fw_upgrade_get_error_str(struct mid *mid_info, int error_code)
- {
- UNUSED(mid_info);
- UNUSED(error_code);
- MLGD("STUB: Call stub moli_fw_upgrade_get_error_str -> this function do nothing.");
- return NULL;
- }
- static void mid_signal_handler(int signal)
- {
- switch (signal) {
- case SIGHUP:
- MLGD("SIG: SIGHUP signal catched. Nothing to do.");
- break;
- case SIGTERM:
- MLGD("SIG: SIGTERM signal catched. MID will shutdown the modem in the next step and exit.");
- /* Clearing Reboot event and start event */
- /* TODO lock - better to replace them by atomic operation if possible */
- mid_info.event &= ~(1<<MID_MODEM_START_EVT);
- mid_info.event &= ~(1<<MID_IPC_RBT_EVT);
- MLGD("STMACH: MID_MODEM_START_EVT event cleared");
- MLGD("STMACH: MID_IPC_RBT_EVT event cleared");
- mid_info.boot_retry_left = 0;
- mid_info.flash_retry_left = 0;
- mid_info.shutdown_retry_left = 0;
- SET_FLAG(mid_info.event, MID_SIG_KILL_EVT);
- MLGD("STMACH: MID_SIG_KILL_EVT event set");
- #if defined(MOTOROLA_FEATURE)
- if (mot_mid_info.recovery_mode)
- mid_mfa_stop(mid_info.mfa, false);
- #endif
- break;
- }
- }
- static int daemonize(char *rdir, char *pidfile)
- {
- pid_t pid, sid;
- #ifndef HAVE_ANDROID_OS
- char pid_str[16];
- int fd;
- #else
- UNUSED(pidfile);
- #endif
- /* Already a daemon */
- if (getppid() == 1) {
- MLGD("MID: MID try to daemonize. But the process is already executed in background.");
- /* Change the file permissions */
- umask(027);
- /* Change to running directory */
- if (chdir(rdir) < 0) {
- MLGW("MID: Failed to change to running dir (specified in mid.conf) \"%s\". MID will run on \"/\" folder.",
- rdir);
- if (chdir("/") < 0)
- MLGE("MID: MID will run from current location, as chdir call failed.");
- }
- /* Open PID file */
- #ifndef HAVE_ANDROID_OS
- if (pidfile) {
- fd = open(pidfile, O_RDWR|O_CREAT, 0640);
- if (fd < 0) {
- MLGE("MID: MID cannot open PID file: %s. Process PID will not be recorded.", pidfile);
- }
- if (lockf(fd, F_TLOCK, 0) < 0) {
- close(fd);
- MLGE("MID: PID file %s lock failure. Process PID record could be corrupted.", pidfile);
- }
- /* Record pid to file - Failure are ignored. */
- sprintf(pid_str, "%d\n", getpid());
- if (fd >= 0) {
- write(fd, pid_str, strlen(pid_str));
- close(fd);
- }
- }
- #endif
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- freopen("/dev/null", "r", stdin);
- freopen("/dev/null", "w", stdout);
- freopen("/dev/null", "w", stderr);
- /* Signal handling
- * Ignore child
- * signal(SIGCHLD, SIG_IGN);
- */
- /* Ignore TTY */
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- /* Catch hangup */
- signal(SIGHUP, mid_signal_handler);
- /* Catch kill */
- signal(SIGTERM, mid_signal_handler);
- return 0;
- }
- /* Fork process */
- pid = fork();
- if (pid < 0) {
- MLGE("MID: Process fork failure. MID will stop as it is critical.");
- return -1;
- }
- if (pid > 0)
- exit(0);
- /* Change the file permissions */
- umask(027);
- /* Change to running directory */
- if (chdir(rdir) < 0) {
- MLGW("MID: Failed to change to running dir (specified in mid.conf) \"%s\". MID will run on \"/\" folder.",
- rdir);
- if (chdir("/") < 0)
- MLGE("MID: MID will run from current location, as chdir call failed.");
- }
- /* Open PID file */
- #ifndef HAVE_ANDROID_OS
- if (pidfile) {
- fd = open(pidfile, O_RDWR|O_CREAT, 0640);
- if (fd < 0) {
- MLGE("MID: MID cannot open PID file: %s. Process PID will not be recorded.", pidfile);
- }
- if (lockf(fd, F_TLOCK, 0) < 0) {
- close(fd);
- MLGE("MID: PID file %s lock failure. Process PID record could be corrupted.", pidfile);
- }
- /* Record pid to file - Failure are ignored. */
- sprintf(pid_str, "%d\n", getpid());
- if (fd >= 0) {
- write(fd, pid_str, strlen(pid_str));
- close(fd);
- }
- }
- #endif
- /* Create a new SID for the child process */
- sid = setsid();
- if (sid < 0) {
- MLGE("MID: Unable to get SID for child process. MID will stop as it is critical.");
- return -1;
- }
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- freopen("/dev/null", "r", stdin);
- freopen("/dev/null", "w", stdout);
- freopen("/dev/null", "w", stderr);
- /* Signal handling
- * Ignore child
- * signal(SIGCHLD, SIG_IGN);
- */
- /* Ignore TTY */
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- /* Catch hangup */
- signal(SIGHUP, mid_signal_handler);
- /* Catch kill */
- signal(SIGTERM, mid_signal_handler);
- return 0;
- }
- static bool get_user_id_by_user_name(const char* user_name, uid_t* uid)
- {
- struct passwd *user;
- if (user_name == NULL) {
- MLGE("No user name supplied");
- return false;
- }
- user = getpwnam(user_name);
- if (!user) {
- MLGE("Failed to find user \"%s\"", user_name);
- return false;
- }
- *uid = user->pw_uid;
- return true;
- }
- static bool get_group_id_by_group_name(const char* group_name, gid_t* gid)
- {
- struct group *group;
- if (group_name == NULL) {
- MLGE("No group name supplied");
- return false;
- }
- group = getgrnam(group_name);
- if (!group) {
- MLGE("Failed to find group \"%s\"", group_name);
- return false;
- }
- *gid = group->gr_gid;
- return true;
- }
- static bool switch_to_user_with_capabilities(const char* run_as_user, const char* run_as_group, const char* capabilities)
- {
- uid_t user_id;
- gid_t group_id;
- cap_t caps_to_set = NULL;
- cap_t end_caps = NULL;
- bool success = false;
- #if defined(MOTOROLA_FEATURE)
- gid_t gid = AID_BLUETOOTH;
- #endif
- MLGD("Switching to user \"%s\", group \"%s\" with capabilities \"%s\"", run_as_user, run_as_group, capabilities);
- if (!get_user_id_by_user_name(run_as_user, &user_id))
- goto exit;
- if (!get_group_id_by_group_name(run_as_group, &group_id))
- goto exit;
- caps_to_set = cap_from_text(capabilities);
- if (caps_to_set == NULL) {
- MLGE("Invalid capabilities string: \"%s\"", capabilities);
- goto exit;
- }
- if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
- MLGE("Failed to set PR_SET_KEEPCAPS flag: %s", strerror(errno));
- goto exit;
- }
- #if defined(MOTOROLA_FEATURE)
- // Set Bluetooth Group as this is needed to re-connect to DBUS
- setgroups(1, &gid);
- #endif
- if (setregid(group_id, group_id) == -1) {
- MLGE("Failed to set group ID of self: %s", strerror(errno));
- goto exit;
- }
- if (setreuid(user_id, user_id) == -1) {
- MLGE("Failed to set user ID of self: %s", strerror(errno));
- goto exit;
- }
- // Now set the caps again, since the effective set was cleared
- MLGD("Setting capabilities to: %s", cap_to_text(caps_to_set, 0));
- if(cap_set_proc(caps_to_set) == -1) {
- MLGE("Failed to set capabilities of self after setuid: %s", strerror(errno));
- goto exit;
- }
- end_caps = cap_get_proc();
- MLGD("End: user=%d, capabilities=\"%s\"", getuid(), cap_to_text(end_caps, 0));
- success = true;
- exit:
- if (caps_to_set) cap_free(caps_to_set);
- if (end_caps) cap_free(end_caps);
- return success;
- }
- static void mid_usage(void)
- {
- printf(
- "Usage: ./mid [options]\n"
- "\n"
- " -h, --help Display this usage information.\n"
- " --cfg CFG_FILE_PATH Load configuration from file. default "
- MID_CFG_FILE "\n"
- "\n"
- );
- }
- #if defined(MOTOROLA_FEATURE)
- static void* mode_checker(void *arg)
- {
- MID_State_t state = STATE_OFF;
- struct mid *mid_info_p = (struct mid *)arg;
- MLGD("mode thread: starting");
- while(mid_info_p) {
- sleep(1);
- if (state == mid_info_p->state)
- continue;
- state = STATE_OFF;
- switch(mid_info_p->state) {
- case STATE_BOOT:
- MLGD("mode thread: testing for ITP mode");
- if (!my_system(&mid_info, mot_mid_info.itp_mode_cmd)) {
- MLGI("mode thread: ITP mode detected");
- state = STATE_BOOT;
- mot_mid_info.dual_boot_mode = 1;
- }
- break;
- case STATE_ON:
- MLGD("mode thread: testing for signaling mode");
- if (!my_system(&mid_info, mot_mid_info.norm_mode_cmd)) {
- MLGI("mode thread: signaling mode detected");
- state = STATE_ON;
- }
- break;
- default:
- break;
- }
- }
- MLGD("mode thread: exiting");
- pthread_exit(NULL);
- return(NULL);
- }
- #endif
- #define NEXT_STATE(_state_) if (_state_!= MID_SAME_STATE) Self_p->state=_state_
- int main(int argc, char *argv[])
- {
- size_t i = 0;
- int ipc_event = 0;
- time_t time_entered_state;
- /* Configuration file */
- #ifdef MID_PARSE_KER_CMDLINE
- char *kernel_cmd_line;
- #define MAX_STR_SIZE 65534
- char garbage[MAX_STR_SIZE + 1];
- int cmd_line_sz = 0;
- int read_line_sz;
- int fproc;
- char* cfg_filename = NULL;
- char* pindex = NULL;
- #endif
- /* Return value */
- int res = 0;
- /* Dynamic library handle */
- char *dl_error = NULL;
- char *dl_name = NULL;
- /* Command line parameters */
- int option_index = 0;
- int cmd_args;
- /* Indicates if a kernel configuration parameter is available */
- int kernel_cfg = 0;
- enum {
- CFG_FILE = 1
- #if defined(MOTOROLA_FEATURE)
- , FIRM_DIR = 2
- #endif
- };
- struct option long_options[] = {
- { "help", no_argument, NULL, 'h' },
- { "cfg", required_argument, NULL, CFG_FILE },
- #if defined(MOTOROLA_FEATURE)
- { "firm_dir", required_argument, NULL, FIRM_DIR },
- #endif
- { 0, 0, 0, 0 }
- };
- char* cfgfile;
- struct mid_config* config;
- apr_status_t apr_status;
- #if defined(MOTOROLA_FEATURE)
- pthread_t mode_checker_td;
- /* Indicates that we are reconnecting to DBUS */
- int reconnect =0;
- #endif
- if ((apr_status = apr_app_initialize(&argc, (char const* const**)&argv, NULL)) != APR_SUCCESS) {
- char message[100];
- MLGE("MID: Failed to initialize Apache Portable Runtime: %s. This critical MID will exit now.\n",
- apr_strerror(apr_status, message, sizeof(message)));
- exit(EXIT_FAILURE);
- }
- opterr = 0;
- optind = 0;
- memset(&mid_info, 0, sizeof(struct mid));
- memset(&mod_firm, 0, sizeof(union mid_modem_firmware));
- memset(&prim_dev, 0, sizeof(struct mid_dev));
- memset(&sec_dev, 0, sizeof(struct mid_dev));
- config = calloc(1, sizeof(struct mid_config));
- moli_load_cfgfile = &stub_moli_load_cfgfile;
- moli_default_settings = &stub_moli_default_settings;
- mid_info.moli_configure_security_data = &stub_moli_configure_security_data;
- mid_info.moli_boot = &stub_moli_boot;
- mid_info.moli_get_crash_dump = &stub_moli_get_crash_dump;
- mid_info.moli_fw_upgrade_get_error_str = &stub_moli_fw_upgrade_get_error_str;
- mid_info.moli_fw_upgrade_flash = &stub_moli_fw_upgrade_flash;
- mid_info.moli_fw_upgrade_init = &stub_moli_fw_upgrade_init;
- mid_info.moli_fw_upgrade_status = &stub_moli_fw_upgrade_status;
- mid_info.moli_fw_upgrade_img_xfer = &stub_moli_fw_upgrade_img_xfer;
- mid_info.config = config;
- #ifdef DEBUG_TRACE
- mid_dbg_info.log_fd = NULL;
- #endif
- mid_info.pid_fd = NULL;
- mid_info.cfg_fd = NULL;
- mid_info.power_on_release = 0;
- #if defined(MOTOROLA_FEATURE)
- mot_mid_info.recovery_mode = 0;
- #endif
- mid_info.pool=NULL;
- if((apr_status = apr_pool_create(&mid_info.pool, NULL)) != APR_SUCCESS) {
- char message[100];
- MLGE("MID: Failed to create memory pool: %s. MID will exit now.\n",
- apr_strerror(apr_status, message, sizeof(message)));
- goto error;
- }
- /* Settings order 1) default (include files) 2) configuration file
- * 3) command line arguments 4) kernel command line */
- /* Default settings initialization */
- /* Daemon working dir - Firmware dir */
- /* Modem IDs */
- mid_info.modem_build_string = MODEM_BUILD_STRING;
- config->sec_data_file = NULL;
- #ifdef DEBUG_TRACE
- mid_dbg_info.mid_dbg_level = MID_DBG_DEFAULT_LEVEL;
- mid_dbg_info.logfile = MID_LOG_FILE;
- #endif
- cfgfile = MID_CFG_FILE;
- /* Set up default path for initial and optional secondary link */
- prim_dev.name = PRI_DEFAULT_PATH;
- sec_dev.name = SEC_DEFAULT_PATH;
- /* Default values for modem firmware, and link defined
- * in specific moli implematation
- */
- config->prim_dev_config = &prim_dev;
- config->sec_dev_config = &sec_dev;
- config->mod_firm_config = &mod_firm;
- MLGD("MID: ST-Ericsson Modem Init Daemon started: %s.", VERSION);
- mid_info.at_chnl_fd = -1;
- if (unlikely((apr_status = apr_thread_mutex_create(&mid_info.mutex, 0, mid_info.pool)) != APR_SUCCESS)) {
- char message[100];
- MLGE("MID: Unable to init internal mid data mutex: %s. Problems are forecasted when mutex will be used.\n",
- apr_strerror(apr_status, message, sizeof(message)));
- }
- mid_info.dl_handle = NULL;
- #ifdef PERF_MEASUREMENT
- if (clock_gettime(CLOCK_MONOTONIC, &mid_info.midStarted))
- MLGW("TIME: Error getting monotonic clock. Following time report should be considered as wrong.");
- float used_time;
- used_time = (float)(mid_info.midStarted.tv_sec+(float)(mid_info.midStarted.tv_nsec/1000000000));
- MLGD("TIME: Started (MONOTONIC CLOCK - clock origin is unspecified) at: %4.2f sec.",used_time);
- #endif
- #ifdef MID_PARSE_KER_CMDLINE
- /* Read /proc/cmdline */
- fproc = open("/proc/cmdline", O_RDONLY);
- if (fproc == -1) {
- kernel_cmd_line = NULL;
- MLGD("MID: No kernel command line accessible from /proc/cmdline.");
- }
- else {
- /* Count kernel cmd line size */
- while ((read_line_sz = read(fproc, garbage, MAX_STR_SIZE)) != 0) {
- if (read_line_sz == -1) {
- MLGE("MID: Unable to read kernel command line: %s.", strerror(errno));
- kernel_cmd_line = NULL;
- goto ker_cmdline_proc_close;
- }
- cmd_line_sz += read_line_sz;
- }
- /* Reset cmd line pointer */
- if (lseek(fproc, 0, SEEK_SET) == -1) {
- MLGE("MID: Unable to lseek position in /proc/cmdline.");
- kernel_cmd_line = NULL;
- goto ker_cmdline_proc_close;
- }
- /* Empty cmd line ? */
- if (cmd_line_sz == 0) {
- MLGE("MID: /proc/cmdline string is empty.");
- kernel_cmd_line = NULL;
- goto ker_cmdline_proc_close;
- }
- /* Add room for end of line while allocating */
- kernel_cmd_line = malloc((cmd_line_sz + 1) * sizeof(char));
- if (!kernel_cmd_line) {
- MLGE("MID: Unable to malloc cmd_line string.");
- kernel_cmd_line = NULL;
- goto ker_cmdline_proc_close;
- }
- if (read(fproc, kernel_cmd_line, cmd_line_sz) == -1) {
- MLGE("MID: Unable to read /proc/cmdline.");
- free(kernel_cmd_line);
- kernel_cmd_line = NULL;
- goto ker_cmdline_proc_close;
- }
- /* Find LF and trucate the string */
- pindex = index(kernel_cmd_line, 0x0A);
- if (pindex != NULL)
- *pindex = '\0';
- kernel_cmd_line[cmd_line_sz] = '\0';
- MLGD("MID: Success to read /proc/cmdline, get: %s.", kernel_cmd_line);
- }
- ker_cmdline_proc_close:
- close(fproc);
- /* Parse /proc/cmdline, check kernel command line parameters for a configuration file */
- if ((kernel_cmd_line != NULL) &&
- ((cfg_filename = strstr(kernel_cmd_line, CMD_PARM_NAME)) != NULL)) {
- /* point on '=' character */
- cfg_filename = index(cfg_filename, 0x3d);
- if (cfg_filename == NULL) {
- MLGE("MID: Kernel command line parse error.");
- free(kernel_cmd_line);
- goto ker_cmdline_fallback;
- }
- cfg_filename++;
- /* point on first white space */
- pindex = index(cfg_filename, 0x20);
- if (pindex != NULL)
- *pindex = '\0';
- /* If no white space, end of string is already marked */
- cfgfile=strdup(cfg_filename);
- MLGD("MID: Found a configuration file name on kernel command line parameters: %s.", cfgfile);
- kernel_cfg = 1;
- free(kernel_cmd_line);
- } else {
- ker_cmdline_fallback:
- MLGD("MID: No %s option on kernel command line. Try to check for mid --cfg option.", CMD_PARM_NAME);
- kernel_cfg = 0;
- }
- #endif
- /* Parse command line */
- while ((cmd_args = getopt_long_only(argc, argv, "h", long_options,
- &option_index)) != -1) {
- switch (cmd_args) {
- case 'h':
- mid_usage();
- exit(EXIT_SUCCESS);
- case CFG_FILE:
- if (!kernel_cfg)
- cfgfile = strdup(optarg);
- break;
- #if defined(MOTOROLA_FEATURE)
- case FIRM_DIR:
- /* Processed later */
- break;
- #endif
- default:
- MLGE("MID: Invalid option / parameter: %s. Will exit now.", argv[optind]);
- mid_usage();
- exit(EXIT_FAILURE);
- }
- }
- if (argc != optind) {
- int i;
- MLGE("MID: Too much parameter on command line: ");
- for (i = optind; i < argc; i++)
- MLGE("%s", argv[i]);
- MLGE("MID: Will exit now due command line parameters error.");
- mid_usage();
- exit(EXIT_FAILURE);
- }
- if (!mid_conf_load(config, cfgfile)) {
- goto error;
- }
- /* Shared library loading */
- if (strcmp(config->modem_arch, "OSMIUM") == 0) {
- prim_dev.flb_alloc_usb_unit = NULL;
- sec_dev.flb_alloc_usb_unit = NULL;
- dl_name = MID_MOLIU33x_NAME;
- }
- else if (strcmp(config->modem_arch, "HASSIUM") == 0)
- dl_name = MID_MOLIU5xx_NAME;
- else if (strcmp(config->modem_arch, "THORIUM") == 0) {
- prim_dev.flb_alloc_usb_unit = NULL;
- sec_dev.flb_alloc_usb_unit = NULL;
- dl_name = MID_MOLIU5xx_NAME;
- }
- if (dl_name != NULL) {
- MLGD("LIB: Loading %s library:", dl_name);
- mid_info.dl_handle = dlopen(dl_name, RTLD_LAZY);
- if (!mid_info.dl_handle) {
- dl_error = (char *)dlerror();
- MLGE("LIB: error: %s. MID will exit now.", dl_error);
- goto error;
- }
- moli_load_cfgfile = dlsym(mid_info.dl_handle, "moli_load_cfgfile");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_check_cfgfile symbol loaded.");
- moli_default_settings = dlsym(mid_info.dl_handle, "moli_default_settings");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_default_settings symbol loaded.");
- if (config->initial_enable_bootldr) {
- mid_info.moli_configure_security_data = dlsym(mid_info.dl_handle, "moli_configure_security_data");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_configure_security_data symbol loaded.");
- mid_info.moli_boot = dlsym(mid_info.dl_handle, "moli_boot");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_boot symbol loaded.");
- }
- if (strncmp(dl_name, MID_MOLIU5xx_NAME, strlen(MID_MOLIU5xx_NAME)) == 0) {
- if (config->initial_enable_bootldr) {
- prim_dev.flb_alloc_usb_unit = dlsym(mid_info.dl_handle, "flb_alloc_usb_unit");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: flb_alloc_usb_unit symbol loaded.");
- sec_dev.flb_alloc_usb_unit = dlsym(mid_info.dl_handle, "flb_alloc_usb_unit");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: flb_alloc_usb_unit symbol loaded.");
- } else {
- mid_info.moli_fw_upgrade_get_error_str = dlsym(mid_info.dl_handle, "moli_fw_upgrade_get_error_str");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_fw_upgrade_get_error_str symbol loaded.");
- mid_info.moli_fw_upgrade_flash = dlsym(mid_info.dl_handle,"moli_fw_upgrade_flash");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_fw_upgrade_flash symbol loaded.");
- mid_info.moli_fw_upgrade_init = dlsym(mid_info.dl_handle,"moli_fw_upgrade_init");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_fw_upgrade_init symbol loaded.");
- mid_info.moli_fw_upgrade_status = dlsym(mid_info.dl_handle,"moli_fw_upgrade_status");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_fw_upgrade_status symbol loaded.");
- mid_info.moli_fw_upgrade_img_xfer = dlsym(mid_info.dl_handle,"moli_fw_upgrade_img_xfer");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_fw_upgrade_img_xfer symbol loaded.");
- }
- mid_info.moli_get_crash_dump = dlsym(mid_info.dl_handle, "moli_get_crash_dump");
- if ((dl_error = (char *)dlerror()) != NULL)
- goto error;
- MLGD("LIB: moli_get_crash_dump symbol loaded.");
- }
- MLGD("LIB: %s library loaded successfully.", dl_name);
- }
- moli_default_settings(&mid_info);
- moli_load_cfgfile(&mid_info, cfgfile);
- #if defined(MOTOROLA_FEATURE)
- /* Parse command line for --firm_dir, which overrides configuration file value for initial_rdir */
- optind = 0;
- while ((cmd_args = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) {
- switch (cmd_args) {
- case FIRM_DIR:
- config->initial_rdir = malloc((strlen(optarg) + 1) * sizeof(char));
- if (config->initial_rdir == NULL) {
- MLGE("Unable to allocate internal mid initial_rdir: %s. Will exit now.", strerror(errno));
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_FAILURE);
- }
- strncpy(config->initial_rdir, optarg, strlen(optarg));
- config->initial_rdir[strlen(optarg)] = '\0';
- /* --firm_dir option is only used in recovery mode for Motorola devices. */
- /* Use this as an indication to handle specific needs in recovery mode. */
- MLGE("Using config->initial_rdir: '%s' for recovery mode", config->initial_rdir);
- mot_mid_info.recovery_mode = 1;
- config->mod_prefl_cmd = mot_mid_info.recovery_mod_prefl_cmd;
- break;
- }
- }
- if (argc != optind) {
- int i;
- MLGE("Invalid parameter: ");
- for (i = optind; i < argc; i++)
- MLGE("%s. Will exit now.", argv[i]);
- mid_usage();
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_FAILURE);
- }
- #endif /* MOTOROLA_FEATURE */
- mid_info.mfa = mid_mfa_init(&mid_info, mid_info.config, mid_info.pool);
- /* One-shot configuration */
- (void)my_system(&mid_info, mid_info.config->mod_init_cmd);
- if (config->daemonize) {
- if (daemonize(config->initial_rdir, config->pidfile)) {
- MLGE("MID: Daemonization error. Will exit now.");
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_FAILURE);
- }
- } else {
- /* Change to running directory */
- if (chdir(config->initial_rdir) < 0) {
- MLGW("MID: Failed to change to running dir \"%s\". MID will run on \"/\" folder.",
- config->initial_rdir);
- if (chdir("/") < 0)
- MLGE("MID: MID will run from current location.");
- }
- /* Catch hangup */
- signal(SIGHUP, mid_signal_handler);
- /* Catch kill */
- signal(SIGTERM, mid_signal_handler);
- }
- #ifndef HAVE_ANDROID_OS
- #ifdef DEBUG_TRACE
- if (mid_dbg_info.logfile && mid_dbg_info.log_to_file) {
- mid_dbg_info.log_fd = fopen(mid_dbg_info.logfile, "w");
- if (mid_dbg_info.log_fd == NULL) {
- MLGE("MID: Log file open failure: %s, %s. Will exit now.", mid_dbg_info.logfile, strerror(errno));
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_FAILURE);
- }
- }
- #endif
- #endif
- mid_info.mid_power = mid_power_init();
- if (mid_info.mid_power == NULL) {
- MLGE("Failed to initialize power subsystem");
- goto error;
- }
- MLGD("MID: Modem_ARCH:%d %s | Modem_Build:(pending...)", mid_info.config->modem_arch_id, mid_info.config->modem_arch);
- /* Remove end "/" in directory name (if any) */
- cleanupdirname(&mid_info);
- /* Ensure service gpio is released */
- mid_enable_gpio_service_safe_mode(&mid_info);
- /* Request GPIOs */
- mid_info.gpios = mid_gpio_init(mid_info.config->mid_gpios, mid_info.config->gpio_base_path, mid_info.config->gpio_ctrl, mid_info.config->gpio_no_aclow, mid_info.config->gpio_no_xport, mid_info.config->gpio_no_dir);
- if (mid_info.gpios == NULL) {
- MLGE("GPIO: Unable to init GPIOs. This is critical, MID will exit now.");
- state_all_evt_sig_kill(&mid_info);
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- goto error;
- }
- /* Connect IPC */
- res = -EMID;
- MLGD("DBUS: Connecting to DBUS... (looping to connect)");
- while (res != 0) {
- #if defined(MOTOROLA_FEATURE)
- res = ipc_medium_connect(&mid_info,reconnect);
- #else
- res = ipc_medium_connect(&mid_info);
- #endif
- if (res != 0)
- usleep(MID_IPC_OPS_DELAY);
- };
- MLGD("DBUS: Connected to DBUS.");
- #if defined(MOTOROLA_FEATURE)
- if (mot_mid_info.recovery_mode == 0) {
- #endif
- // Now that all modules got their chance to initialize, we can drop
- // all privileges not needed during normal operations.
- if (!switch_to_user_with_capabilities("system", "radio", "CAP_SYS_MODULE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_BOOT=ep")) {
- MLGE("Failed to drop privileges");
- goto error;
- }
- #if defined(MOTOROLA_FEATURE)
- }
- #endif
- #if defined(MOTOROLA_FEATURE)
- if (strncmp("service", mid_info.config->runtime_mode, strlen("service")) != 0) {
- #endif
- /* Initial startup trig a modem start event */
- MLGD("STMACH: MID_MODEM_START_EVT event set");
- SET_FLAG(mid_info.event, MID_MODEM_START_EVT);
- #if defined(MOTOROLA_FEATURE)
- }
- #endif
- mid_disable_gpio_out_safe_mode(&mid_info);
- /* Ensure modem is off */
- /* TODO check if an AT channel can be openned to shutdown */
- shutdown_modem(&mid_info);
- /* Set all ios in safe mode */
- mid_enable_io_safe_mode(&mid_info);
- /* Initial state */
- mid_info.state = STATE_OFF;
- time_entered_state = time(NULL);
- mid_info.flash_retry_left = mid_info.config->flash_retry;
- mid_info.boot_retry_left = mid_info.config->boot_retry;
- mid_info.shutdown_retry_left = mid_info.config->shutdown_retry;
- mid_info.boot_failed = 0;
- mid_info.flash_failed = 0;
- mid_info.modem_warm_start = 0;
- mid_info.moli_fw_upgrade_init(&mid_info.fw_upgr_last_error);
- #if defined(MOTOROLA_FEATURE)
- res = pthread_create(&mode_checker_td, NULL, &mode_checker, (void*)&mid_info);
- #endif
- /* Poll filedescriptor */
- for (;;) {
- const size_t guessed_num_fds = ipc_get_num_fds() + 3;
- apr_pollfd_t fds[guessed_num_fds];
- size_t num_fds;
- size_t num_ipc_fds;
- apr_file_t* rst2_fd;
- apr_file_t* pwrrstin_fd;
- bool has_mfa_fd;
- apr_status_t status;
- apr_int32_t num_signalled;
- char message[100];
- LOCK_MID_DATA;
- num_fds = num_ipc_fds = ipc_get_fds(fds, guessed_num_fds - 3);
- rst2_fd = mid_gpio_get_fd(mid_info.gpios, GPIO_ID_RESOUT2);
- pwrrstin_fd = mid_gpio_get_fd(mid_info.gpios, GPIO_ID_PWRRSTIN);
-
- if (rst2_fd != NULL) {
- fds[num_fds].desc_type = APR_POLL_FILE;
- fds[num_fds].desc.f = rst2_fd;
- fds[num_fds].reqevents = APR_POLLPRI;
- fds[num_fds].rtnevents = 0;
- num_fds++;
- }
- if (pwrrstin_fd != NULL) {
- fds[num_fds].desc_type = APR_POLL_FILE;
- fds[num_fds].desc.f = pwrrstin_fd;
- fds[num_fds].reqevents = APR_POLLPRI;
- fds[num_fds].rtnevents = 0;
- num_fds++;
- }
- if ((has_mfa_fd = mid_mfa_get_fd(mid_info.mfa, &fds[num_fds]))) {
- num_fds++;
- }
- UNLOCK_MID_DATA;
- /* If we're in a none transient state we allow sleep */
- if (!mid_statemachine_get_current_timeout(&mid_info))
- if (!mid_permit_suspend(mid_info.mid_power))
- MLGE("POW: Unable to allow system to suspend. MID will continue anyway but system power management may be disturbed.");
- /* Poll */
- status = apr_poll(fds, num_fds, &num_signalled, MID_POLL_LAT * 1000000);
- switch(status) {
- case APR_EINTR:
- MLGI("MID: Received interrupt condition while polling: %s. MID will process events that are set.", apr_strerror(status, message, sizeof(message)));
- break;
- case APR_TIMEUP:
- /* Here we check if we have a timeout on the POLL, that we don't have */
- /* any pending event, we are in a transient state and that we exceeded */
- /* time in the current state. This indicates that we are in some deadlock */
- /* and that we will try to recover. */
- if ((time(NULL) > time_entered_state + mid_statemachine_get_current_timeout(&mid_info)) &&
- mid_statemachine_get_current_timeout(&mid_info) > 0) {
- MLGE("MID: MID in state (%s) and maximum time in this state is exceeded.", mid_statemachine_get_name_of_current_state(&mid_info));
- LOCK_MID_DATA;
- MLGE("STMACH: MID_TIMEOUT_EVT event set.");
- SET_FLAG(mid_info.event, MID_TIMEOUT_EVT);
- UNLOCK_MID_DATA;
- }
- break;
- case APR_SUCCESS:
- MLGD("MID: Received event(s) on monitored file descriptor(s). MID will check event(s) source(s)");
- for (i = 0; i < num_ipc_fds; i++) {
- if (fds[i].rtnevents) {
- #if defined(MOTOROLA_FEATURE)
- if (fds[i].rtnevents & APR_POLLHUP)
- {
- MLGD("MID: DBUS HANG UP event received");
- // Clean up and Re-connect to DBUS
- ipc_medium_cleanup();
- // Wait for a second and then re-connect to DBUS
- usleep(MID_IPC_OPS_DELAY);
- usleep(MID_IPC_OPS_DELAY);
- /* Re-Connect IPC */
- reconnect = 1;
- res = -EMID;
- MLGD("DBUS: Re-Connecting to DBUS... (looping to connect)");
- while (res != 0) {
- res = ipc_medium_connect(&mid_info,reconnect);
- if (res != 0)
- usleep(MID_IPC_OPS_DELAY);
- }
- ipc_event = 0;
- }
- else
- #endif
- {
- MLGD("MID: DBUS activity received.");
- ipc_notify_for_event(i, fds[i].rtnevents);
- ipc_event = 1;
- }
- }
- }
- if (ipc_event) {
- if (!mid_prevent_suspend(mid_info.mid_power))
- MLGE("POW: Unable to prevent system to suspend. MID will continue anyway but power management may disturbe MID operation.");
- ipc_process_event();
- ipc_event = 0;
- }
- if (rst2_fd != NULL) {
- if (fds[i].rtnevents & APR_POLLPRI) {
- int status;
- MLGD("MID: GPIO RESOUT2 activity received.");
- status = mid_gpio_get_value(mid_info.gpios, GPIO_ID_RESOUT2);
- LOCK_MID_DATA;
- MLGD("STMACH: MID_GPIO_RST2_EVT event set.");
- SET_FLAG(mid_info.event, MID_GPIO_RST2_EVT);
- UNLOCK_MID_DATA;
- MLGD("GPIO: New GPIO RESOUT2 logical level (1 active, 0 inactive) %d.", status);
- }
- i++;
- }
- if (pwrrstin_fd != NULL) {
- if (fds[i].rtnevents & APR_POLLPRI) {
- int status;
- MLGD("MID: GPIO PWRRSTIN activity received.");
- status = mid_gpio_get_value(mid_info.gpios, GPIO_ID_PWRRSTIN);
- LOCK_MID_DATA;
- MLGD("STMACH: MID_GPIO_PRST_EVT event set.");
- SET_FLAG(mid_info.event, MID_GPIO_PRST_EVT);
- UNLOCK_MID_DATA;
- MLGD("GPIO: New GPIO PWRRSTIN logical level (1 active, 0 inactive) %d.", status);
- }
- i++;
- }
- if (has_mfa_fd) {
- mid_mfa_receive_message(&fds[i], &mid_info, mid_info.mfa);
- i++;
- }
- break;
- default:
- MLGE("MID: Poll listening problem: %s, This error is ignored and MID will continue anyway. Unexpected various error could occur from now.", apr_strerror(status, message, sizeof(message)));
- break;
- }
- /* Process all events */
- mid_statemachine_process_all_events(&mid_info, &time_entered_state);
- }
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_SUCCESS);
- error:
- MLGE("MID: MID will exit due to earlier error");
- if (mid_info.dl_handle != NULL)
- dlclose(mid_info.dl_handle);
- exit(EXIT_FAILURE);
- }