/* * tbistring.c * * Copyright (C) 2001, 2002, 2003, 2005, 2007, 2012 Imagination Technologies. * * 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. * * String table functions provided as part of the thread binary interface for * Meta processors */ #include <linux/export.h> #include <linux/string.h> #include <asm/tbx.h> /* * There are not any functions to modify the string table currently, if these * are required at some later point I suggest having a seperate module and * ensuring that creating new entries does not interfere with reading old * entries in any way. */ const TBISTR *__TBIFindStr(const TBISTR *start, const char *str, int match_len) { const TBISTR *search = start; bool exact = true; const TBISEG *seg; if (match_len < 0) { /* Make match_len always positive for the inner loop */ match_len = -match_len; exact = false; } else { /* * Also support historic behaviour, which expected match_len to * include null terminator */ if (match_len && str[match_len-1] == '\0') match_len--; } if (!search) { /* Find global string table segment */ seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL, TBID_SEGSCOPE_GLOBAL, TBID_SEGTYPE_STRING)); if (!seg || seg->Bytes < sizeof(TBISTR)) /* No string table! */ return NULL; /* Start of string table */ search = seg->pGAddr; } for (;;) { while (!search->Tag) /* Allow simple gaps which are just zero initialised */ search = (const TBISTR *)((const char *)search + 8); if (search->Tag == METAG_TBI_STRE) { /* Reached the end of the table */ search = NULL; break; } if ((search->Len >= match_len) && (!exact || (search->Len == match_len + 1)) && (search->Tag != METAG_TBI_STRG)) { /* Worth searching */ if (!strncmp(str, (const char *)search->String, match_len)) break; } /* Next entry */ search = (const TBISTR *)((const char *)search + search->Bytes); } return search; } const void *__TBITransStr(const char *str, int len) { const TBISTR *search = NULL; const void *res = NULL; for (;;) { /* Search onwards */ search = __TBIFindStr(search, str, len); /* No translation returns NULL */ if (!search) break; /* Skip matching entries with no translation data */ if (search->TransLen != METAG_TBI_STRX) { /* Calculate base of translation string */ res = (const char *)search->String + ((search->Len + 7) & ~7); break; } /* Next entry */ search = (const TBISTR *)((const char *)search + search->Bytes); } /* Return base address of translation data or NULL */ return res; } EXPORT_SYMBOL(__TBITransStr);