aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2020-07-16 17:49:35 +0200
committerDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2020-07-16 23:21:38 +0200
commitad8c4b6aca3dcd8376c18ada456936e0074f8c7a (patch)
treebc38fac149710a7e9743b052805353ca91ab3ec0
parentf4f26a72c7eacdc4c6617170fad01b1160f2b209 (diff)
downloadhardware_replicant_libsamsung-ipc-patches-todo/modem-abstraction-modem-partitions.tar.gz
hardware_replicant_libsamsung-ipc-patches-todo/modem-abstraction-modem-partitions.tar.bz2
hardware_replicant_libsamsung-ipc-patches-todo/modem-abstraction-modem-partitions.zip
This is a test to see if we can make an abstraction for the modem OS partition loading. The concept behind that is pretty easy to understand: - There is a modem OS partition - This has has sub-partitions - The sub-partitions need to be loaded in the modem Given that: - The loading code of some functions like xmm626_*_psi_load is very similar between the MIPI and HSIC functions (the only difference is that it uses a MIPI vs HSIC load function behind the hood). - We now know the partition names - The concept is trivial to understand It would be a good idea to get that part merged first. It will also enable to cleanup a lot the device codes at the same time, and we could merge part of our other abstraction for the modem as we need a mipi/hsic abstraction for sending the data to the modem. Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-rw-r--r--samsung-ipc/devices/i9300/i9300.c119
-rw-r--r--samsung-ipc/devices/i9300/i9300.h3
-rw-r--r--samsung-ipc/devices/ipc_devices.c1
-rw-r--r--samsung-ipc/devices/ipc_devices.h1
-rw-r--r--samsung-ipc/ipc.c6
-rw-r--r--samsung-ipc/ipc.h3
-rw-r--r--samsung-ipc/modems/xmm626/os_partitions.c215
-rw-r--r--samsung-ipc/modems/xmm626/os_partitions.h58
8 files changed, 342 insertions, 64 deletions
diff --git a/samsung-ipc/devices/i9300/i9300.c b/samsung-ipc/devices/i9300/i9300.c
index 19137de..051439f 100644
--- a/samsung-ipc/devices/i9300/i9300.c
+++ b/samsung-ipc/devices/i9300/i9300.c
@@ -34,10 +34,9 @@
int i9300_boot(struct ipc_client *client)
{
void *modem_image_data = NULL;
- int modem_image_fd = -1;
int modem_boot_fd = -1;
+ int modem_image_fd = -1;
int modem_link_fd = -1;
- unsigned char *p;
int rc;
if (client == NULL)
@@ -45,30 +44,9 @@ int i9300_boot(struct ipc_client *client)
ipc_client_log(client, "Starting i9300 modem boot");
- modem_image_fd = open(I9300_MODEM_IMAGE_DEVICE, O_RDONLY);
- if (modem_image_fd < 0) {
- ipc_client_log(client, "Opening modem image device failed");
- goto error;
- }
- ipc_client_log(client, "Opened modem image device");
-
- modem_image_data = mmap(0, I9300_MODEM_IMAGE_SIZE, PROT_READ,
- MAP_SHARED, modem_image_fd, 0);
- if (modem_image_data == NULL ||
- modem_image_data == (void *) 0xffffffff) {
- ipc_client_log(client,
- "Mapping modem image data to memory failed");
- goto error;
- }
- ipc_client_log(client, "Mapped modem image data to memory");
-
- modem_boot_fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE,
- O_RDWR | O_NOCTTY | O_NONBLOCK);
- if (modem_boot_fd < 0) {
- ipc_client_log(client, "Opening modem boot device failed");
+ rc = xmm626_open(client);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Opened modem boot device");
modem_link_fd = open(XMM626_SEC_MODEM_LINK_PM_DEVICE, O_RDWR);
if (modem_link_fd < 0) {
@@ -100,25 +78,15 @@ int i9300_boot(struct ipc_client *client)
}
ipc_client_log(client, "Waited for link connected");
- p = (unsigned char *) modem_image_data + I9300_PSI_OFFSET;
-
- rc = xmm626_hsic_psi_send(client, modem_boot_fd, (void *) p,
- I9300_PSI_SIZE);
- if (rc < 0) {
- ipc_client_log(client, "Sending XMM626 HSIC PSI failed");
+ rc = xmm626_load_os_partition(client, MODEM_OS_PARTITION_PSIRAM,
+ modem_boot_fd);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Sent XMM626 HSIC PSI");
- p = (unsigned char *) modem_image_data + I9300_EBL_OFFSET;
-
- rc = xmm626_hsic_ebl_send(client, modem_boot_fd, (void *) p,
- I9300_EBL_SIZE);
- if (rc < 0) {
- ipc_client_log(client, "Sending XMM626 HSIC EBL failed");
+ rc = xmm626_load_os_partition(client, MODEM_OS_PARTITION_EBL,
+ modem_boot_fd);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Sent XMM626 HSIC EBL");
rc = xmm626_hsic_port_config_send(client, modem_boot_fd);
if (rc < 0) {
@@ -128,34 +96,22 @@ int i9300_boot(struct ipc_client *client)
}
ipc_client_log(client, "Sent XMM626 HSIC port config");
- p = (unsigned char *) modem_image_data + I9300_SEC_START_OFFSET;
-
- rc = xmm626_hsic_sec_start_send(client, modem_boot_fd, (void *) p,
- I9300_SEC_START_SIZE);
- if (rc < 0) {
- ipc_client_log(client, "Sending XMM626 HSIC SEC start failed");
+ rc = xmm626_load_os_partition(client, MODEM_OS_PARTITION_SECPACK,
+ modem_boot_fd);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Sent XMM626 HSIC SEC start");
-
- p = (unsigned char *) modem_image_data + I9300_FIRMWARE_OFFSET;
- rc = xmm626_hsic_firmware_send(client, modem_boot_fd, (void *) p,
- I9300_FIRMWARE_SIZE);
- if (rc < 0) {
- ipc_client_log(client, "Sending XMM626 HSIC firmware failed");
+ rc = xmm626_load_os_partition(client, MODEM_OS_PARTITION_MAIN,
+ modem_boot_fd);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Sent XMM626 HSIC firmware");
- rc = xmm626_hsic_nv_data_send(client, modem_boot_fd);
- if (rc < 0) {
- ipc_client_log(client, "Sending XMM626 HSIC nv_data failed");
+ rc = xmm626_load_os_partition(client, MODEM_OS_PARTITION_NV,
+ modem_boot_fd);
+ if (rc < 0)
goto error;
- }
- ipc_client_log(client, "Sent XMM626 HSIC nv_data");
- rc = xmm626_hsic_sec_end_send(client, modem_boot_fd);
+ rc = xmm626_load_end(client, modem_boot_fd);
if (rc < 0) {
ipc_client_log(client, "Sending XMM626 HSIC SEC end failed");
goto error;
@@ -387,6 +343,37 @@ int i9300_data_destroy(__attribute__((unused)) struct ipc_client *client,
return 0;
}
+struct modem_os_subpartition i9300_modem_os_subpartitions_specs[] = {
+ {
+ .type = MODEM_OS_PARTITION_PSIRAM,
+ .offset = 0x1000,
+ .size = 0xE000,
+ },
+ {
+ .type = MODEM_OS_PARTITION_EBL,
+ .offset = 0xF000,
+ .size = 0x19000,
+ },
+ {
+ .type = MODEM_OS_PARTITION_MAIN,
+ .offset = 0x28000,
+ .size = 0x9D7800,
+ },
+ {
+ .type = MODEM_OS_PARTITION_SECPACK,
+ .offset = 0x9FF800,
+ .size = 0x800,
+ },
+ {
+ .type = MODEM_OS_PARTITION_NV,
+ .offset = 0xA00000,
+ .size = 0x200000,
+ },
+ {
+ /* Sentinel */
+ },
+}
+
struct ipc_client_ops i9300_fmt_ops = {
.boot = i9300_boot,
.send = xmm626_kernel_smdk4412_fmt_send,
@@ -430,3 +417,9 @@ struct ipc_client_nv_data_specs i9300_nv_data_specs = {
.nv_data_size = XMM626_NV_DATA_SIZE,
.nv_data_chunk_size = XMM626_NV_DATA_CHUNK_SIZE,
};
+
+struct ipc_client_modem_os_partition_specs i9300_modem_os_partition_specs = {
+ .path = I9300_MODEM_IMAGE_DEVICE,
+ .size = I9300_MODEM_IMAGE_SIZE,
+ .subpartition_specs = i9300_modem_os_subpartitions_specs,
+};
diff --git a/samsung-ipc/devices/i9300/i9300.h b/samsung-ipc/devices/i9300/i9300.h
index 2cd011d..52cf17e 100644
--- a/samsung-ipc/devices/i9300/i9300.h
+++ b/samsung-ipc/devices/i9300/i9300.h
@@ -43,5 +43,6 @@ extern struct ipc_client_ops i9300_rfs_ops;
extern struct ipc_client_handlers i9300_handlers;
extern struct ipc_client_gprs_specs i9300_gprs_specs;
extern struct ipc_client_nv_data_specs i9300_nv_data_specs;
-
+extern struct ipc_client_modem_os_partition_specs i9300_modem_os_partition_specs;
+
#endif /* __I9300_H__ */
diff --git a/samsung-ipc/devices/ipc_devices.c b/samsung-ipc/devices/ipc_devices.c
index c94d030..db78e85 100644
--- a/samsung-ipc/devices/ipc_devices.c
+++ b/samsung-ipc/devices/ipc_devices.c
@@ -132,6 +132,7 @@ struct ipc_device_desc ipc_devices[] = {
.handlers = &i9300_handlers,
.gprs_specs = &i9300_gprs_specs,
.nv_data_specs = &i9300_nv_data_specs,
+ .modem_os_partition_specs = &i9300_modem_os_partition_specs,
},
{
.name = "n7100",
diff --git a/samsung-ipc/devices/ipc_devices.h b/samsung-ipc/devices/ipc_devices.h
index 176607c..bdcbba6 100644
--- a/samsung-ipc/devices/ipc_devices.h
+++ b/samsung-ipc/devices/ipc_devices.h
@@ -42,6 +42,7 @@ struct ipc_device_desc {
struct ipc_client_handlers *handlers;
struct ipc_client_gprs_specs *gprs_specs;
struct ipc_client_nv_data_specs *nv_data_specs;
+ struct ipc_client_modem_os_partition_specs *modem_os_partition_specs;
};
extern struct ipc_device_desc ipc_devices[];
diff --git a/samsung-ipc/ipc.c b/samsung-ipc/ipc.c
index 48c0450..7daf978 100644
--- a/samsung-ipc/ipc.c
+++ b/samsung-ipc/ipc.c
@@ -215,6 +215,12 @@ static struct ipc_client *ipc_transport_client_create(int type)
client->gprs_specs = ipc_devices[device_index].gprs_specs;
client->nv_data_specs = ipc_devices[device_index].nv_data_specs;
+ /* Not all devices currently implement that
+ * TODO: Remove the check when implemented
+ */
+ if (ipc_devices[device_index].modem_os_partition_specs)
+ client->modem_os_partition_specs = ipc_devices[device_index].modem_os_partition_specs;
+
/* Handlers can be modified */
client->handlers = (struct ipc_client_handlers *) calloc(
1, sizeof(struct ipc_client_handlers));
diff --git a/samsung-ipc/ipc.h b/samsung-ipc/ipc.h
index 1cfa757..724569f 100644
--- a/samsung-ipc/ipc.h
+++ b/samsung-ipc/ipc.h
@@ -23,6 +23,8 @@
#include <samsung-ipc.h>
+#include "modems/xmm626/os_partitions.h"
+
#ifndef __IPC_H__
#define __IPC_H__
@@ -98,6 +100,7 @@ struct ipc_client {
struct ipc_client_handlers *handlers;
struct ipc_client_gprs_specs *gprs_specs;
struct ipc_client_nv_data_specs *nv_data_specs;
+ struct ipc_client_modem_os_partition_specs *modem_os_partition_specs;
};
/*
diff --git a/samsung-ipc/modems/xmm626/os_partitions.c b/samsung-ipc/modems/xmm626/os_partitions.c
new file mode 100644
index 0000000..1f2e949
--- /dev/null
+++ b/samsung-ipc/modems/xmm626/os_partitions.c
@@ -0,0 +1,215 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * Based on the incomplete C++ implementation which is:
+ * Copyright (C) 2012 Sergey Gridasov <grindars@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 2 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 "ipc.h"
+#include "modems/modem.h"
+#include "modems/xmm626/os_partitions.h"
+#include "modems/xmm626/xmm626.h"
+
+struct xmm2626_os_partitions_pdata pdata {
+ int fd;
+ void *data;
+};
+
+// TODO
+extern struct modem_os_partition i9300_modem_os_partitions;
+int os_partition_match(struct ipc_client *client,
+ struct modem_os_partition *partition[])
+{
+
+}
+
+// todo: move in specific helper file
+char *block_device_dirs[] = {
+ "/dev/disk",
+ "/dev/block/",
+}
+
+int try_path(char* partition)
+{
+ // for path in block_device_dirs
+ // try if exists
+ // return if exists
+}
+
+int get_modem_partition_file()
+{
+ // TODO: write a generic function to get multiple block device prefix
+ // and use it here
+ return I9300_MODEM_IMAGE_DEVICE;
+}
+
+int xmm626_modem_os_partition_fd(struct ipc_client *client)
+{
+ /* TODO */
+// return client->[...]->pdata->fd;
+}
+
+int xmm626_modem_os_partition_open(struct ipc_client *client)
+{
+ char* partition_file = client->modem_os_partition_specs->path;
+ size_t partition_size = client->modem_os_partition_specs->size;
+
+ pdata->fd = open(partition_file, O_RDONLY);
+ if (pdata->fd < 0) {
+ ipc_client_log(client, "Opening modem image device failed");
+ goto error;
+ }
+ ipc_client_log(client, "Opened modem image device");
+
+ pdata->data = mmap(0, partition_size, PROT_READ, MAP_SHARED, pdata->fd,
+ 0);
+ if (pdata->data == NULL || pdata->data == (void *) 0xffffffff) {
+ ipc_client_log(client,
+ "Mapping modem image data to memory failed");
+ goto error;
+ }
+ ipc_client_log(client, "Mapped modem image data to memory");
+
+ pdata->fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE,
+ O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (pdata->fd < 0) {
+ ipc_client_log(client, "Opening modem boot device failed");
+ goto error;
+ }
+ ipc_client_log(client, "Opened modem boot device");
+
+error:
+ rc = -1;
+
+complete:
+ if (pdata->data != NULL)
+ munmap(modem_image_data, partition_size);
+
+ if (pdata->fd >= 0)
+ close(pdata->fd);
+
+ return rc;
+
+}
+
+int xmm626_modem_os_partition_close(struct ipc_client *client,
+ struct xmm2626_os_partitions_pdata *pdata)
+{
+ if (pdata->fd >= 0)
+ return close(pdata_fd);
+
+ return 0;
+}
+
+int xmm626_load_os_subpartition(struct ipc_client *client,
+ enum modem_os_partition type)
+{
+ // TODO: get partition data
+ // struct modem_os_partition *partition
+ // TODO match partition data
+
+ //TODO: some checks
+ // if ff == 0
+
+ switch (partition->type) {
+ case MODEM_OS_PARTITION_PSIRAM:
+ // TODO: MIPI/HSIC
+ return xmm626_psi_send(client, pdata->fd,
+ pdata->data,
+ psiram_size);
+ case MODEM_OS_PARTITION_EBL:
+ // TODO: MIPI/HSIC
+ int xmm626_hsic_ebl_send(client, int device_fd,
+ const void *ebl_data, size_t ebl_size);
+
+ case MODEM_OS_PARTITION_MAIN:
+ return xmm626_send_main_partition(client, device_fd,
+ partition->data,
+ partition->size);
+ case MODEM_OS_PARTITION_SECPACK:
+ // TODO: MIPI/HSIC
+ return xmm626_hsic_sec_end_send(client, device_fd);
+
+ case MODEM_OS_PARTITION_NV:
+ return xmm626_nv_data_send(client, device_fd);
+ }
+
+ //ipc_client_log(client, "Loading %s partition into the XMM626 modem failed");
+ //or
+ //ipc_client_log(client, "Loading %s partition into the XMM626 modem failed");
+}
+
+
+int xmm626_send_main_partition(struct ipc_client *client, int device_fd,
+ const void *firmware_data, size_t firmware_size)
+{
+ int rc;
+
+ if (client == NULL || device_fd < 0 || firmware_data == NULL ||
+ firmware_size == 0) {
+ return -1;
+ }
+
+ rc = modem_data_send(client, device_fd, firmware_data, firmware_size,
+ XMM626_FIRMWARE_ADDRESS);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm626_nv_data_send(struct ipc_client *client, int device_fd)
+{
+ void *nv_data = NULL;
+ size_t nv_size;
+ int rc;
+
+ if (client == NULL || device_fd < 0)
+ return -1;
+
+ nv_size = ipc_client_nv_data_size(client);
+ if (nv_size == 0)
+ return -1;
+
+ nv_data = ipc_nv_data_load(client);
+ if (nv_data == NULL) {
+ ipc_client_log(client, "Loading nv_data failed");
+ goto error;
+ }
+ ipc_client_log(client, "Loaded nv_data");
+
+ rc = modem_data_send(client, device_fd, nv_data, nv_size,
+ XMM626_NV_DATA_ADDRESS);
+ if (rc < 0)
+ goto error;
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (nv_data != NULL)
+ free(nv_data);
+
+ return rc;
+}
diff --git a/samsung-ipc/modems/xmm626/os_partitions.h b/samsung-ipc/modems/xmm626/os_partitions.h
new file mode 100644
index 0000000..6166200
--- /dev/null
+++ b/samsung-ipc/modems/xmm626/os_partitions.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+ *
+ * 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 2 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 XMM626_OS_PARTITIONS
+#define XMM626_OS_PARTITIONS
+
+/* Current function/partition mapping
+ * TODO: migrate functions
+ * +-----------------+-----------+
+ * | Function | Partition |
+ * +-----------------+-----------+
+ * | psi | PSIRAM |
+ * | ebl | EBL |
+ * | firmware | MAIN |
+ * | sec_start | SECPACK |
+ * | device specific | NV |
+ * +-----------------+-----------+
+ */
+enum modem_os_partition {
+ MODEM_OS_PARTITION_HEADER = 0,
+ MODEM_OS_PARTITION_PSIRAM,
+ MODEM_OS_PARTITION_EBL,
+ MODEM_OS_PARTITION_MAIN,
+ MODEM_OS_PARTITION_SECPACK,
+ MODEM_OS_PARTITION_NV,
+};
+
+struct ipc_client_modem_os_subpartition {
+ const enum modem_os_partition type;
+ void *data;
+ const size_t offset;
+ const size_t size;
+};
+
+struct ipc_client_os_partition_specs {
+ char* path;
+ size_t size;
+ struct ipc_client_modem_os_subpartition *subpartitions_specs[];
+};
+
+#endif /* XMM626_OS_PARTITIONS */