summaryrefslogtreecommitdiffstats
path: root/Tools/Source/PcdTools/org/tianocore/pcd/entity/MemoryDatabaseManager.java
blob: 7a874699677801b08a5ab0c6ec2149604f249039 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
/** @file
  MemoryDatabaseManager class.

  Database hold all PCD information comes from SPD, MSA, FPD file in memory.
 
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
 
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/
package org.tianocore.pcd.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.tianocore.pcd.entity.UsageIdentification;
import org.tianocore.pcd.exception.EntityException;

/** Database hold all PCD information comes from SPD, MSA, FPD file in memory.
**/
public class MemoryDatabaseManager {
    ///
    ///  Memory database. The string "cName + SpaceNameGuid" is primary key.
    ///  memory database is in global scope, and it will be used for others PCD tools.
    ///
    private static Map<String, Token>  memoryDatabase       = null;

    ///
    /// Before build a module, the used libary will be build firstly, the PCD of these
    /// libarry is inheritted by the module, so stored module's PCD information as PCD
    /// context of building libary.
    /// 
    public static List<UsageInstance> UsageInstanceContext = null;

    ///
    /// Current module name, if now is buiding library, this value indicate this library
    /// is for building what module.
    /// 
    public static String CurrentModuleName                 = null;

    ///
    /// String for PCD PEIM and DXE autogen file
    /// 
    public static String PcdPeimHString                    = "";
    public static String PcdPeimCString                    = "";
    public static String PcdDxeHString                     = "";
    public static String PcdDxeCString                     = "";

    /**
      Constructure function
    **/
    public MemoryDatabaseManager() {
        //
        // Allocate memory for new database in global scope.
        //
        if (memoryDatabase == null) {
            memoryDatabase = new HashMap<String, Token>();
        }
    }

    /**
      Judege whether token exists in memory database
      
      @param primaryKey    the primaryKey for searching token
      
      @retval  TRUE  - token already exist in database.
      @retval  FALSE - token does not exist in database.
    **/
    public boolean isTokenInDatabase(String primaryKey) {
        return (memoryDatabase.get(primaryKey) != null);
    }

    /**
      Add a pcd token into memory database.
      
      @param primaryKey   the primary key for searching token
      @param token        token instance
    **/
    public void addTokenToDatabase(String primaryKey, Token token) {
        memoryDatabase.put(primaryKey, token);
    }

    /**
      Get a token instance from memory database with primary key.
  
      @param primaryKey   the primary key for searching token
    
      @return token instance.
    **/
    public Token getTokenByKey(String primaryKey) {
        return memoryDatabase.get(primaryKey);
    }

    /**
      Get the number of PCD token record in memory database.
      
      @return the number of PCD token record in memory database.
    **/
    public int getDBSize() {
        return memoryDatabase.size();
    }

    /**
      Get the token record array contained all PCD token in memory database.
      
      @return the token record array contained all PCD token in memory database.
    **/
    public Token[] getRecordArray() {
        Token[]     tokenArray  = null;
        Object[]    dataArray   = null;
        Map.Entry   entry       = null;
        int         index       = 0;

        if (memoryDatabase == null) {
            return null;
        }

        dataArray  = memoryDatabase.entrySet().toArray();
        tokenArray = new Token[memoryDatabase.size()];
        for (index = 0; index < memoryDatabase.size(); index ++) {
            entry =(Map.Entry) dataArray [index];
            tokenArray[index] =(Token) entry.getValue();
        }

        return tokenArray;
    }

    /**
       Get record array only contains DYNAMIC or DYNAMIC_EX type PCD.
       
       @return ArrayList
     */
    private ArrayList getDynamicRecordArray() {
        Token[]     tokenArray  =   getRecordArray();
        int         index       =   0;
        ArrayList<Token>   al   =   new ArrayList<Token>();

        for (index = 0; index < tokenArray.length; index++) {
            if (tokenArray[index].isDynamicPCD) {
                al.add(tokenArray[index]);
            }
        }

        return al;
    }


