1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CARD - include
3   File:     hash.h
4 
5   Copyright 2007-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16 
17  *---------------------------------------------------------------------------*/
18 #ifndef NITRO_CARD_HASH_H_
19 #define NITRO_CARD_HASH_H_
20 
21 
22 #include <nitro/misc.h>
23 #include <nitro/types.h>
24 #include <nitro/card/types.h>
25 #include <nitro/mi/device.h>
26 
27 
28 #ifdef __cplusplus
29 extern "C"
30 {
31 #endif
32 
33 
34 /*---------------------------------------------------------------------------*/
35 /* Constants */
36 
37 #define CARD_ROM_HASH_SIZE      20
38 
39 
40 /*---------------------------------------------------------------------------*/
41 /* Declarations */
42 
43 struct CARDRomHashSector;
44 struct CARDRomHashBlock;
45 struct CARDRomHashContext;
46 
47 // This structure manages the image cache for various sectors.
48 typedef struct CARDRomHashSector
49 {
50     struct CARDRomHashSector   *next;
51     u32                         index;
52     u32                         offset;
53     void                       *image;
54 }
55 CARDRomHashSector;
56 
57 // This block structure manages the hash and image cache for various sectors.
58 // If the final block size of the NTR region is an odd number, the start of the LTD region will follow consecutively. You must therefore note that no more than a single block may exist in both regions.
59 //
60 typedef struct CARDRomHashBlock
61 {
62     struct CARDRomHashBlock    *next;
63     u32                         index;
64     u32                         offset;
65     u8                         *hash;
66     u8                         *hash_aligned;
67 }
68 CARDRomHashBlock;
69 
70 // This structure manages SRL file hashes.
71 // Each program has different size requirements that cannot be calculated statically. As a result, the plan is to dynamically allocate only the appropriate amount from the arena.
72 //
73 // Memory requirements are as follows.
74 //   - The master hash table:
75 //       A ROM header must be compared with its hash to determine if it is valid, so we will load it all at once from ROM and make it resident during initialization.
76 //
77 //       Calculate the number of bytes required as follows: (ROM size / sector size / number of sectors) * 20 bytes (for SHA1). If the ROM size is 1 gigabit, the sector size is 1024 bytes, and there are 32 sectors, this will be approximately 80 KB.
78 //
79 //   - The block cache:
80 //       Manages the ROM image cache and its hash in blocks.
81 //       A list structure that can always manage multiple blocks is necessary because discrete accesses may span block boundaries.
82 //
83 //       Memory is required only for the total list count, with 20 structures per sector + a.
84 //   - The sector cache:
85 //       Maintains the actual image cache.
86 //       Blocks will not necessarily access all sectors universally, so a separate list structure is required to manage sectors, as well.
87 //
88 typedef struct CARDRomHashContext
89 {
90     // Basic settings obtained from the ROM header
91     CARDRomRegion       area_ntr;
92     CARDRomRegion       area_ltd;
93     CARDRomRegion       sector_hash;
94     CARDRomRegion       block_hash;
95     u32                 bytes_per_sector;
96     u32                 sectors_per_block;
97     u32                 block_max;
98     u32                 sector_max;
99 
100     // Device interface to load data and its hash
101     void                   *userdata;
102     MIDeviceReadFunction    ReadSync;
103     MIDeviceReadFunction    ReadAsync;
104 
105     // Thread that is currently loading data.
106     OSThread           *loader;
107     void               *recent_load;
108 
109     // Sector and block cache
110     CARDRomHashSector  *loading_sector; // Sector waiting for media to load
111     CARDRomHashSector  *loaded_sector;  // Sector waiting for hash verification
112     CARDRomHashSector  *valid_sector;   // Sector that has already been verified
113     CARDRomHashBlock   *loading_block;  // Block waiting for media to load
114     CARDRomHashBlock   *loaded_block;   // Block waiting for hash verification
115     CARDRomHashBlock   *valid_block;    // Block that has already been verified
116     // Array allocated from an arena
117     u8                 *master_hash;    // A block hash array
118     u8                 *images;         // Sector image
119     u8                 *hashes;         // The hash array within a block
120     CARDRomHashSector  *sectors;        // Sector data
121     CARDRomHashBlock   *blocks;         // Block data
122 }
123 CARDRomHashContext;
124 
125 
126 /*---------------------------------------------------------------------------*/
127 /* Functions */
128 
129 /*---------------------------------------------------------------------------*
130   Name:         CARD_InitRomHashContext
131 
132   Description:  Initializes a ROM hash context.
133 
134   Arguments:    context: The CARDRomHashContext structure that should be initialized
135                 header: A ROM header buffer with ROM data that should be managed
136                            (This is only used within this function and does not need to be maintained)
137                 buffer: Buffer for management data to use within a context
138                 length: Buffer size for management data
139                            (This can be calculated with the CARD_CalcRomHashBufferLength function)
140                 sync: Synchronous callback function for device reads
141                 async: Asynchronous callback function for device reads (NULL if unsupported)
142                 userdata: Arbitrary user-defined argument to pass to the device read callback
143 
144   Returns:      None.
145  *---------------------------------------------------------------------------*/
146 void CARD_InitRomHashContext(CARDRomHashContext *context, const CARDRomHeaderTWL *header,
147                              void *buffer, u32 length,
148                              MIDeviceReadFunction sync, MIDeviceReadFunction async,
149                              void *userdata);
150 
151 /*---------------------------------------------------------------------------*
152   Name:         CARD_CalcRomHashBufferLength
153 
154   Description:  Gets the buffer size required for the ROM hash context.
155 
156   Arguments:    header: A ROM header buffer with ROM data that should be managed
157 
158   Returns:      The buffer size required for the ROM hash context.
159  *---------------------------------------------------------------------------*/
160 u32 CARD_CalcRomHashBufferLength(const CARDRomHeaderTWL *header);
161 
162 /*---------------------------------------------------------------------------*
163   Name:         CARDi_NotifyRomHashReadAsync
164 
165   Description:  Notifies a hash context that an asynchronous device read has finished.
166 
167   Arguments:    context: CARDRomHashContext structure.
168 
169   Returns:      None.
170  *---------------------------------------------------------------------------*/
171 void CARD_NotifyRomHashReadAsync(CARDRomHashContext *context);
172 
173 /*---------------------------------------------------------------------------*
174   Name:         CARD_ReadRomHashImage
175 
176   Description:  Loads a ROM image with a verified hash from the specified offset.
177 
178   Arguments:    context: CARDRomHashContext structure.
179                 offset: The ROM offset to access.
180 
181   Returns:      None.
182  *---------------------------------------------------------------------------*/
183 void CARD_ReadRomHashImage(CARDRomHashContext *context, void *buffer, u32 offset, u32 length);
184 
185 
186 #ifdef __cplusplus
187 } // extern "C"
188 #endif
189 
190 
191 #endif // NITRO_CARD_HASH_H_
192