1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - libraries
3   File:     mb_block.c
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-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro.h>
19 #include "mb_common.h"
20 #include "mb_block.h"
21 #include "mb_private.h"
22 
23 
24 //============================================================================
25 //  Function Prototype Declarations
26 //============================================================================
27 static u8 *MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr, u16 child);
28 static BOOL IsGetAllRequestData(u16 child);
29 
30 
31 //============================================================================
32 //  Variable Declarations
33 //============================================================================
34 
35 // The size and number of a divided request's fragments.
36 static struct
37 {
38     int     size;
39     int     num;
40     int     bufSize;
41 }
42 req_data_piece;
43 
44 // For child
45 // Divided request send index.
46 static u8 req_data_piece_idx = 0;
47 
48 // For parent
49 // Receive buffer for a divided request
50 static MbRequestPieceBuf *req_buf;
51 
52 
53 //============================================================================
54 //  function definitions
55 //============================================================================
56 
57 /*---------------------------------------------------------------------------*
58   Name:         MBi_SetChildMPMaxSize
59 
60   Description:  Sets the transmission data size for a child and calculates the divided request size.
61 
62 
63   Arguments:    childMaxSize: Child transmission size.
64 
65   Returns:      None.
66  *---------------------------------------------------------------------------*/
MBi_SetChildMPMaxSize(u16 childMaxSize)67 void MBi_SetChildMPMaxSize(u16 childMaxSize)
68 {
69     req_data_piece.size = MB_COMM_CALC_REQ_DATA_PIECE_SIZE(childMaxSize);
70     req_data_piece.num = MB_COMM_CALC_REQ_DATA_PIECE_NUM(childMaxSize);
71     req_data_piece.bufSize = MB_COMM_CALC_REQ_DATA_BUF_SIZE(childMaxSize);
72 }
73 
74 
75 /*---------------------------------------------------------------------------*
76   Name:         MBi_SetParentPieceBuffer
77 
78   Description:  Sets the receive buffer for a parent's divided request.
79 
80   Arguments:    buf:   Pointer to the receive buffer.
81 
82   Returns:      None.
83  *---------------------------------------------------------------------------*/
MBi_SetParentPieceBuffer(MbRequestPieceBuf * buf)84 void MBi_SetParentPieceBuffer(MbRequestPieceBuf * buf)
85 {
86     req_buf = buf;
87     MI_CpuClear8(req_buf, sizeof(MbRequestPieceBuf));
88 }
89 
90 
91 /*---------------------------------------------------------------------------*
92   Name:         MBi_ClearParentPieceBuffer
93 
94   Description:  Clears the buffer for receiving divided requests.
95 
96   Arguments:    child_aid:   Child AID of the buffer to clear.
97 
98   Returns:      None.
99  *---------------------------------------------------------------------------*/
MBi_ClearParentPieceBuffer(u16 child_aid)100 void MBi_ClearParentPieceBuffer(u16 child_aid)
101 {
102     if (req_buf == NULL)
103     {
104         return;
105     }
106 
107     MI_CpuClear8(req_buf->data_buf[child_aid - 1],
108                  MB_COMM_CALC_REQ_DATA_BUF_SIZE(req_data_piece.bufSize));
109     req_buf->data_bmp[child_aid - 1] = 0;
110 }
111 
112 
113 /*---------------------------------------------------------------------------*
114   Name:         MBi_MakeParentSendBuffer
115 
116   Description:  Builds the actual data to send, using a parent's send header information.
117 
118   Arguments:    hdr:     Pointer to the parent send header.
119                 sendbuf:   Pointer to the buffer that creates the send data.
120 
121   Returns:      pointer to send buffer
122  *---------------------------------------------------------------------------*/
MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr,u8 * sendbuf)123 u8     *MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr, u8 *sendbuf)
124 {
125     u8     *ptr = sendbuf;
126 
127     *ptr++ = hdr->type;
128 
129     switch (hdr->type)
130     {
131     case MB_COMM_TYPE_PARENT_SENDSTART:        //  1
132         break;
133     case MB_COMM_TYPE_PARENT_KICKREQ: //  2
134         break;
135     case MB_COMM_TYPE_PARENT_DL_FILEINFO:      //  3
136         break;
137     case MB_COMM_TYPE_PARENT_DATA:    //  4
138         *ptr++ = (u8)(0x00ff & hdr->fid);       // Lo
139         *ptr++ = (u8)((0xff00 & hdr->fid) >> 8);        // Hi
140         *ptr++ = (u8)(0x00ff & hdr->seqno);     // Lo
141         *ptr++ = (u8)((0xff00 & hdr->seqno) >> 8);      // Hi
142         break;
143     case MB_COMM_TYPE_PARENT_BOOTREQ: //  5
144         break;
145     case MB_COMM_TYPE_PARENT_MEMBER_FULL:      //  6
146         break;
147     default:
148         return NULL;
149     }
150 
151     return ptr;
152 }
153 
154 
155 /*---------------------------------------------------------------------------*
156   Name:         MBi_SetRecvBufferFromChild
157 
158   Description:  Get the header portion from a packet received from the child, and return a pointer to the data portion.
159 
160 
161   Arguments:    hdr:     Pointer to a variable for getting the header.
162                 recvbuf:      Pointer to the receive buffer.
163 
164   Returns:      Pointer to the data portion.
165  *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromChild(const u8 * recvbuf,MBCommChildBlockHeader * hdr,u16 child_id)166 u8     *MBi_SetRecvBufferFromChild(const u8 *recvbuf, MBCommChildBlockHeader * hdr, u16 child_id)
167 {
168     u8     *ptr = (u8 *)recvbuf;
169 
170     hdr->type = *ptr++;
171 
172     switch (hdr->type)
173     {
174     case MB_COMM_TYPE_CHILD_FILEREQ:
175         // Restore fragmented data.
176         if (IsGetAllRequestData(child_id))
177         {
178             return (u8 *)req_buf->data_buf[child_id - 1];
179         }
180 
181         hdr->req_data.piece = *ptr++;
182         if (hdr->req_data.piece > req_data_piece.num)
183         {
184             return NULL;               // Error
185         }
186         MI_CpuCopy8(ptr, hdr->req_data.data, (u32)req_data_piece.size);
187         ptr = MBi_ReceiveRequestDataPiece(hdr, child_id);
188         break;
189     case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
190         hdr->data.req = (u16)(0x00ff & (*ptr++));
191         hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
192         break;
193     case MB_COMM_TYPE_CHILD_CONTINUE:
194         hdr->data.req = (u16)(0x00ff & (*ptr++));
195         hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
196         MI_CpuCopy8(ptr, hdr->data.reserved, (u32)req_data_piece.size);
197         ptr += req_data_piece.size;
198         break;
199     default:
200         return NULL;
201     }
202 
203     return ptr;
204 }
205 
206 
207 /*---------------------------------------------------------------------------*
208   Name:         MBi_ReceiveRequestDataPiece
209 
210   Description:  Builds data in its entirety from the divided request data that was received from the child.
211 
212   Arguments:    hdr:     Pointer to a variable for getting the header.
213                 recvbuf:      Pointer to the receive buffer.
214 
215   Returns:      Pointer to the data when the divided request data is all complete.
216                 NULL when not it is not complete.
217  *---------------------------------------------------------------------------*/
MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr,u16 child)218 static u8 *MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr, u16 child)
219 {
220     u8      piece;
221     u8     *ptr;
222 
223     if (req_buf == NULL)
224     {
225         return NULL;
226     }
227 
228     piece = hdr->req_data.piece;
229 
230     if (piece > req_data_piece.num)
231     {
232         return NULL;
233     }
234 
235     ptr = ((u8 *)req_buf->data_buf[child - 1]) + (piece * req_data_piece.size);
236 
237     MI_CpuCopy8(&hdr->req_data.data[0], ptr, (u32)req_data_piece.size);
238 
239     req_buf->data_bmp[child - 1] |= (1 << piece);
240 
241     MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
242                     ptr[5]);
243 
244     if (IsGetAllRequestData(child))
245     {
246         return (u8 *)req_buf->data_buf[child - 1];
247     }
248 
249     return NULL;
250 }
251 
252 
253 /*---------------------------------------------------------------------------*
254   Name:
255 
256   Description:  Builds data in its entirety from the divided request data that was received from the child.
257 
258   Arguments:    hdr:     Pointer to a variable for getting the header.
259                 recvbuf:      Pointer to the receive buffer.
260 
261   Returns:      TRUE if the divided request data is all complete.
262                 FALSE if it is not complete.
263  *---------------------------------------------------------------------------*/
IsGetAllRequestData(u16 child)264 static BOOL IsGetAllRequestData(u16 child)
265 {
266     u16     i;
267 
268     /* Determine whether Pieces were collected. */
269     for (i = 0; i < req_data_piece.num; i++)
270     {
271         if ((req_buf->data_bmp[child - 1] & (1 << i)) == 0)
272         {
273             return FALSE;
274         }
275     }
276 
277     return TRUE;
278 }
279 
280 
281 
282 /*---------------------------------------------------------------------------*
283   Name:         MBi_MakeChildSendBuffer
284 
285   Description:  Builds the actual data to send, using a child's send header information.
286 
287   Arguments:    hdr:     Pointer to the child send header.
288                 sendbuf:   Pointer to the buffer that creates the send data.
289 
290   Returns:      pointer to send buffer
291  *---------------------------------------------------------------------------*/
MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr,u8 * sendbuf)292 u8     *MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr, u8 *sendbuf)
293 {
294     u8     *pbuf = sendbuf;
295 
296     *pbuf++ = hdr->type;
297     switch (hdr->type)
298     {
299     case MB_COMM_TYPE_CHILD_FILEREQ:
300         *pbuf++ = hdr->req_data.piece;
301         if (hdr->req_data.piece > req_data_piece.num)
302         {
303             return NULL;               // Error
304         }
305 
306         MI_CpuCopy8((void *)(hdr->req_data.data), (void *)pbuf, (u32)req_data_piece.size);
307         pbuf += req_data_piece.size;
308         break;
309     case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
310         break;
311     case MB_COMM_TYPE_CHILD_CONTINUE:
312         *pbuf++ = (u8)(0x00ff & hdr->data.req); // Lo
313         *pbuf++ = (u8)((0xff00 & hdr->data.req) >> 8);  // Hi
314         MI_CpuCopy8((void *)(hdr->data.reserved), (void *)pbuf, (u32)req_data_piece.size);
315         pbuf += req_data_piece.size;
316         break;
317     case MB_COMM_TYPE_CHILD_STOPREQ:
318         break;
319     case MB_COMM_TYPE_CHILD_BOOTREQ_ACCEPTED:
320         break;
321     default:
322         return NULL;
323     }
324 
325     return pbuf;
326 }
327 
328 
329 /*---------------------------------------------------------------------------*
330   Name:         MBi_SendRequestDataPiece
331 
332   Description:  Divide request data to send from a child.
333 
334   Arguments:    pData:     Pointer that gets divided data.
335                 pReq:      Request data to divide.
336 
337   Returns:      Index value of the divided data that was obtained.
338  *---------------------------------------------------------------------------*/
MBi_SendRequestDataPiece(u8 * pData,const MBCommRequestData * pReq)339 u8 MBi_SendRequestDataPiece(u8 *pData, const MBCommRequestData *pReq)
340 {
341     const u8 *ptr = (u8 *)pReq;
342 
343     /* Decide upon the send piece. */
344     req_data_piece_idx = (u8)((req_data_piece_idx + 1) % req_data_piece.num);
345     MB_DEBUG_OUTPUT("req_data piece : %d\n", req_data_piece_idx);
346 
347     // Copy data to the send buffer.
348     MI_CpuCopy8((void *)&ptr[req_data_piece_idx * req_data_piece.size],
349                 pData, (u32)req_data_piece.size);
350 
351     MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", pData[0], pData[1], pData[2], pData[3],
352                     pData[4], pData[5]);
353 
354     return req_data_piece_idx;
355 }
356 
357 
358 
359 /*---------------------------------------------------------------------------*
360   Name:         MBi_SetRecvBufferFromParent
361 
362   Description:  Get the header portion from a packet received from the parent, and return a pointer to the data portion.
363 
364 
365   Arguments:    hdr:     Pointer to a variable for getting the header.
366                 recvbuf:      Pointer to the receive buffer.
367 
368   Returns:      Pointer to the data portion.
369  *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr,const u8 * recvbuf)370 u8     *MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr, const u8 *recvbuf)
371 {
372 
373     hdr->type = *recvbuf++;
374 
375     switch (hdr->type)
376     {
377     case MB_COMM_TYPE_PARENT_SENDSTART:
378         break;
379     case MB_COMM_TYPE_PARENT_KICKREQ:
380         break;
381     case MB_COMM_TYPE_PARENT_DL_FILEINFO:
382         break;
383     case MB_COMM_TYPE_PARENT_DATA:
384         hdr->fid = (u16)(*recvbuf++);  // Lo
385         hdr->fid |= ((u16)(*recvbuf++) << 8);   // Hi
386         hdr->seqno = (u16)(*recvbuf++); // Lo
387         hdr->seqno |= ((u16)(*recvbuf++) << 8); // Hi
388         break;
389     case MB_COMM_TYPE_PARENT_BOOTREQ:
390         break;
391     case MB_COMM_TYPE_PARENT_MEMBER_FULL:
392         break;
393     default:
394         return NULL;
395     }
396     return (u8 *)recvbuf;
397 }
398