1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 */
39
40#ifndef __ARCH_ARM_LINUX_ATAG_HH__
41#define __ARCH_ARM_LINUX_ATAG_HH__
42
43#include <cstring>
44#include <string>
45
46#include "base/types.hh"
47
48enum {
49    CoreTag   = 0x54410001,
50    MemTag    = 0x54410002,
51    RevTag    = 0x54410007,
52    SerialTag = 0x54410006,
53    CmdTag    = 0x54410009,
54    NoneTag   = 0x00000000
55};
56
57class AtagHeader
58{
59  protected:
60    uint32_t *storage;
61    uint32_t _size;
62
63  public:
64    /** Tag (normally starts with 'T''A' and 16 bits of number */
65    virtual uint32_t tag() = 0;
66    /** If the header should be 0 size */
67    virtual bool null() { return false; }
68
69    uint32_t size() const { return _size; }
70
71    AtagHeader(uint32_t s)
72        : _size(s)
73    {
74        storage = new uint32_t[size()];
75    }
76
77    virtual ~AtagHeader()
78    {
79        delete[] storage;
80    }
81
82    uint32_t copyOut(uint8_t *p)
83    {
84        storage[0] = null() ? 0 : size();
85        storage[1] = tag();
86        memcpy(p, storage, size() << 2);
87        return size() << 2;
88    }
89};
90
91class AtagCore : public AtagHeader
92{
93  public:
94    static const uint32_t Size = 5;
95    uint32_t tag() { return CoreTag; }
96
97    void flags(uint32_t i) { storage[2] = i; }
98    void pagesize(uint32_t i) { storage[3] = i; }
99    void rootdev(uint32_t i) { storage[4] = i; }
100    AtagCore()
101        : AtagHeader(Size)
102    {}
103};
104
105class AtagMem : public AtagHeader
106{
107  public:
108    static const uint32_t Size = 4;
109    uint32_t tag() { return MemTag; }
110
111    void memSize(uint32_t i) { storage[2] = i; }
112    void memStart(uint32_t i) { storage[3] = i; }
113    AtagMem()
114        : AtagHeader(Size)
115    {}
116};
117
118class AtagRev : public AtagHeader
119{
120  public:
121    static const uint32_t Size = 3;
122    uint32_t tag() { return RevTag; }
123
124    void rev(uint32_t i) { storage[2] = i; }
125    AtagRev()
126        : AtagHeader(Size)
127    {}
128};
129
130
131class AtagSerial : public AtagHeader
132{
133  public:
134    static const uint32_t Size = 4;
135    uint32_t tag() { return SerialTag; }
136
137    void sn(uint64_t i) { storage[2] = (uint32_t)i; storage[3] = i >> 32; }
138    AtagSerial()
139        : AtagHeader(Size)
140    {}
141};
142
143class AtagCmdline : public AtagHeader
144{
145  public:
146    static const uint32_t Size = 3;
147    uint32_t tag() { return CmdTag; }
148
149    void cmdline(const std::string &s)
150    {
151        // Add one for null terminator
152        int len = s.length() + 1;
153
154        // 2 + ceiling(len/4)
155        _size = 2 + ((len + 3) >> 2);
156
157        delete[] storage;
158        storage = new uint32_t[size()];
159        // Initialize the last byte of memory here beacuse it might be slightly
160        // longer than needed and mis-speculation of the NULL in the O3 CPU can
161        // change stats ever so slightly when that happens.
162        storage[size() - 1] = 0;
163        strcpy((char*)&storage[2] , s.c_str());
164    }
165    AtagCmdline()
166        : AtagHeader(Size)
167    {}
168};
169
170class AtagNone : public AtagHeader
171{
172  public:
173    static const uint32_t Size = 2;
174    virtual bool null() { return true; }
175    uint32_t tag() { return NoneTag; }
176    AtagNone()
177        : AtagHeader(Size)
178    {}
179};
180/*
181//
182// example ARM Linux bootloader code
183// this example is distributed under the BSD licence
184// Code taken from http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
185///
186
187// list of possible tags
188#define ATAG_NONE       0x00000000
189#define ATAG_CORE       0x54410001
190#define ATAG_MEM        0x54410002
191#define ATAG_VIDEOTEXT  0x54410003
192#define ATAG_RAMDISK    0x54410004
193#define ATAG_INITRD2    0x54420005
194#define ATAG_SERIAL     0x54410006
195#define ATAG_REVISION   0x54410007
196#define ATAG_VIDEOLFB   0x54410008
197#define ATAG_CMDLINE    0x54410009
198
199// structures for each atag
200struct atag_header {
201        u32 size; // length of tag in words including this header
202        u32 tag;  // tag type
203};
204
205struct atag_core {
206        u32 flags;
207        u32 pagesize;
208        u32 rootdev;
209};
210
211struct atag_mem {
212        u32     size;
213        u32     start;
214};
215
216struct atag_videotext {
217        u8              x;
218        u8              y;
219        u16             video_page;
220        u8              video_mode;
221        u8              video_cols;
222        u16             video_ega_bx;
223        u8              video_lines;
224        u8              video_isvga;
225        u16             video_points;
226};
227
228struct atag_ramdisk {
229        u32 flags;
230        u32 size;
231        u32 start;
232};
233
234struct atag_initrd2 {
235        u32 start;
236        u32 size;
237};
238
239struct atag_serialnr {
240        u32 low;
241        u32 high;
242};
243
244struct atag_revision {
245        u32 rev;
246};
247
248struct atag_videolfb {
249        u16             lfb_width;
250        u16             lfb_height;
251        u16             lfb_depth;
252        u16             lfb_linelength;
253        u32             lfb_base;
254        u32             lfb_size;
255        u8              red_size;
256        u8              red_pos;
257        u8              green_size;
258        u8              green_pos;
259        u8              blue_size;
260        u8              blue_pos;
261        u8              rsvd_size;
262        u8              rsvd_pos;
263};
264
265struct atag_cmdline {
266        char    cmdline[1];
267};
268
269struct atag {
270        struct atag_header hdr;
271        union {
272                struct atag_core         core;
273                struct atag_mem          mem;
274                struct atag_videotext    videotext;
275                struct atag_ramdisk      ramdisk;
276                struct atag_initrd2      initrd2;
277                struct atag_serialnr     serialnr;
278                struct atag_revision     revision;
279                struct atag_videolfb     videolfb;
280                struct atag_cmdline      cmdline;
281        } u;
282};
283*/
284
285
286#endif // __ARCH_ARM_LINUX_ATAG_HH__
287