summaryrefslogtreecommitdiff
path: root/src/glibext/gbincontent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext/gbincontent.c')
-rw-r--r--src/glibext/gbincontent.c392
1 files changed, 390 insertions, 2 deletions
diff --git a/src/glibext/gbincontent.c b/src/glibext/gbincontent.c
index c72ac15..e0c64d4 100644
--- a/src/glibext/gbincontent.c
+++ b/src/glibext/gbincontent.c
@@ -24,6 +24,7 @@
#include "gbincontent.h"
+#include <assert.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
@@ -33,6 +34,9 @@
#include <sys/stat.h>
+#include "../common/endianness.h"
+
+
/* Aire de contenu binaire */
typedef struct _binary_part
@@ -73,6 +77,9 @@ static void g_binary_content_dispose(GBinContent *);
/* Procède à la libération totale de la mémoire. */
static void g_binary_content_finalize(GBinContent *);
+/* Retrouve la zone adaptée pour une localisation de données. */
+static const binary_part *g_binary_content_find_part(const GBinContent *, const vmpa2t *, phys_t *);
+
/* Indique le type défini par la GLib pour les contenus de données. */
@@ -239,10 +246,43 @@ GBinContent *g_binary_content_new_from_file(const char *filename)
}
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture globale demandée. *
+* start = position de la tête de lecture dans la zone. [OUT] *
+* *
+* Description : Retrouve la zone adaptée pour une localisation de données. *
+* *
+* Retour : Partie trouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static const binary_part *g_binary_content_find_part(const GBinContent *content, const vmpa2t *addr, phys_t *start)
+{
+ const binary_part *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+ binary_part *part; /* Zone mémoire manipulée */
+ result = NULL;
+ for (i = 0; i < content->count && result == NULL; i++)
+ {
+ part = &content->parts[i];
+
+ if (mrange_contains_addr(&part->range, addr))
+ result = part;
+
+ }
+ if (result != NULL)
+ *start = compute_vmpa_diff(get_mrange_addr(&result->range), addr);
+
+ return result;
+
+}
/******************************************************************************
@@ -260,19 +300,367 @@ GBinContent *g_binary_content_new_from_file(const char *filename)
* *
******************************************************************************/
-bool g_binary_content_get_raw(const GBinContent *content, const vmpa2t *addr, phys_t length, bin_t *out)
+bool g_binary_content_get_raw(const GBinContent *content, vmpa2t *addr, phys_t length, bin_t *out)
{
+ bool result;
+ phys_t offset;
+
/* FIXME */
- memcpy(out, &content->parts[0].data[get_phy_addr(addr)], length);
+ offset = get_phy_addr(addr);
+
+ memcpy(out, &content->parts[0].data[offset], length);
+
+ advance_vmpa(addr, length);
+
+ return true;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture. *
+* low = position éventuelle des 4 bits visés. [OUT] *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur quatre bits. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_u4(const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian, uint8_t *val)
+{
+ phys_t start; /* Tête de lecture relative */
+ const binary_part *part; /* Zone de mémoire effective */
+ bin_t *data; /* Contenu binaire représenté */
+
+ part = g_binary_content_find_part(content, addr, &start);
+ if (part == NULL) return false;
+
+ if ((get_mrange_length(&part->range) - start) < 1) return false;
+
+ data = part->data;
+
+ if (*low)
+ {
+ *val = data[start] & 0x0f;
+ *low = false;
+ }
+ else
+ {
+ *val = (data[start] & 0xf0) >> 4;
+ *low = true;
+ advance_vmpa(addr, 4);
+ }
+
+ return true;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture. *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur un octet. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_u8(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint8_t *val)
+{
+ phys_t start; /* Tête de lecture relative */
+ const binary_part *part; /* Zone de mémoire effective */
+ bin_t *data; /* Contenu binaire représenté */
+
+ part = g_binary_content_find_part(content, addr, &start);
+ if (part == NULL) return false;
+
+ if ((get_mrange_length(&part->range) - start) < 1) return false;
+
+ data = part->data;
+
+ *val = data[start];
+
+ advance_vmpa(addr, 1);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture. *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur deux octets. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_u16(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint16_t *val)
+{
+ phys_t start; /* Tête de lecture relative */
+ const binary_part *part; /* Zone de mémoire effective */
+ bin_t *data; /* Contenu binaire représenté */
+
+ part = g_binary_content_find_part(content, addr, &start);
+ if (part == NULL) return false;
+
+ if ((get_mrange_length(&part->range) - start) < 2) return false;
+
+ data = part->data;
+
+ switch (endian)
+ {
+ case SRE_LITTLE:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = data[start] | (uint16_t)data[start + 1] << 8;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = data[start + 1] | (uint16_t)data[start] << 8;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+ case SRE_MIDDLE:
+ assert(false); /* TODO */
+ break;
+
+ case SRE_BIG:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = data[start + 1] | (uint16_t)data[start] << 8;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = data[start] | (uint16_t)data[start + 1] << 8;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+
+ }
+
+ advance_vmpa(addr, 2);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture. *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur quatre octets. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_u32(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint32_t *val)
+{
+ phys_t start; /* Tête de lecture relative */
+ const binary_part *part; /* Zone de mémoire effective */
+ bin_t *data; /* Contenu binaire représenté */
+
+ part = g_binary_content_find_part(content, addr, &start);
+ if (part == NULL) return false;
+
+ if ((get_mrange_length(&part->range) - start) < 4) return false;
+
+ data = part->data;
+
+ switch (endian)
+ {
+ case SRE_LITTLE:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = data[start] | (uint32_t)data[start + 1] << 8;
+ *val |= data[start + 2] << 16 | (uint32_t)data[start + 3] << 24;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = data[start + 3] | (uint32_t)data[start + 2] << 8;
+ *val |= data[start + 1] << 16 | (uint32_t)data[start] << 24;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+ case SRE_MIDDLE:
+ assert(false); /* TODO */
+ break;
+
+ case SRE_BIG:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = data[start + 3] | (uint32_t)data[start + 2] << 8;
+ *val |= data[start + 1] << 16 | (uint32_t)data[start] << 24;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = data[start] | (uint32_t)data[start + 1] << 8;
+ *val |= data[start + 2] << 16 | (uint32_t)data[start + 3] << 24;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+
+ }
+
+ advance_vmpa(addr, 4);
return true;
}
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture. *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur huit octets. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_u64(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint64_t *val)
+{
+ phys_t start; /* Tête de lecture relative */
+ const binary_part *part; /* Zone de mémoire effective */
+ bin_t *data; /* Contenu binaire représenté */
+
+ part = g_binary_content_find_part(content, addr, &start);
+ if (part == NULL) return false;
+
+ if ((get_mrange_length(&part->range) - start) < 8) return false;
+ data = part->data;
+ switch (endian)
+ {
+ case SRE_LITTLE:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = (uint64_t)data[start] | (uint64_t)data[start + 1] << 8;
+ *val |= (uint64_t)data[start + 2] << 16 | (uint64_t)data[start + 3] << 24;
+ *val |= (uint64_t)data[start + 4] << 32 | (uint64_t)data[start + 5] << 40;
+ *val |= (uint64_t)data[start + 6] << 48 | (uint64_t)data[start + 7] << 56;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = (uint64_t)data[start + 7] | (uint64_t)data[start + 6] << 8;
+ *val |= (uint64_t)data[start + 5] << 16 | (uint64_t)data[start + 4] << 24;
+ *val |= (uint64_t)data[start + 3] << 32 | (uint64_t)data[start + 2] << 40;
+ *val |= (uint64_t)data[start + 1] << 48 | (uint64_t)data[start] << 56;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+ case SRE_MIDDLE:
+ assert(false); /* TODO */
+ break;
+
+ case SRE_BIG:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *val = (uint64_t)data[start + 7] | (uint64_t)data[start + 6] << 8;
+ *val |= (uint64_t)data[start + 5] << 16 | (uint64_t)data[start + 4] << 24;
+ *val |= (uint64_t)data[start + 3] << 32 | (uint64_t)data[start + 2] << 40;
+ *val |= (uint64_t)data[start + 1] << 48 | (uint64_t)data[start] << 56;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *val = (uint64_t)data[start] | (uint64_t)data[start + 1] << 8;
+ *val |= (uint64_t)data[start + 2] << 16 | (uint64_t)data[start + 3] << 24;
+ *val |= (uint64_t)data[start + 4] << 32 | (uint64_t)data[start + 5] << 40;
+ *val |= (uint64_t)data[start + 6] << 48 | (uint64_t)data[start + 7] << 56;
+
+#else
+
+# error "TODO : extra byte order !"
+
+#endif
+
+ break;
+
+
+ }
+
+ advance_vmpa(addr, 8);
+
+ return true;
+
+}