diff options
-rw-r--r-- | samsung-ipc/device/aries/aries_ipc.c | 944 | ||||
-rw-r--r-- | samsung-ipc/device/aries/aries_ipc.h (renamed from samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.h) | 42 | ||||
-rw-r--r-- | samsung-ipc/device/aries/onedram.h | 30 | ||||
-rw-r--r-- | samsung-ipc/device/aries/phonet.h | 62 | ||||
-rw-r--r-- | samsung-ipc/device/aries/sipc4.h | 256 | ||||
-rw-r--r-- | samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.c | 644 | ||||
-rw-r--r-- | samsung-ipc/device/galaxysmtd/galaxysmtd_modem_ctl.h | 44 | ||||
-rw-r--r-- | samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.c | 356 | ||||
-rw-r--r-- | samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.h | 41 |
9 files changed, 1313 insertions, 1106 deletions
diff --git a/samsung-ipc/device/aries/aries_ipc.c b/samsung-ipc/device/aries/aries_ipc.c new file mode 100644 index 0000000..92ab454 --- /dev/null +++ b/samsung-ipc/device/aries/aries_ipc.c @@ -0,0 +1,944 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> + * Joerie de Gram <j.de.gram@gmail.com> + * Simon Busch <morphis@gravedo.de> + * Igor Almeida <igor.contato@gmail.com> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <stdbool.h> +#include <termios.h> +#include <fcntl.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <linux/netlink.h> +#include <net/if.h> +#include <asm/types.h> +#include <mtd/mtd-abi.h> +#include <assert.h> + +#include <radio.h> + +#include "aries_ipc.h" +#include "ipc_private.h" +#include "sipc4.h" +#include "onedram.h" +#include "phonet.h" + +int phonet_iface_ifdown(void) +{ + struct ifreq ifr; + int fd; + int rc; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ); + + fd = socket(AF_PHONET, SOCK_DGRAM, 0); + + rc = ioctl(fd, SIOCGIFFLAGS, &ifr); + if(rc < 0) + return -1; + + ifr.ifr_flags = (ifr.ifr_flags & (~IFF_UP)); + + rc = ioctl(fd, SIOCSIFFLAGS, &ifr); + if(rc < 0) + return -1; + + close(fd); + + return 0; +} + +int phonet_iface_ifup(void) +{ + struct ifreq ifr; + int fd; + int rc; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ); + + fd = socket(AF_PHONET, SOCK_DGRAM, 0); + + rc = ioctl(fd, SIOCGIFFLAGS, &ifr); + if(rc < 0) + return -1; + + ifr.ifr_flags |= IFF_UP; + + rc = ioctl(fd, SIOCSIFFLAGS, &ifr); + if(rc < 0) + return -1; + + close(fd); + + return 0; +} + +int aries_modem_bootstrap(struct ipc_client *client) +{ + int s3c2410_serial3_fd = -1; + int onedram_fd = -1; + + /* Control variables. */ + int boot_tries_count = 0; + int rc = 0; + + /* Boot variables */ + uint8_t *radio_img_p = NULL; + uint32_t onedram_data = 0; + uint8_t bootcore_version = 0; + uint8_t info_size = 0; + uint8_t crc_byte = 0; + int block_size = 0; + + /* s3c2410 serial setup variables. */ + struct termios termios; + int serial; + + /* fds maniplation variables */ + struct timeval timeout; + fd_set fds; + + /* nv_data variables */ + void *nv_data_p; + void *onedram_p; + + /* General purpose variables. */ + uint8_t data; + uint16_t data_16; + uint8_t *data_p; + int i; + + ipc_client_log(client, "aries_ipc_bootstrap: enter"); + +boot_loop_start: + if(boot_tries_count > 5) + { + ipc_client_log(client, "aries_ipc_bootstrap: boot has failed too many times."); + goto error; + } + + /* Read the radio.img image. */ + ipc_client_log(client, "aries_ipc_bootstrap: reading radio image"); + radio_img_p = ipc_mtd_read(client, "/dev/block/bml12", RADIO_IMG_READ_SIZE, RADIO_IMG_READ_SIZE); + ipc_client_log(client, "aries_ipc_bootstrap: radio image read"); + + ipc_client_log(client, "aries_ipc_bootstrap: open onedram"); + onedram_fd=open("/dev/onedram", O_RDWR); + if(onedram_fd < 0) + goto error_loop; + + /* Reset the modem before init to send the first part of modem.img. */ + ipc_client_log(client, "aries_ipc_bootstrap: turning %s iface down", PHONET_IFACE); + rc = phonet_iface_ifdown(); + if(rc < 0) + goto error; + + ipc_client_power_off(client); + ipc_client_log(client, "aries_ipc_bootstrap: sent PHONE \"off\" command"); + usleep(1000); + + ipc_client_power_on(client); + ipc_client_log(client, "aries_ipc_bootstrap: sent PHONE \"on\" command"); + usleep(200000); + + ipc_client_log(client, "aries_ipc_bootstrap: open s3c2410_serial3"); + s3c2410_serial3_fd=open("/dev/s3c2410_serial3", O_RDWR); + if(s3c2410_serial3_fd < 0) + goto error_loop; + + /* Setup the s3c2410 serial. */ + ipc_client_log(client, "aries_ipc_bootstrap: setup s3c2410_serial3"); + tcgetattr(s3c2410_serial3_fd, &termios); + + cfmakeraw(&termios); + cfsetispeed(&termios, B115200); + cfsetospeed(&termios, B115200); + + tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); + + /* Send 'AT' in ASCII. */ + ipc_client_log(client, "aries_ipc_bootstrap: sending AT in ASCII"); + for(i=0 ; i < 20 ; i++) + { + rc = write(s3c2410_serial3_fd, "AT", 2); + usleep(50000); + } + ipc_client_log(client, "aries_ipc_bootstrap: sending AT in ASCII done"); + + usleep(50000); //FIXME + + /* Write the first part of modem.img. */ + FD_ZERO(&fds); + FD_SET(s3c2410_serial3_fd, &fds); + + timeout.tv_sec=5; + timeout.tv_usec=0; + + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + /* Get and check bootcore version. */ + read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version)); + ipc_client_log(client, "aries_ipc_bootstrap: got bootcore version: 0x%x", bootcore_version); + + if(bootcore_version != BOOTCORE_VERSION) + goto error_loop; + + timeout.tv_sec=5; + timeout.tv_usec=0; + + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + /* Get info_size. */ + read(s3c2410_serial3_fd, &info_size, sizeof(info_size)); + ipc_client_log(client, "aries_ipc_bootstrap: got info_size: 0x%x", info_size); + + timeout.tv_sec=5; + timeout.tv_usec=0; + + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + /* Send PSI magic. */ + data=PSI_MAGIC; + write(s3c2410_serial3_fd, &data, sizeof(data)); + ipc_client_log(client, "aries_ipc_bootstrap: sent PSI_MAGIC (0x%x)", PSI_MAGIC); + + /* Send PSI data len. */ + data_16=PSI_DATA_LEN; + data_p=(uint8_t *)&data_16; + + for(i=0 ; i < 2 ; i++) + { + write(s3c2410_serial3_fd, data_p, 1); + data_p++; + } + ipc_client_log(client, "aries_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)", PSI_DATA_LEN); + + timeout.tv_sec=5; + timeout.tv_usec=0; + + data_p=radio_img_p; + + ipc_client_log(client, "aries_ipc_bootstrap: sending the first part of radio.img"); + + for(i=0 ; i < PSI_DATA_LEN ; i++) + { + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + write(s3c2410_serial3_fd, data_p, 1); + crc_byte=crc_byte ^ *data_p; + + data_p++; + } + + ipc_client_log(client, "aries_ipc_bootstrap: first part of radio.img sent; crc_byte is 0x%x", crc_byte); + + timeout.tv_sec=5; + timeout.tv_usec=0; + + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte)); + + ipc_client_log(client, "aries_ipc_bootstrap: crc_byte sent"); + + data = 0; + for(i = 0 ; data != 0x01 ; i++) + { + timeout.tv_sec=5; + timeout.tv_usec=0; + + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + read(s3c2410_serial3_fd, &data, sizeof(data)); + + if(i > 50) + { + ipc_client_log(client, "aries_ipc_bootstrap: fairly too much attempts to get ACK"); + goto error_loop; + } + } + + ipc_client_log(client, "aries_ipc_bootstrap: close s3c2410_serial3"); + close(s3c2410_serial3_fd); + + FD_ZERO(&fds); + FD_SET(onedram_fd, &fds); + + timeout.tv_sec=5; + timeout.tv_usec=0; + + ipc_client_log(client, "aries_ipc_bootstrap: wait for 0x12341234 from onedram"); + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + read(onedram_fd, &onedram_data, sizeof(onedram_data)); + + if(onedram_data != ONEDRAM_INIT_READ) + { + ipc_client_log(client, "aries_ipc_bootstrap: wrong onedram init magic (got 0x%04x)", onedram_data); + goto error_loop; + } + + ipc_client_log(client, "aries_ipc_bootstrap: got 0x%04x", onedram_data); + + ipc_client_log(client, "aries_ipc_bootstrap: writing the rest of modem.img to onedram."); + + /* Pointer to the remaining part of radio.img. */ + data_p=radio_img_p + PSI_DATA_LEN; + + onedram_p = mmap(NULL, ONENAND_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, onedram_fd, 0); + + if(onedram_p == NULL || onedram_p < 0 || onedram_p == 0xffffffff) + { + ipc_client_log(client, "aries_ipc_bootstrap: could not map onedram to memory"); + goto error_loop; + } + + // it sometimes hangs here + + memcpy(onedram_p, data_p, RADIO_IMG_READ_SIZE - PSI_DATA_LEN); + + free(radio_img_p); + + /* nv_data part. */ + + /* Check if all the nv_data files are ok. */ + nv_data_check(client); + + /* Check if the MD5 is ok. */ + nv_data_md5_check(client); + + /* Write nv_data.bin to modem_ctl. */ + ipc_client_log(client, "aries_ipc_bootstrap: write nv_data to onedram"); + + nv_data_p = ipc_file_read(client, "/efs/nv_data.bin", NV_DATA_SIZE, 1024); + if (nv_data_p == NULL) + goto error; + data_p = nv_data_p; + + memcpy(onedram_p + RADIO_IMG_MAX_SIZE, data_p, NV_DATA_SIZE); + + free(nv_data_p); + + munmap(onedram_p, ONENAND_MAP_SIZE); + + if(ioctl(onedram_fd, ONEDRAM_REL_SEM) < 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: ONEDRAM_REL_SEM ioctl on onedram failed"); + goto error_loop; + } + + onedram_data = ONEDRAM_DEINIT_CMD; + + timeout.tv_sec=5; + timeout.tv_usec=0; + + ipc_client_log(client, "aries_ipc_bootstrap: send 0x%04x", onedram_data); + write(onedram_fd, &onedram_data, sizeof(onedram_data)); + + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed"); + goto error_loop; + } + + read(onedram_fd, &onedram_data, sizeof(onedram_data)); + + if(onedram_data != ONEDRAM_DEINIT_READ) + { + ipc_client_log(client, "aries_ipc_bootstrap: wrong onedram deinit magic (got 0x%04x)", onedram_data); + goto error_loop; + } + + ipc_client_log(client, "aries_ipc_bootstrap: got 0x%04x", onedram_data); + + close(onedram_fd); + + rc = 0; + goto exit; + +error_loop: + ipc_client_log(client, "aries_ipc_bootstrap: something went wrong"); + boot_tries_count++; + sleep(2); + + goto boot_loop_start; + +error: + ipc_client_log(client, "aries_ipc_bootstrap: something went wrong"); + rc = -1; +exit: + ipc_client_log(client, "aries_ipc_bootstrap: exit"); + return rc; +} + +int aries_ipc_fmt_client_send(struct ipc_client *client, struct ipc_message_info *request) +{ + struct ipc_header reqhdr; + void *data; + int rc = 0; + + reqhdr.mseq = request->mseq; + reqhdr.aseq = request->aseq; + reqhdr.group = request->group; + reqhdr.index = request->index; + reqhdr.type = request->type; + reqhdr.length = (uint16_t) (request->length + sizeof(struct ipc_header)); + + data = malloc(reqhdr.length); + + memcpy(data, &reqhdr, sizeof(struct ipc_header)); + memcpy((unsigned char *) (data + sizeof(struct ipc_header)), request->data, request->length); + + assert(client->handlers->write != NULL); + + ipc_client_log(client, "aries_ipc_fmt_client_send: SEND FMT!"); + ipc_client_log(client, "aries_ipc_fmt_client_send: IPC request (mseq=0x%02x command=%s (0x%04x) type=%s)", + request->mseq, ipc_command_to_str(IPC_COMMAND(request)), IPC_COMMAND(request), ipc_request_type_to_str(request->type)); + +#ifdef DEBUG + if(request->length > 0) + { + ipc_client_log(client, "==== FMT DATA DUMP ===="); + ipc_hex_dump(client, (void *) request->data, request->length); + } +#endif + + ipc_client_log(client, ""); + + rc = client->handlers->write(data, reqhdr.length, client->handlers->write_data); + return rc; +} + +int aries_ipc_rfs_client_send(struct ipc_client *client, struct ipc_message_info *request) +{ + struct rfs_hdr *rfs_hdr; + void *data; + int rc = 0; + + data = malloc(request->length + sizeof(struct rfs_hdr)); + memset(data, 0, request->length + sizeof(struct rfs_hdr)); + + rfs_hdr = (struct rfs_hdr *) data; + + rfs_hdr->id = request->mseq; + rfs_hdr->cmd = request->index; + rfs_hdr->len = request->length + sizeof(struct rfs_hdr); + + memcpy((void *) (data + sizeof(struct rfs_hdr)), request->data, request->length); + + assert(client->handlers->write != NULL); + + ipc_client_log(client, "aries_ipc_rfs_client_send: SEND RFS (id=%d cmd=%d len=%d)!", rfs_hdr->id, rfs_hdr->cmd, rfs_hdr->len); + ipc_client_log(client, "aries_ipc_rfs_client_send: IPC request (mseq=0x%02x command=%s (0x%04x))", + request->mseq, ipc_command_to_str(IPC_COMMAND(request)), IPC_COMMAND(request)); + +#ifdef DEBUG + if(request->length > 0) + { + ipc_client_log(client, "==== RFS DATA DUMP ===="); + ipc_hex_dump(client, (void *) (data + sizeof(struct rfs_hdr)), request->length); + } +#endif + + ipc_client_log(client, ""); + + rc = client->handlers->write((uint8_t*) data, rfs_hdr->len, client->handlers->write_data); + return rc; +} + +int aries_ipc_fmt_client_recv(struct ipc_client *client, struct ipc_message_info *response) +{ + struct ipc_header *resphdr; + void *data; + int bread = 0; + + data = malloc(MAX_MODEM_DATA_SIZE); + memset(data, 0, MAX_MODEM_DATA_SIZE); + + memset(response, 0, sizeof(struct ipc_message_info)); + + assert(client->handlers->read != NULL); + bread = client->handlers->read((uint8_t*) data, MAX_MODEM_DATA_SIZE, client->handlers->read_data); + + if (bread < 0) + { + ipc_client_log(client, "aries_ipc_fmt_client_recv: can't receive enough bytes from modem to process incoming response!"); + return -1; + } + + if(data == NULL) + { + ipc_client_log(client, "aries_ipc_fmt_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!"); + return -1; + } + + resphdr = (struct ipc_header *) data; + + response->mseq = resphdr->mseq; + response->aseq = resphdr->aseq; + response->group = resphdr->group; + response->index = resphdr->index; + response->type = resphdr->type; + response->length = resphdr->length - sizeof(struct ipc_header); + response->data = NULL; + + ipc_client_log(client, "aries_ipc_fmt_client_recv: RECV FMT!"); + ipc_client_log(client, "aries_ipc_fmt_client_recv: IPC response (aseq=0x%02x command=%s (0x%04x) type=%s)", + response->aseq, ipc_command_to_str(IPC_COMMAND(response)), IPC_COMMAND(response), ipc_response_type_to_str(response->type)); + + if(response->length > 0) + { +#ifdef DEBUG + ipc_client_log(client, "==== FMT DATA DUMP ===="); + ipc_hex_dump(client, (void *) (data + sizeof(struct ipc_header)), response->length); +#endif + response->data = malloc(response->length); + memcpy(response->data, (uint8_t *) data + sizeof(struct ipc_header), response->length); + } + + free(data); + + ipc_client_log(client, ""); + + return 0; +} + +int aries_ipc_rfs_client_recv(struct ipc_client *client, struct ipc_message_info *response) +{ + void *data; + int bread = 0; + struct rfs_hdr *rfs_hdr; + + data = malloc(MAX_MODEM_DATA_SIZE); + memset(data, 0, MAX_MODEM_DATA_SIZE); + + memset(response, 0, sizeof(struct ipc_message_info)); + + assert(client->handlers->read != NULL); + bread = client->handlers->read((uint8_t*) data, MAX_MODEM_DATA_SIZE, client->handlers->read_data); + if (bread < 0) + { + ipc_client_log(client, "aries_ipc_rfs_client_recv: can't receive enough bytes from modem to process incoming response!"); + return -1; + } + + rfs_hdr = (struct rfs_hdr *) data; + + if(rfs_hdr->len <= 0 || rfs_hdr->len >= MAX_MODEM_DATA_SIZE || data == NULL) + { + ipc_client_log(client, "aries_ipc_rfs_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!"); + return -1; + } + + response->mseq = 0; + response->aseq = rfs_hdr->id; + response->group = IPC_GROUP_RFS; + response->index = rfs_hdr->cmd; + response->type = 0; + response->length = rfs_hdr->len - sizeof(struct rfs_hdr); + response->data = NULL; + + ipc_client_log(client, "aries_ipc_rfs_client_recv: RECV RFS (id=%d cmd=%d len=%d)!", rfs_hdr->id, rfs_hdr->cmd, rfs_hdr->len - sizeof(struct rfs_hdr)); + ipc_client_log(client, "aries_ipc_rfs_client_recv: IPC response (aseq=0x%02x command=%s (0x%04x))", + response->mseq, ipc_command_to_str(IPC_COMMAND(response)), IPC_COMMAND(response)); + + if(response->length > 0) + { +#ifdef DEBUG + ipc_client_log(client, "==== RFS DATA DUMP ===="); + ipc_hex_dump(client, (void *) (data + sizeof(struct rfs_hdr)), response->length); +#endif + response->data = malloc(response->length); + memcpy(response->data, (uint8_t *) (data + sizeof(struct rfs_hdr)), response->length); + } + + free(data); + + ipc_client_log(client, ""); + + return 0; +} + +int aries_ipc_open(void *data, unsigned int size, void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + struct sockaddr_pn *spn; + struct ifreq ifr; + + int type = *((int *) data); + + int reuse; + int socket_rfs_magic; + + int fd = -1; + int rc; + + if(io_data == NULL) + goto error; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + spn = common_data->spn; + + memset(&ifr, 0, sizeof(ifr)); + memset(ifr.ifr_name, 0, IFNAMSIZ); + memset(spn, 0, sizeof(struct sockaddr_pn)); + + strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ); + + spn->spn_family = AF_PHONET; + spn->spn_dev = 0; + + switch(type) + { + case IPC_CLIENT_TYPE_FMT: + spn->spn_resource = PHONET_SPN_RES_FMT; + break; + case IPC_CLIENT_TYPE_RFS: + spn->spn_resource = PHONET_SPN_RES_RFS; + break; + default: + break; + } + + fd = socket(AF_PHONET, SOCK_DGRAM, 0); + if(fd < 0) + return -1; + + rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, IFNAMSIZ); + if(rc < 0) + goto error; + + rc = ioctl(fd, SIOCGIFINDEX, &ifr); + if(rc < 0) + goto error; + + reuse = 1; + rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + if(rc < 0) + goto error; + + rc = bind(fd, spn, sizeof(struct sockaddr_pn)); + if(rc < 0) + goto error; + + common_data->fd = fd; + + if(type == IPC_CLIENT_TYPE_RFS) + { + socket_rfs_magic = SOCKET_RFS_MAGIC; + rc = setsockopt(fd, SOL_SOCKET, SO_RFSMAGIC, &socket_rfs_magic, sizeof(socket_rfs_magic)); + if(rc < 0) + goto error; + } + + rc = phonet_iface_ifup(); + if(rc < 0) + goto error; + + goto end; + +error: + return -1; + +end: + return 0; +} + +int aries_ipc_close(void *data, unsigned int size, void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + int fd = -1; + + if(io_data == NULL) + return -1; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + fd = common_data->fd; + + if(fd < 0) + return -1; + + close(fd); + + return 0; +} + +int aries_ipc_read(void *data, unsigned int size, void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + int spn_len; + int fd = -1; + int rc; + + if(io_data == NULL) + return -1; + + if(data == NULL) + return -1; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + fd = common_data->fd; + + if(fd < 0) + return -1; + + spn_len = sizeof(struct sockaddr_pn); + rc = recvfrom(fd, data, size, 0, common_data->spn, &spn_len); + + if(rc < 0) + return -1; + + return 0; +} + +int aries_ipc_write(void *data, unsigned int size, void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + int spn_len; + int fd = -1; + int rc; + + if(io_data == NULL) + return -1; + + if(data == NULL) + return -1; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + fd = common_data->fd; + + if(fd < 0) + return -1; + + spn_len = sizeof(struct sockaddr_pn); + + rc = sendto(fd, data, size, 0, common_data->spn, spn_len); + + if(rc < 0) + return -1; + + return 0; +} + +int aries_ipc_power_on(void *data) +{ + int fd = open("/sys/class/modemctl/xmm/status", O_RDONLY); + char status[1] = { 0 }; + char power_data[4] = "on"; + int rc; + + if(fd < 0) + return -1; + + rc = read(fd, status, 1); + + close(fd); + + if(rc < 0) + return -1; + + // it's already on + if(status[0] == '1') + return 0; + + fd = open("/sys/class/modemctl/xmm/control", O_RDWR); + if(fd < 0) + return -1; + + rc = write(fd, power_data, 2); + + close(fd); + + if(rc < 0) + return -1; + + return 0; +} + +int aries_ipc_power_off(void *data) +{ + int fd = open("/sys/class/modemctl/xmm/status", O_RDONLY); + char status[1] = { 0 }; + char power_data[5] = "off"; + int rc; + + if(fd < 0) + return -1; + + rc = read(fd, status, 1); + + close(fd); + + if(rc < 0) + return -1; + + // it's already off + if(status[0] == '0') + return 0; + + fd = open("/sys/class/modemctl/xmm/control", O_RDWR); + if(fd < 0) + return -1; + + rc = write(fd, power_data, 3); + + close(fd); + + if(rc < 0) + return -1; + + return 0; +} + +void *aries_ipc_common_data_create(void) +{ + struct aries_ipc_handlers_common_data *common_data; + void *io_data; + int io_data_len; + int spn_len; + + io_data_len = sizeof(struct aries_ipc_handlers_common_data); + io_data = malloc(io_data_len); + + if(io_data == NULL) + return NULL; + + memset(io_data, 0, io_data_len); + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + + spn_len = sizeof(struct sockaddr_pn); + common_data->spn = malloc(spn_len); + + if(common_data == NULL) + return NULL; + + memset(common_data->spn, 0, spn_len); + + return io_data; +} + +int aries_ipc_common_data_destroy(void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + + // This was already done, not an error but we need to return + if(io_data == NULL) + return 0; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + + if(common_data->spn != NULL) + free(common_data->spn); + + free(io_data); + + return 0; +} + +int aries_ipc_common_data_set_fd(void *io_data, int fd) +{ + struct aries_ipc_handlers_common_data *common_data; + + if(io_data == NULL) + return -1; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + common_data->fd = fd; + + return 0; +} + +int aries_ipc_common_data_get_fd(void *io_data) +{ + struct aries_ipc_handlers_common_data *common_data; + + if(io_data == NULL) + return -1; + + common_data = (struct aries_ipc_handlers_common_data *) io_data; + + return common_data->fd; +} + +struct ipc_handlers ipc_default_handlers = { + .read = aries_ipc_read, + .write = aries_ipc_write, + .open = aries_ipc_open, + .close = aries_ipc_close, + .power_on = aries_ipc_power_on, + .power_off = aries_ipc_power_off, + .common_data = NULL, + .common_data_create = aries_ipc_common_data_create, + .common_data_destroy = aries_ipc_common_data_destroy, + .common_data_set_fd = aries_ipc_common_data_set_fd, + .common_data_get_fd = aries_ipc_common_data_get_fd, +}; + +struct ipc_ops ipc_fmt_ops = { + .send = aries_ipc_fmt_client_send, + .recv = aries_ipc_fmt_client_recv, + .bootstrap = aries_modem_bootstrap, +}; + +struct ipc_ops ipc_rfs_ops = { + .send = aries_ipc_rfs_client_send, + .recv = aries_ipc_rfs_client_recv, + .bootstrap = NULL, +}; + +// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.h b/samsung-ipc/device/aries/aries_ipc.h index 05e0a5c..82c7286 100644 --- a/samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.h +++ b/samsung-ipc/device/aries/aries_ipc.h @@ -2,6 +2,7 @@ * This file is part of libsamsung-ipc. * * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> + * Igor Almeida <igor.contato@gmail.com> * * libsamsung-ipc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,38 +19,37 @@ * */ -#ifndef __GALAXYSMTD_IPC_H__ -#define __GALAXYSMTD_IPC_H__ +#ifndef __ARIES_IPC_H__ +#define __ARIES_IPC_H__ + +#include "phonet.h" -//from trace/logcat: nCoreVer = 0xf0 #define BOOTCORE_VERSION 0xf0 -//from trace: write(14, "0", 1) before PSI_DATA_LEN #define PSI_MAGIC 0x30 -//from trace/logcat: Bootloader IMG Size: 0x00005000, sent after PSI_MAGIC, LSB first #define PSI_DATA_LEN 0x5000 -//from /radio/modem.bin size (0xc00000) - /efs/nv_data.bin size (0x2...) -#define RADIO_IMG_SIZE 0xc00000-0x200000 +#define RADIO_IMG_MAX_SIZE 0xd80000 +#define RADIO_IMG_READ_SIZE 0xa00000 +#define ONENAND_MAP_SIZE 0xFFF000 +#define ONEDRAM_INIT_READ 0x12341234 +#define ONEDRAM_DEINIT_CMD 0x45674567 +#define ONEDRAM_DEINIT_READ 0xabcdabcd +#define SO_RFSMAGIC 0x21 +#define SOCKET_RFS_MAGIC 0x80000 +#define PHONET_IFACE "svnet0" +#define PHONET_SPN_RES_FMT 0x01 +#define PHONET_SPN_RES_RFS 0x41 -//should be the same from crespo #define MAX_MODEM_DATA_SIZE 0x1000 -struct samsung_rfs_msg -{ - uint32_t offset; - uint32_t size; -}; +int phonet_iface_ifdown(void); +int phonet_iface_ifup(void); -struct samsung_rfs_cfrm +struct aries_ipc_handlers_common_data { - uint8_t confirmation; - struct samsung_rfs_msg msg; + int fd; + struct sockaddr_pn *spn; }; -int wake_lock(char *lock_name, int len); -int wake_unlock(char *lock_name, int len); - -extern struct ipc_handlers galaxysmtd_ipc_default_handlers; - #endif // vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/device/aries/onedram.h b/samsung-ipc/device/aries/onedram.h new file mode 100644 index 0000000..9c69c76 --- /dev/null +++ b/samsung-ipc/device/aries/onedram.h @@ -0,0 +1,30 @@ +/** + * header for onedram driver + * + * Copyright (C) 2010 Samsung Electronics. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __ONEDRAM_H__ +#define __ONEDRAM_H__ + +#include <linux/ioctl.h> + +#define ONEDRAM_GET_AUTH _IOW('o', 0x20, u32) +#define ONEDRAM_PUT_AUTH _IO('o', 0x21) +#define ONEDRAM_REL_SEM _IO('o', 0x22) + +#endif /* __ONEDRAM_H__ */ diff --git a/samsung-ipc/device/aries/phonet.h b/samsung-ipc/device/aries/phonet.h new file mode 100644 index 0000000..edf36ec --- /dev/null +++ b/samsung-ipc/device/aries/phonet.h @@ -0,0 +1,62 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef NETPHONET_PHONET_H +#define NETPHONET_PHONET_H + +#include <sys/types.h> + +#include <sys/socket.h> +#ifndef AF_PHONET +#define AF_PHONET 35 +#define PF_PHONET AF_PHONET +#endif + +#define PN_PROTO_TRANSPORT 0 +#define PN_PROTO_PHONET 1 +#define PN_PROTO_PIPE 2 + +#define SOL_PNPIPE 275 + +#define PNPIPE_ENCAP 1 +#define PNPIPE_IFINDEX 2 + +#define PNPIPE_ENCAP_NONE 0 +#define PNPIPE_ENCAP_IP 1 + +#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0) +#define SIOCPNADDRESOURCE (SIOCPROTOPRIVATE + 14) +#define SIOCPNDELRESOURCE (SIOCPROTOPRIVATE + 15) + +struct sockaddr_pn { + sa_family_t spn_family; + uint8_t spn_obj; + uint8_t spn_dev; + uint8_t spn_resource; + uint8_t __pad[sizeof(struct sockaddr) - (sizeof(sa_family_t) + 3)]; +} __attribute__ ((packed)); + +#include <linux/rtnetlink.h> +#ifndef RTNLGRP_PHONET_IFADDR +#define RTNLGRP_PHONET_IFADDR 21 +#endif + +#endif diff --git a/samsung-ipc/device/aries/sipc4.h b/samsung-ipc/device/aries/sipc4.h new file mode 100644 index 0000000..616d005 --- /dev/null +++ b/samsung-ipc/device/aries/sipc4.h @@ -0,0 +1,256 @@ +/** + * SAMSUNG MODEM IPC header version 4 + * + * Copyright (C) 2010 Samsung Electronics. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __SAMSUNG_IPC_V4_H__ +#define __SAMSUNG_IPC_V4_H__ + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +/* IPC4.1 NEW PARTITION MAP + * This map is seen by AP side + + 0x00_0000 =========================================== + MAGIC(4)| ACCESS(4) | RESERVED(8) + 0x00_0010 ------------------------------------------- + FMT_OUT_PTR | FMT_IN_PTR + HEAD(4) | TAIL(4) | HEAD(4) | TAIL(4) + 0x00_0020 ------------------------------------------- + RAW_OUT_PTR | RAW_IN_PTR + HEAD(4) | TAIL(4) | HEAD(4) | TAIL(4) + 0x00_0030 ------------------------------------------- + RFS_OUT_PTR | RFS_IN_PTR + HEAD(4) | TAIL(4) | HEAD(4) | TAIL(4) + 0x00_0040 ------------------------------------------- + RESERVED (4KB - 64B) + 0x00_1000 ------------------------------------------- + CP Fatal Display (160B) + 0x00_10A0 ------------------------------------------- + RESERVED (1MB - 4kb-4kb-4kb - 160B) + 0x0F_E000 ------------------------------------------- + Formatted Out (4KB) + 0x0F_F000 ------------------------------------------- + Formatted In (4KB) + 0x10_0000 =========================================== + Raw Out (1MB) + 0x20_0000 =========================================== + Raw In (1MB) + 0x30_0000 =========================================== + RemoteFS Out (1MB) + 0x40_0000 =========================================== + RemoteFS In (1MB) + 0x50_0000 =========================================== + + 0xFF_FFFF =========================================== +*/ + +#define FMT_OUT 0x0FE000 +#define FMT_IN 0x0FF000 +#define FMT_SZ 0x1000 /* 4096 bytes */ + +#define RAW_OUT 0x100000 +#define RAW_IN 0x200000 +#define RAW_SZ 0x100000 /* 1 MB */ + +#define RFS_OUT 0x300000 +#define RFS_IN 0x400000 +#define RFS_SZ 0x100000 /* 1 MB */ + +#define FATAL_DISP 0x001000 +#define FATAL_DISP_SZ 0xA0 /* 160 bytes */ + +#define SIPC_MAP_SIZE (RFS_IN + RFS_SZ) +#define SIPC_NAME "IPCv4.1" + +enum { + IPCIDX_FMT = 0, + IPCIDX_RAW, + IPCIDX_RFS, + IPCIDX_MAX +}; + +struct ringbuf_cont { + u32 out_head; + u32 out_tail; + u32 in_head; + u32 in_tail; +}; + +struct sipc_mapped { /* map to the onedram start addr */ + u32 magic; + u32 access; + u32 hwrev; + u32 reserved; + + struct ringbuf_cont rbcont[IPCIDX_MAX]; +}; + + +#define PN_CMD 0x00 +#define PN_FMT 0x01 +#define PN_RFS 0x41 +#define PN_RAW(chid) (0x20 | (chid)) +#define CHID(x) ((x) & 0x1F) + +#define res_to_ridx(x) ((x) >> 5) + +/* + * IPC Frame Format + */ +#define HDLC_START 0x7F +#define HDLC_END 0x7E + +/* Formatted IPC Frame */ +struct fmt_hdr { + u16 len; + u8 control; +} __attribute__ ((packed)); + +#define FMT_ID_MASK 0x7F /* Information ID mask */ +#define FMT_ID_SIZE 0x80 /* = 128 ( 0 ~ 127 ) */ +#define FMT_MB_MASK 0x80 /* More bit mask */ + +#define FMT_TX_MIN 5 /* ??? */ + +#define is_fmt_last(x) (!((x) & FMT_MB_MASK)) + +/* RAW IPC Frame */ +struct raw_hdr { + u32 len; + u8 channel; + u8 control; +} __attribute__ ((packed)); + + +/* RFS IPC Frame */ +struct rfs_hdr { + u32 len; + u8 cmd; + u8 id; +} __attribute__ ((packed)); + +/* + * RAW frame channel ID + */ +enum { + CHID_0 = 0, + CHID_CSD_VT_DATA, + CHID_PDS_PVT_CONTROL, + CHID_PDS_VT_AUDIO, + CHID_PDS_VT_VIDEO, + CHID_5, /* 5 */ + CHID_6, + CHID_CDMA_DATA, + CHID_PCM_DATA, + CHID_TRANSFER_SCREEN, + CHID_PSD_DATA1, /* 10 */ + CHID_PSD_DATA2, + CHID_PSD_DATA3, + CHID_PSD_DATA4, + CHID_PSD_DATA5, + CHID_PSD_DATA6, /* 15 */ + CHID_PSD_DATA7, + CHID_PSD_DATA8, + CHID_PSD_DATA9, + CHID_PSD_DATA10, + CHID_PSD_DATA11, /* 20 */ + CHID_PSD_DATA12, + CHID_PSD_DATA13, + CHID_PSD_DATA14, + CHID_PSD_DATA15, + CHID_BT_DUN, /* 25 */ + CHID_CIQ_BRIDGE_DATA, + CHID_27, + CHID_CP_LOG1, + CHID_CP_LOG2, + CHID_30, /* 30 */ + CHID_31, + CHID_MAX +}; + +#define PDP_MAX 15 +#define PN_PDP_START PN_RAW(CHID_PSD_DATA1) +#define PN_PDP_END PN_RAW(CHID_PSD_DATA15) + +#define PN_PDP(chid) (0x20 | ((chid) + CHID_PSD_DATA1 - 1)) +#define PDP_ID(res) ((res) - PN_PDP_START) + + +/* + * IPC 4.0 Mailbox message definition + */ +#define MB_VALID 0x0080 +#define MB_COMMAND 0x0040 + +#define MB_CMD(x) (MB_VALID | MB_COMMAND | x) +#define MB_DATA(x) (MB_VALID | x) + +/* + * If not command + */ +#define MBD_SEND_FMT 0x0002 +#define MBD_SEND_RAW 0x0001 +#define MBD_SEND_RFS 0x0100 +#define MBD_REQ_ACK_FMT 0x0020 +#define MBD_REQ_ACK_RAW 0x0010 +#define MBD_REQ_ACK_RFS 0x0400 +#define MBD_RES_ACK_FMT 0x0008 +#define MBD_RES_ACK_RAW 0x0004 +#define MBD_RES_ACK_RFS 0x0200 + +/* + * If command + */ +enum { + MBC_NONE = 0, + MBC_INIT_START, // 0x0001 + MBC_INIT_END, // 0x0002 + MBC_REQ_ACTIVE, // 0x0003 + MBC_RES_ACTIVE, // 0x0004 + MBC_TIME_SYNC, // 0x0005 + MBC_POWER_OFF, // 0x0006 + MBC_RESET, // 0x0007 + MBC_PHONE_START, // 0x0008 + MBC_ERR_DISPLAY, // 0x0009 + MBC_POWER_SAVE, // 0x000A + MBC_NV_REBUILD, // 0x000B + MBC_EMER_DOWN, // 0x000C + MBC_REQ_SEM, // 0x000D + MBC_RES_SEM, // 0x000E + MBC_MAX // 0x000F +}; +#define MBC_MASK 0xFF + +/* CMD_INIT_END extended bit */ +#define CP_BOOT_ONLINE 0x0000 +#define CP_BOOT_AIRPLANE 0x1000 +#define AP_OS_ANDROID 0x0100 +#define AP_OS_WINMOBILE 0x0200 +#define AP_OS_LINUX 0x0300 +#define AP_OS_SYMBIAN 0x0400 + +/* CMD_PHONE_START extended bit */ +#define CP_QUALCOMM 0x0100 +#define CP_INFINEON 0x0200 +#define CP_BROADCOM 0x0300 + +#endif /* __SAMSUNG_IPC_V4_H__ */ + diff --git a/samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.c b/samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.c deleted file mode 100644 index 7ddfb91..0000000 --- a/samsung-ipc/device/galaxysmtd/galaxysmtd_ipc.c +++ /dev/null @@ -1,644 +0,0 @@ -/** - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> - * Joerie de Gram <j.de.gram@gmail.com> - * Simon Busch <morphis@gravedo.de> - * - * libsamsung-ipc is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsamsung-ipc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <stdbool.h> -#include <termios.h> -#include <fcntl.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <asm/types.h> -#include <mtd/mtd-abi.h> -#include <assert.h> - -#include <radio.h> - -#include "galaxysmtd_modem_ctl.h" -#include "galaxysmtd_nv_data.h" -#include "galaxysmtd_ipc.h" -#include "ipc_private.h" - -int wake_lock_fd= -1; -int wake_unlock_fd= -1; - -int galaxysmtd_modem_bootstrap(struct ipc_client *client) -{ - int s3c2410_serial3_fd= -1; - int modem_ctl_fd= -1; - - /* Control variables. */ - int boot_tries_count=0; - int rc=0; - - /* Boot variables */ - uint8_t *radio_img_p=NULL; - uint8_t bootcore_version=0; - uint8_t info_size=0; - uint8_t crc_byte=0; - int block_size=0; - - /* s3c2410 serial setup variables. */ - struct termios termios; - int serial; - - /* fds maniplation variables */ - struct timeval timeout; - fd_set fds; - - /* nv_data variables */ - void *nv_data_p; - - /* General purpose variables. */ - uint8_t data; - uint16_t data_16; - uint8_t *data_p; - unsigned int modem_ctl_data; - int i; - void *onedram_map=NULL; - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: enter"); - -boot_loop_start: - if(boot_tries_count > 5) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: boot has failed too many times."); - goto error; - } - - //TODO try to disable svnet0 first? - - /* Read the radio.img image. */ - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: reading radio image"); - radio_img_p = ipc_mtd_read(client, "/dev/block/bml12", RADIO_IMG_SIZE, 0x1000); - if (radio_img_p == NULL) { - goto error; - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: radio image read"); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: open modem_ctl"); - modem_ctl_fd = open("/dev/onedram", O_RDWR); - if(modem_ctl_fd < 0) - goto error_loop; - - /* Reset the modem before init to send the first part of modem.bin. */ - ipc_client_power_off(client); - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sent PHONE \"off\" command"); - usleep(1000); - ipc_client_power_on(client); - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sent PHONE \"on\" command"); - usleep(200000); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: open s3c2410_serial3"); - s3c2410_serial3_fd = open("/dev/s3c2410_serial3", O_RDWR); - if(s3c2410_serial3_fd < 0) - goto error_loop; - - /* Setup the s3c2410 serial. */ - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: setup s3c2410_serial3"); - - ioctl(s3c2410_serial3_fd, TIOCMGET, &serial); //FIXME - ioctl(s3c2410_serial3_fd, TIOCMSET, &serial); //FIXME - - tcgetattr(s3c2410_serial3_fd, &termios); //FIXME - tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); //FIXME - - tcgetattr(s3c2410_serial3_fd, &termios); - - cfmakeraw(&termios); - cfsetispeed(&termios, B115200); - cfsetospeed(&termios, B115200); - - tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); - - /* Send 'AT' in ASCII. */ - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sending AT in ASCII"); - for(i=0 ; i < 20 ; i++) - { - rc = write(s3c2410_serial3_fd, "AT", 2); - usleep(50000); - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sending AT in ASCII done"); - - usleep(50000); //FIXME - - /* Get and check bootcore version. */ - read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version)); - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: got bootcore version: 0x%x", bootcore_version); - - if(bootcore_version != BOOTCORE_VERSION) - goto error_loop; - - /* Get info_size. */ - read(s3c2410_serial3_fd, &info_size, sizeof(info_size)); - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: got info_size: 0x%x", info_size); - - /* Send PSI magic. */ - data=PSI_MAGIC; - write(s3c2410_serial3_fd, &data, sizeof(data)); - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sent PSI_MAGIC (0x%x)", PSI_MAGIC); - - /* Send PSI data len. */ - data_16=PSI_DATA_LEN; - data_p=(uint8_t *)&data_16; - - for(i=0 ; i < 2 ; i++) - { - write(s3c2410_serial3_fd, data_p, 1); - data_p++; - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)", PSI_DATA_LEN); - - /* Write the first part of modem.img. */ - FD_ZERO(&fds); - FD_SET(s3c2410_serial3_fd, &fds); - - timeout.tv_sec=5; - timeout.tv_usec=0; - - data_p=radio_img_p; - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: sending the first part of modem.bin"); - - crc_byte=0; - for(i=0 ; i < PSI_DATA_LEN ; i++) - { - if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: select timeout passed"); - goto error_loop; - } - - write(s3c2410_serial3_fd, data_p, 1); - crc_byte=crc_byte ^ *data_p; - - data_p++; - } - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: first part of modem.bin sent; crc_byte is 0x%x", crc_byte); - - if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: select timeout passed"); - goto error_loop; - } - - write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte)); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: crc_byte sent"); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: wait for ACK"); - data = 0; - for(i = 0 ; data != 0x01 ; i++) - { - if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: select timeout passed"); - goto error_loop; - } - - read(s3c2410_serial3_fd, &data, sizeof(data)); - - if(i > 50) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: fairly too much attempts to get ACK"); - goto error_loop; - } - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: got ACK"); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: close s3c2410_serial3"); - close(s3c2410_serial3_fd); - - FD_ZERO(&fds); - FD_SET(modem_ctl_fd, &fds); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: wait for 0x12341234"); - if(select(modem_ctl_fd+1, &fds, NULL, NULL, &timeout) == 0) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: select timeout passed"); - goto error_loop; - } - - read(modem_ctl_fd, &modem_ctl_data, sizeof(modem_ctl_data)); - if(modem_ctl_data != 0x12341234) { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: wrong ACK flag from modem_ctl"); - goto error_loop; - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: got 0x12341234"); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: writing the rest of modem.bin to modem_ctl."); - - /* Pointer to the remaining part of radio.img. */ - data_p=radio_img_p + PSI_DATA_LEN; - - size_t map_length = 16773120; //magic buflen comes from proprietary ril trace - onedram_map = mmap(NULL, map_length, PROT_READ|PROT_WRITE, MAP_SHARED, modem_ctl_fd, 0); - if(onedram_map == -1) { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: could not map onedram to memory"); - goto error_loop; - } - - memcpy(onedram_map, data_p, RADIO_IMG_SIZE - PSI_DATA_LEN); - - free(radio_img_p); - - /* nv_data part. */ - - /* Check if all the nv_data files are ok. */ - nv_data_check(client); - - /* Check if the MD5 is ok. */ - nv_data_md5_check(client); - - /* Write nv_data.bin to modem_ctl. */ - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: write nv_data to modem_ctl"); - - nv_data_p = ipc_file_read(client, "/efs/nv_data.bin", NV_DATA_SIZE, 1024); - if (nv_data_p == NULL) - goto error; - data_p = nv_data_p; - - //seems 0xd80000 is the absolute maximum for the radio_img, like crespo - //uses. it creates a gap though, since we only write 0x9fb000 bytes to /dev/onedram - memcpy(onedram_map + 0xd80000, data_p, NV_DATA_SIZE); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: done writing nv_data"); - - free(nv_data_p); - munmap(onedram_map, map_length); - - //TODO finalize bootstrap - ioctl(modem_ctl_fd, 0x6f22, 0); //magic request comes from proprietary ril trace - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: send 0x45674567"); - modem_ctl_data = 0x45674567; - write(modem_ctl_fd, &modem_ctl_data, sizeof(modem_ctl_data)); - - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: wait for 0xabcdabcd"); - for(i = 0 ; modem_ctl_data != 0xabcdabcd ; i++) - { - if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: select timeout passed"); - goto error_loop; - } - - read(modem_ctl_fd, &modem_ctl_data, sizeof(modem_ctl_data)); - - if(i > 10) - { - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: fairly too much attempts to get 0xabcdabcd"); - goto error_loop; - } - } - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: got 0xabcdabcd"); - - close(modem_ctl_fd); - - rc = 0; - goto exit; - -error_loop: - ipc_client_log(client, "%s: something went wrong", __func__); - boot_tries_count++; - sleep(2); - - goto boot_loop_start; - -error: - ipc_client_log(client, "%s: something went wrong", __func__); - rc = 1; -exit: - ipc_client_log(client, "galaxysmtd_ipc_bootstrap: exit"); - return rc; -} - -int crespo_ipc_client_send(struct ipc_client *client, struct ipc_message_info *request) -{ - struct modem_io modem_data; - struct ipc_header reqhdr; - int rc = 0; - - memset(&modem_data, 0, sizeof(struct modem_io)); - modem_data.size = request->length + sizeof(struct ipc_header); - - reqhdr.mseq = request->mseq; - reqhdr.aseq = request->aseq; - reqhdr.group = request->group; - reqhdr.index = request->index; - reqhdr.type = request->type; - reqhdr.length = (uint16_t) (request->length + sizeof(struct ipc_header)); - - modem_data.data = malloc(reqhdr.length); - - memcpy(modem_data.data, &reqhdr, sizeof(struct ipc_header)); - memcpy((unsigned char *) (modem_data.data + sizeof(struct ipc_header)), request->data, request->length); - - assert(client->handlers->write != NULL); - - ipc_client_log(client, "INFO: crespo_ipc_client_send: Modem SEND FMT (id=%d cmd=%d size=%d)!", modem_data.id, modem_data.cmd, modem_data.size); - ipc_client_log(client, "INFO: crespo_ipc_client_send: request: type = %d (%s), group = %d, index = %d (%s)", - request->type, ipc_request_type_to_str(request->type), request->group, request->index, ipc_command_type_to_str(IPC_COMMAND(request))); - -#ifdef DEBUG - if(request->length > 0) - { - ipc_client_log(client, "INFO: ==== DATA DUMP ===="); - ipc_hex_dump(client, (void *) request->data, request->length); - } -#endif - - ipc_client_log(client, ""); - - rc = client->handlers->write((uint8_t*) &modem_data, sizeof(struct modem_io), client->handlers->write_data); - return rc; -} - -int wake_lock(char *lock_name, int len) -{ - int rc = 0; - - wake_lock_fd = open("/sys/power/wake_lock", O_RDWR); - rc = write(wake_lock_fd, lock_name, len); - close(wake_lock_fd); - - return rc; -} - -int wake_unlock(char *lock_name, int len) -{ - int rc = 0; - - wake_lock_fd = open("/sys/power/wake_unlock", O_RDWR); - rc = write(wake_lock_fd, lock_name, len); - close(wake_unlock_fd); - - return rc; -} - -int galaxysmtd_ipc_client_recv(struct ipc_client *client, struct ipc_message_info *response) -{ - struct modem_io modem_data; - struct ipc_header *resphdr; - int bread = 0; - - memset(&modem_data, 0, sizeof(struct modem_io)); - modem_data.data = malloc(MAX_MODEM_DATA_SIZE); - modem_data.size = MAX_MODEM_DATA_SIZE; - - memset(response, 0, sizeof(struct ipc_message_info)); - - wake_lock("secril_fmt-interface", 20); - - assert(client->handlers->read != NULL); - ipc_client_log(client, "INFO: galaxysmtd_ipc_client_recv -> read"); - bread = client->handlers->read((uint8_t*) &modem_data, sizeof(struct modem_io) + MAX_MODEM_DATA_SIZE, client->handlers->read_data); - ipc_client_log(client, "INFO: galaxysmtd_ipc_client_recv read something"); - if (bread < 0) - { - ipc_client_log(client, "ERROR: galaxysmtd_ipc_client_recv: can't receive enough bytes from modem to process incoming response!"); - return 1; - } - - ipc_client_log(client, "INFO: galaxysmtd_ipc_client_recv: Modem RECV FMT (id=%d cmd=%d size=%d)!", modem_data.id, modem_data.cmd, modem_data.size); - - if(modem_data.size <= 0 || modem_data.size >= 0x1000 || modem_data.data == NULL) - { - ipc_client_log(client, "ERROR: galaxysmtd_ipc_client_recv: we retrieve less bytes from the modem than we exepected!"); - return 1; - } - - /* You MUST send back modem_data */ - - resphdr = (struct ipc_header *) modem_data.data; - - response->mseq = resphdr->mseq; - response->aseq = resphdr->aseq; - response->group = resphdr->group; - response->index = resphdr->index; - response->type = resphdr->type; - response->length = modem_data.size - sizeof(struct ipc_header); - response->data = NULL; - - ipc_client_log(client, "INFO: crespo_ipc_client_recv: response: type = %d (%s), group = %d, index = %d (%s)", - resphdr->type, ipc_response_type_to_str(resphdr->type), resphdr->group, resphdr->index, ipc_command_type_to_str(IPC_COMMAND(resphdr))); - - if(response->length > 0) - { -#ifdef DEBUG - ipc_client_log(client, "INFO: ==== DATA DUMP ===="); - ipc_hex_dump(client, (void *) (modem_data.data + sizeof(struct ipc_header)), response->length); -#endif - response->data = malloc(response->length); - memcpy(response->data, (uint8_t *) modem_data.data + sizeof(struct ipc_header), response->length); - } - - free(modem_data.data); - - ipc_client_log(client, ""); - - wake_unlock("secril_fmt-interface", 20); - - return 0; -} - -int galaxysmtd_ipc_open(void *data, unsigned int size, void *io_data) -{ - int type = *((int *) data); - int fd = -1; - int ret; - char sadata[14]; - - if(io_data == NULL) - goto error; - - memset(sadata, 0, 14); - - const struct sockaddr saddr = { - .sa_family = 0x23, - .sa_data = sadata, - }; - - switch(type) - { - case IPC_CLIENT_TYPE_FMT: - sadata[2] = 1; - break; - case IPC_CLIENT_TYPE_RFS: - sadata[2] = 'A'; - break; - default: - break; - } - - fd = socket(0x23, SOCK_DGRAM, 0); - - if(fd < 0) - goto error; - - ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "svnet0", 16); - if(ret<0) - goto error; - - ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, "\1\0\0\0", 4); - if(ret<0) - goto error; - - ret = bind(fd, &saddr, sizeof(struct sockaddr)); - if(ret<0) - goto error; - - if(type == IPC_CLIENT_TYPE_RFS) { - ret = setsockopt(fd, SOL_SOCKET, 0x21, "", 4); - } - - *((int*)io_data) = fd; - goto end; - -error: - return -1; - -end: - return 0; -} - -int crespo_ipc_close(void *data, unsigned int size, void *io_data) -{ - int fd = -1; - - if(io_data == NULL) - return -1; - - fd = *((int *) io_data); - - if(fd < 0) - return -1; - - close(fd); - - return 0; -} - -int galaxysmtd_ipc_read(void *data, unsigned int size, void *io_data) -{ - int fd = -1; - int rc; - - if(io_data == NULL) - return -1; - - if(data == NULL) - return -1; - - fd = *((int *) io_data); - - if(fd < 0) - return -1; - - rc = recvfrom(fd, data, size, 0, NULL, NULL); - - if(rc < 0) - return -1; - - return 0; -} - -int crespo_ipc_write(void *data, unsigned int size, void *io_data) -{ - int fd = -1; - int rc; - - if(io_data == NULL) - return -1; - - fd = *((int *) io_data); - - if(fd < 0) - return -1; - - rc = ioctl(fd, IOCTL_MODEM_SEND, data); - - if(rc < 0) - return -1; - - return 0; -} - -int galaxysmtd_ipc_power_on(void *data) -{ - int fd = open("/sys/class/modemctl/xmm/control", O_RDWR); - int rc; - - if(fd < 0) - return -1; - - rc = write(fd, "on", 2); - close(fd); - - if(rc < 0) - return -1; - - //TODO should check if nothing was written as well? - - return 0; -} - -int galaxysmtd_ipc_power_off(void *data) -{ - int fd = open("/sys/class/modemctl/xmm/control", O_RDWR); - int rc; - - if(fd < 0) - return -1; - - rc = write(fd, "off", 3); - close(fd); - - if(rc < 0) - return -1; - - //TODO should check if nothing was written as well? - - return 0; -} - -struct ipc_handlers ipc_default_handlers = { - .read = galaxysmtd_ipc_read, - .write = crespo_ipc_write, - .open = galaxysmtd_ipc_open, - .close = crespo_ipc_close, - .power_on = galaxysmtd_ipc_power_on, - .power_off = galaxysmtd_ipc_power_off, -}; - -struct ipc_ops ipc_ops = { - .send = crespo_ipc_client_send, - .recv = galaxysmtd_ipc_client_recv, - .bootstrap = galaxysmtd_modem_bootstrap, -}; - -// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/device/galaxysmtd/galaxysmtd_modem_ctl.h b/samsung-ipc/device/galaxysmtd/galaxysmtd_modem_ctl.h deleted file mode 100644 index 7c23165..0000000 --- a/samsung-ipc/device/galaxysmtd/galaxysmtd_modem_ctl.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010 Samsung Electronics. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __MODEM_CONTROL_H__ -#define __MODEM_CONTROL_H__ - -#define IOCTL_MODEM_RAMDUMP _IO('o', 0x19) -#define IOCTL_MODEM_RESET _IO('o', 0x20) -#define IOCTL_MODEM_START _IO('o', 0x21) -#define IOCTL_MODEM_OFF _IO('o', 0x22) - -#define IOCTL_MODEM_SEND _IO('o', 0x23) -#define IOCTL_MODEM_RECV _IO('o', 0x24) - -struct modem_io { - uint32_t size; - uint32_t id; - uint32_t cmd; - void *data; -}; - -/* platform data */ -struct modemctl_data { - const char *name; - unsigned gpio_phone_active; - unsigned gpio_pda_active; - unsigned gpio_cp_reset; - unsigned gpio_phone_on; - bool is_cdma_modem; /* 1:CDMA Modem */ -}; - -#endif diff --git a/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.c b/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.c deleted file mode 100644 index f4c3967..0000000 --- a/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.c +++ /dev/null @@ -1,356 +0,0 @@ -/** - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> - * - * libsamsung-ipc is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsamsung-ipc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <sys/stat.h> - -#include <openssl/md5.h> - -#include <radio.h> -#include "galaxysmtd_nv_data.h" -#include "galaxysmtd_ipc.h" - -void md5hash2string(char *out, uint8_t *in) -{ - int i; - - for(i=0 ; i < MD5_DIGEST_LENGTH ; i++) - { - /* After the first iteration, we override \0. */ - if(*in < 0x10) - sprintf(out, "0%x", *in); - else - sprintf(out, "%x", *in); - in++; - out+=2; - } -} - -void nv_data_generate(struct ipc_client *client) -{ - ipc_client_log(client, "This feature isn't present yet\n"); - -// nv_data_backup_create(); -} - -void nv_data_md5_compute(void *data_p, int size, void *hash) -{ - MD5_CTX ctx; - -// MD5((unsigned char *)nv_data_p, nv_data_stat.st_size, nv_data_md5_hash); - - MD5_Init(&ctx); - MD5_Update(&ctx, data_p, size); - MD5_Update(&ctx, NV_DATA_MD5_SECRET, sizeof(NV_DATA_MD5_SECRET) - 1); - MD5_Final(hash, &ctx); -} - -void nv_data_backup_create(struct ipc_client *client) -{ - uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH]; - char *nv_data_md5_hash_string; - - struct stat nv_stat; - void *nv_data_p; - uint8_t data; - uint8_t *data_p; - - int fd; - int i; - - ipc_client_log(client, "nv_data_backup_create: enter\n"); - - if(stat("/efs/nv_data.bin", &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_check: nv_data.bin missing\n"); - nv_data_generate(client); - } - - /* Read the content of nv_data.bin. */ - nv_data_p=ipc_file_read(client, "/efs/nv_data.bin", NV_DATA_SIZE, NV_DATA_SIZE / 10); - - fd=open("/efs/.nv_data.bak", O_RDWR | O_CREAT, 0644); - - data_p=nv_data_p; - - /* Write the content of nv_data.bin in the backup file. */ - for(i=0 ; i < NV_DATA_SIZE / 10 ; i++) - { - write(fd, data_p, NV_DATA_SIZE / 10); - data_p+=NV_DATA_SIZE / 10; - } - - close(fd); - free(nv_data_p); - - /* Alloc the memory for the md5 hash string. */ - nv_data_md5_hash_string=malloc(MD5_STRING_SIZE); - memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE); - - /* Read the newly-written .nv_data.bak. */ - nv_data_p=ipc_file_read(client, "/efs/.nv_data.bak", NV_DATA_SIZE, NV_DATA_SIZE / 10); - - /* Compute the MD5 hash for .nv_data.bak.. */ - nv_data_md5_compute(nv_data_p, NV_DATA_SIZE, nv_data_md5_hash); - md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash); - - ipc_client_log(client, "nv_data_backup_create: new MD5 hash is %s\n", nv_data_md5_hash_string); - - free(nv_data_p); - - /* Write the MD5 hash in nv_data.bin.md5. */ - fd=open("/efs/.nv_data.bak.md5", O_RDWR | O_CREAT, 0644); - - write(fd, nv_data_md5_hash_string, MD5_STRING_SIZE); - - close(fd); - free(nv_data_md5_hash_string); - - /* Write ASCII 1 on the state file. */ - fd=open("/efs/.nv_state", O_RDWR | O_CREAT, 0644); - - data='1'; - write(fd, &data, sizeof(data)); - - close(fd); - - ipc_client_log(client, "nv_data_backup_create: exit\n"); -} - -void nv_data_backup_restore(struct ipc_client *client) -{ - uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH]; - char *nv_data_md5_hash_string; - char *nv_data_md5_hash_read; - - struct stat nv_stat; - void *nv_data_p; - uint8_t data; - uint8_t *data_p; - - int fd; - int i; - - ipc_client_log(client, "nv_data_backup_restore: enter\n"); - - if(stat("/efs/.nv_data.bak", &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_backup_restore: .nv_data.bak missing\n"); - nv_data_generate(client); - nv_data_backup_create(client); - return; - } - - if(nv_stat.st_size != NV_DATA_SIZE) - { - ipc_client_log(client, "nv_data_backup_restore: wrong .nv_data.bak size\n"); - nv_data_generate(client); - nv_data_backup_create(client); - return; - } - - /* Read the content of the backup file. */ - nv_data_p=ipc_file_read(client, "/efs/.nv_data.bak", NV_DATA_SIZE, NV_DATA_SIZE / 10); - - fd=open("/efs/nv_data.bin", O_RDWR | O_CREAT, 0644); - - data_p=nv_data_p; - - /* Write the content of the backup file in nv_data.bin. */ - for(i=0 ; i < NV_DATA_SIZE / 10 ; i++) - { - write(fd, data_p, NV_DATA_SIZE / 10); - data_p+=NV_DATA_SIZE / 10; - } - - close(fd); - free(nv_data_p); - - /* Alloc the memory for the md5 hashes strings. */ - nv_data_md5_hash_string=malloc(MD5_STRING_SIZE); - nv_data_md5_hash_read=malloc(MD5_STRING_SIZE); - - memset(nv_data_md5_hash_read, 0, MD5_STRING_SIZE); - memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE); - - /* Read the newly-written nv_data.bin. */ - nv_data_p=ipc_file_read(client, "/efs/nv_data.bin", NV_DATA_SIZE, NV_DATA_SIZE / 10); - - /* Compute the MD5 hash for nv_data.bin. */ - nv_data_md5_compute(nv_data_p, NV_DATA_SIZE, nv_data_md5_hash); - md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash); - - free(nv_data_p); - - /* Open the backup file MD5 hash. */ - fd=open("/efs/.nv_data.bak.md5", O_RDONLY); - - /* Read the md5 stored in the file. */ - read(fd, nv_data_md5_hash_read, MD5_STRING_SIZE); - - /* Add 0x0 to end the string: not sure this is part of the file. */ - nv_data_md5_hash_read[MD5_STRING_SIZE - 1]='\0'; - - ipc_client_log(client, "nv_data_backup_restore: computed MD5: %s read MD5: %s\n", - nv_data_md5_hash_string, nv_data_md5_hash_read); - - /* Make sure both hashes are the same. */ - if(strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0) - { - ipc_client_log(client, "nv_data_md5_check: MD5 hash mismatch\n"); - nv_data_generate(client); - nv_data_backup_create(client); - return; - } - - close(fd); - - /* Write the MD5 hash in nv_data.bin.md5. */ - fd=open("/efs/nv_data.bin.md5", O_RDWR | O_CREAT, 0644); - - write(fd, nv_data_md5_hash_string, MD5_STRING_SIZE); - - close(fd); - - free(nv_data_md5_hash_string); - free(nv_data_md5_hash_read); - - fd=open("/efs/.nv_state", O_RDWR | O_CREAT, 0644); - - data='1'; - write(fd, &data, sizeof(data)); - - close(fd); - - ipc_client_log(client, "nv_data_backup_create: exit\n"); -} - -void nv_data_check(struct ipc_client *client) -{ - struct stat nv_stat; - int nv_state_fd=-1; - int nv_state=0; - - ipc_client_log(client, "nv_data_check: enter\n"); - - if(stat("/efs/nv_data.bin", &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_check: nv_data.bin missing\n"); - nv_data_backup_restore(client); - stat("/efs/nv_data.bin", &nv_stat); - } - - if(nv_stat.st_size != NV_DATA_SIZE) - { - ipc_client_log(client, "nv_data_check: wrong nv_data.bin size\n"); - nv_data_backup_restore(client); - } - - if(stat("/efs/.nv_data.bak", &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_check: .nv_data.bak missing\n"); - nv_data_backup_create(client); - } - - if(stat("/efs/nv_data.bin.md5", &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_check: nv_data.bin.md5 missing\n"); - nv_data_backup_create(client); - } - - nv_state_fd=open("/efs/.nv_state", O_RDONLY); - - if(nv_state_fd < 0 || fstat(nv_state_fd, &nv_stat) < 0) - { - ipc_client_log(client, "nv_data_check: .nv_state missing\n"); - nv_data_backup_restore(client); - } - - read(nv_state_fd, &nv_state, sizeof(nv_state)); - - close(nv_state_fd); - - if(nv_state != '1') - { - ipc_client_log(client, "nv_data_check: bad nv_state\n"); - nv_data_backup_restore(client); - } - - ipc_client_log(client, "nv_data_check: everything should be alright\n"); - ipc_client_log(client, "nv_data_check: exit\n"); -} - -void nv_data_md5_check(struct ipc_client *client) -{ - struct stat nv_stat; - uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH]; - char *nv_data_md5_hash_string; - char *nv_data_md5_hash_read; - void *nv_data_p; - - int fd; - uint8_t *data_p; - - ipc_client_log(client, "nv_data_md5_check: enter\n"); - - nv_data_md5_hash_string=malloc(MD5_STRING_SIZE); - nv_data_md5_hash_read=malloc(MD5_STRING_SIZE); - - memset(nv_data_md5_hash_read, 0, MD5_STRING_SIZE); - memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE); - - nv_data_p=ipc_file_read(client, "/efs/nv_data.bin", NV_DATA_SIZE, 1024); - data_p=nv_data_p; - - nv_data_md5_compute(data_p, NV_DATA_SIZE, nv_data_md5_hash); - - md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash); - - free(nv_data_p); - - fd=open("/efs/nv_data.bin.md5", O_RDONLY); - - /* Read the md5 stored in the file. */ - read(fd, nv_data_md5_hash_read, MD5_STRING_SIZE); - - /* Add 0x0 to end the string: not sure this is part of the file. */ - nv_data_md5_hash_read[MD5_STRING_SIZE - 1]='\0'; - - ipc_client_log(client, "nv_data_md5_check: computed MD5: %s read MD5: %s\n", - nv_data_md5_hash_string, nv_data_md5_hash_read); - - if(strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0) - { - ipc_client_log(client, "nv_data_md5_check: MD5 hash mismatch\n"); - nv_data_backup_restore(client); - } - - free(nv_data_md5_hash_string); - free(nv_data_md5_hash_read); - - ipc_client_log(client, "nv_data_md5_check: exit\n"); -} - -// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.h b/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.h deleted file mode 100644 index e82f3da..0000000 --- a/samsung-ipc/device/galaxysmtd/galaxysmtd_nv_data.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> - * - * libsamsung-ipc is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsamsung-ipc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef __GALAXYSMTD_NV_DATA_H__ -#define __GALAXYSMTD_NV_DATA__ - -#include <radio.h> - -#define NV_DATA_MD5_SECRET "Samsung_Android_RIL" -#define NV_DATA_SIZE 0x200000 - -#define MD5_STRING_SIZE MD5_DIGEST_LENGTH * 2 + 1 - -void md5hash2string(char *out, uint8_t *in); -void nv_data_generate(struct ipc_client *client); -void nv_data_md5_compute(void *data_p, int size, void *hash); -void nv_data_backup_create(struct ipc_client *client); -void nv_data_backup_restore(struct ipc_client *client); -void nv_data_check(struct ipc_client *client); -void nv_data_md5_check(struct ipc_client *client); - -#endif - -// vim:ts=4:sw=4:expandtab |