diff options
author | PaulK <contact@paulk.fr> | 2012-01-28 11:33:48 +0100 |
---|---|---|
committer | PaulK <contact@paulk.fr> | 2012-01-28 11:45:10 +0100 |
commit | dcdee945b6f58d0bd1d989d270d562d86d8b15b3 (patch) | |
tree | 7212c81c7b7a1d32ecc80f61171f082d49cb61ff /samsung-ipc/device | |
parent | af1854b3be3410f3090a967cfee8b387d6ad3950 (diff) | |
download | external_libsamsung-ipc-dcdee945b6f58d0bd1d989d270d562d86d8b15b3.zip external_libsamsung-ipc-dcdee945b6f58d0bd1d989d270d562d86d8b15b3.tar.gz external_libsamsung-ipc-dcdee945b6f58d0bd1d989d270d562d86d8b15b3.tar.bz2 |
Added support for aries devices (galaxy s, galaxy tab, perhaps more)
Thanks to Igor Almeida for contributing to bootstrap code and for his help with galaxy s!
Diffstat (limited to 'samsung-ipc/device')
-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 |