summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/shared/firmware.h
blob: 3cd233c3b6ecade70915e7bd412aec0a8b981404 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* zenutils - Utilities for working with creative firmwares.
 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
 *
 * This program 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.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef ZEN_FIRMWARE_H_INCLUDED
#define ZEN_FIRMWARE_H_INCLUDED

#include <list>
#include <utils.h>

namespace zen {
    struct firmware_header_t
    {
        dword tag;
        dword size;
    }; //struct firmware_header_t

    class firmware_entry
    {
    public:
        firmware_entry(bool big_endian);
        firmware_entry(const firmware_entry& copy);
        firmware_entry& operator=(const firmware_entry& right);

        bool read(std::istream& is);
        bool write(std::ostream& os) const;

        bool is_big_endian() const;
        const firmware_header_t& get_header() const;
        firmware_header_t& get_header();
        const shared::bytes& get_bytes() const;
        shared::bytes& get_bytes();

        std::string get_name() const;
        std::string get_content_name() const;
        size_t get_content_offset() const;
        size_t calc_size() const;

    protected:
        void assign(const firmware_entry& copy);

    private:
        bool _big_endian;
        firmware_header_t _header;
        shared::bytes _bytes;
    }; //class firmware_entry

    typedef std::list<firmware_entry> firmware_entries;

    class firmware_archive
    {
    public:
        firmware_archive(bool big_endian);
        firmware_archive(const firmware_archive& copy);
        firmware_archive& operator=(const firmware_archive& right);

        bool read(std::istream& is);
        bool write(std::ostream& os) const;

        bool is_big_endian() const;
        const firmware_entries& get_children() const;
        firmware_entries& get_children();
        const firmware_entries& get_neighbours() const;
        firmware_entries& get_neighbours();
        bool is_signed() const;
        size_t calc_size() const;

    protected:
        void assign(const firmware_archive& copy);

    private:
        firmware_entries _children;
        firmware_entries _neighbours;
        bool _big_endian;
    }; //class firmware_archive
}; //namespace zen

#endif //ZEN_FIRMWARE_ARCHIVE_H_INCLUDED
n371'>371 372 373 374 375 376 377
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2002 by Alan Korr
 *
 * This program 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.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#ifndef SYSTEM_ARM_H
#define SYSTEM_ARM_H

/* Common to all ARM_ARCH */
#define nop \
  asm volatile ("nop")

void __div0(void);

#define IRQ_ENABLED      0x00
#define IRQ_DISABLED     0x80
#define IRQ_STATUS       0x80
#define FIQ_ENABLED      0x00
#define FIQ_DISABLED     0x40
#define FIQ_STATUS       0x40
#define IRQ_FIQ_ENABLED  0x00
#define IRQ_FIQ_DISABLED 0xc0
#define IRQ_FIQ_STATUS   0xc0
#define HIGHEST_IRQ_LEVEL IRQ_DISABLED

#define set_irq_level(status) \
    set_interrupt_status((status), IRQ_STATUS)
#define set_fiq_status(status) \
    set_interrupt_status((status), FIQ_STATUS)

#define disable_irq_save() \
    disable_interrupt_save(IRQ_STATUS)
#define disable_fiq_save() \
    disable_interrupt_save(FIQ_STATUS)

#define restore_irq(cpsr) \
    restore_interrupt(cpsr)
#define restore_fiq(cpsr) \
    restore_interrupt(cpsr)

#define disable_irq() \
    disable_interrupt(IRQ_STATUS)
#define enable_irq() \
    enable_interrupt(IRQ_STATUS)
#define disable_fiq() \
    disable_interrupt(FIQ_STATUS)
#define enable_fiq() \
    enable_interrupt(FIQ_STATUS)

#define irq_enabled() \
    interrupt_enabled(IRQ_STATUS)
#define fiq_enabled() \
    interrupt_enabled(FIQ_STATUS)
#define ints_enabled() \
    interrupt_enabled(IRQ_FIQ_STATUS)

#define irq_enabled_checkval(val) \
    (((val) & IRQ_STATUS) == 0)
#define fiq_enabled_checkval(val) \
    (((val) & FIQ_STATUS) == 0)
#define ints_enabled_checkval(val) \
    (((val) & IRQ_FIQ_STATUS) == 0)

/* We run in SYS mode */
#define is_thread_context() \
    (get_processor_mode() == 0x1f)

/* Core-level interrupt masking */

static inline int set_interrupt_status(int status, int mask)
{
    unsigned long cpsr;
    int oldstatus;
    /* Read the old levels and set the new ones */
    asm volatile (
        "mrs    %1, cpsr        \n"
        "bic    %0, %1, %[mask] \n"
        "orr    %0, %0, %2      \n"
        "msr    cpsr_c, %0      \n"
        : "=&r,r"(cpsr), "=&r,r"(oldstatus)
        : "r,i"(status & mask), [mask]"i,i"(mask));

    return oldstatus;
}

static inline void restore_interrupt(int cpsr)
{
    /* Set cpsr_c from value returned by disable_interrupt_save
     * or set_interrupt_status */
    asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
}

static inline bool interrupt_enabled(int status)
{
    unsigned long cpsr;
    asm ("mrs %0, cpsr" : "=r"(cpsr));
    return (cpsr & status) == 0;
}

static inline unsigned long get_processor_mode(void)
{
    unsigned long cpsr;
    asm ("mrs %0, cpsr" : "=r"(cpsr));
    return cpsr & 0x1f;
}

/* ARM_ARCH version section for architecture*/

#if ARM_ARCH >= 6
static inline uint16_t swap16_hw(uint16_t value)
    /*
      result[15..8] = value[ 7..0];
      result[ 7..0] = value[15..8];
    */
{
    uint32_t retval;
    asm ("revsh %0, %1"                         /* xxAB */
        : "=r"(retval) : "r"((uint32_t)value)); /* xxBA */
    return retval;
}

static inline uint32_t swap32_hw(uint32_t value)
    /*
      result[31..24] = value[ 7.. 0];
      result[23..16] = value[15.. 8];
      result[15.. 8] = value[23..16];
      result[ 7.. 0] = value[31..24];
    */
{
    uint32_t retval;
    asm ("rev %0, %1"                 /* ABCD */
        : "=r"(retval) : "r"(value)); /* DCBA */
    return retval;
}

static inline uint32_t swap_odd_even32_hw(uint32_t value)
{
    /*
      result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
      result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
    */
    uint32_t retval;
    asm ("rev16 %0, %1"               /* ABCD */
        : "=r"(retval) : "r"(value)); /* BADC */
    return retval;
}

static inline void enable_interrupt(int mask)
{
    /* Clear I and/or F disable bit */
    /* mask is expected to be constant and so only relevent branch
     * is preserved */
    switch (mask & IRQ_FIQ_STATUS)
    {
    case IRQ_STATUS:
        asm volatile ("cpsie i");
        break;
    case FIQ_STATUS:
        asm volatile ("cpsie f");
        break;
    case IRQ_FIQ_STATUS:
        asm volatile ("cpsie if");
        break;
    }
}

static inline void disable_interrupt(int mask)
{
    /* Set I and/or F disable bit */