    /**
      Get the token record array contained all PCD token referenced by PEI phase.
          The output array is sorted based on descending order of the size of alignment for each feilds.

      @return the token record array contained all PCD token referenced in PEI phase.
      @throws EntityException
    **/
    public void getTwoPhaseDynamicRecordArray(ArrayList<Token> pei, ArrayList<Token> dxe) 
        throws EntityException {
        int                     usageInstanceIndex  =   0;
        int                     index               =   0;
        ArrayList               tokenArrayList      =   getDynamicRecordArray();
        Object[]                usageInstanceArray  =   null;
        UsageInstance           usageInstance       =   null;

        //pei = new ArrayList<Token>();
        //dxe = new ArrayList<Token>();

        for (index = 0; index < tokenArrayList.size(); index++) {
            boolean found   =   false;
            Token       token = (Token) tokenArrayList.get(index);
            if (token.consumers != null) {
                usageInstanceArray = token.consumers.entrySet().toArray();
                for (usageInstanceIndex = 0; usageInstanceIndex < token.consumers.size(); usageInstanceIndex ++) {
                    usageInstance =(UsageInstance) (((Map.Entry)usageInstanceArray[usageInstanceIndex]).getValue());
                    if (usageInstance.isPeiPhaseComponent()) {
                        pei.add(token);
                        found = true;
                        break;
                    }
                }
            }

            //
            // If no PEI components reference the PCD entry, 
            // we check if it is referenced in DXE driver. 
            //
            if (!found) {
                if (token.consumers != null) {
                    usageInstanceArray = token.consumers.entrySet().toArray();
                    for (usageInstanceIndex = 0; usageInstanceIndex < token.consumers.size(); usageInstanceIndex ++) {
                        usageInstance =(UsageInstance) (((Map.Entry)usageInstanceArray[usageInstanceIndex]).getValue());
                        if (usageInstance.isDxePhaseComponent()) {
                            dxe.add(token);
                            found = true;
                            break;
                        }
                    }
                }
                
                if (!found) {
                    if (token.isDynamicPCD && token.consumers.size() == 0) {
                        dxe.add(token);
                    } else {
                        //
                        // We only support Dynamice(EX) type for PEI and DXE phase.
                        // If it is not referenced in either PEI or DXE, throw exception now.
                        //
                        throw new EntityException("[PCD tool Internal Error] Dynamic(EX) PCD Entries are referenced in module that is not in PEI phase nor in DXE phase.");
                    }
                }
            }
        }

        return;
    }

    /**
      Get all PCD record for a module according to module's name, module's GUID,
      package name, package GUID, arch, version information.
     
      @param usageId   the id of UsageInstance.
      
      @return  all usage instance for this module in memory database.
    **/
    public List<UsageInstance> getUsageInstanceArrayByModuleName(UsageIdentification usageId) {

        String primaryKey = UsageInstance.getPrimaryKey(usageId);

        return getUsageInstanceArrayByKeyString(primaryKey);
    }

    /**
       Get all PCD token for a usage instance according to primary key.
       
       @param primaryKey    the primary key of usage instance.
       
       @return List<UsageInstance>
     */
    public List<UsageInstance> getUsageInstanceArrayByKeyString(String primaryKey) {
        Token[]               tokenArray          = null;
        int                   recordIndex         = 0; 
        UsageInstance         usageInstance       = null;
        List<UsageInstance>   returnArray         = new ArrayList<UsageInstance>();

        tokenArray = getRecordArray();

        //
        // Loop to find all PCD record related to current module
        //
        for (recordIndex = 0; recordIndex < getDBSize(); recordIndex ++) {
            if (tokenArray[recordIndex].consumers.size() != 0) {
                usageInstance = tokenArray[recordIndex].consumers.get(primaryKey);
                if (usageInstance != null) {
                    returnArray.add(usageInstance);
                }
            }
        }

        return returnArray;
    }

    /**
      Get all modules name who contains PCD information
     
      @return Array for module name
    **/
    public List<String> getAllModuleArray()
    {
        int                       indexToken    = 0;
        int                       usageIndex    = 0;
        int                       moduleIndex   = 0;
        Token[]                   tokenArray    = null;
        Object[]                  usageInstanceArray = null;
        List<String>              moduleNames   = new ArrayList<String>();
        UsageInstance             usageInstance = null;
        boolean                   bFound        = false;

        tokenArray = getRecordArray();
        //
        // Find all consumer usage instance for retrieving module's name
        //
        for (indexToken = 0; indexToken < getDBSize(); indexToken ++) {
            usageInstanceArray = tokenArray[indexToken].consumers.entrySet().toArray();
            for (usageIndex = 0; usageIndex < tokenArray[indexToken].consumers.size(); usageIndex ++) {
                usageInstance = (UsageInstance)((Map.Entry)usageInstanceArray[usageIndex]).getValue();
                bFound        = false;
                for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) {
                    if (moduleNames.get(moduleIndex).equalsIgnoreCase(usageInstance.getPrimaryKey())) {
                        bFound = true;
                        break;
                    }
                }
                if (!bFound) {
                    moduleNames.add(usageInstance.getPrimaryKey());
                }
            }
        }
        return moduleNames;
    }
}