|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: * 3 June 99 wgulland created.
27: *
28: * Useful stuff called from several different FireWire objects.
29: */
30: #include <IOKit/assert.h>
31: #include <IOKit/IOLib.h>
32: #include <IOKit/firewire/IOFWRegs.h>
33: #include <IOKit/firewire/IOFireWirePriv.h>
34:
35: ////////////////////////////////////////////////////////////////////////////////
36: //
37: // FWComputeCRC16
38: //
39: // This proc computes a CRC 16 check.
40: //
41:
42: UInt16 FWComputeCRC16(UInt32 *pQuads, UInt32 numQuads)
43: {
44: SInt32 shift;
45: UInt32 sum;
46: UInt32 crc16;
47: UInt32 quadNum;
48: UInt32 quad;
49:
50: // Compute CRC 16 over all quads.
51: crc16 = 0;
52: for (quadNum = 0; quadNum < numQuads; quadNum++) {
53: quad = *pQuads++;
54: for (shift = 28; shift >= 0; shift -= 4) {
55: sum = ((crc16 >> 12) ^ (quad >> shift)) & 0x0F;
56: crc16 = (crc16 << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
57: }
58: }
59:
60: return (crc16 & 0xFFFF);
61: }
62:
63:
64: ////////////////////////////////////////////////////////////////////////////////
65: //
66: // FWCSRROMInvalidateEntryIDType
67: //
68: // Invalidate a CSR ROM entry ID. This will deallocate any memory allocated
69: // for the ID excluding the ID data record itself.
70: //
71: // Probably only thing needed is to release reference to the ROM.
72: //
73:
74: void FWCSRROMInvalidateEntryIDType(CSRROMEntryID csrROMEntryID)
75: {
76: CSRROMEntryIDDataPtr pCSRROMEntryIDData;
77:
78: if (csrROMEntryID != kInvalidCSRROMEntryID)
79: {
80: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
81:
82: switch (pCSRROMEntryIDData->entryType)
83: {
84: case kLocalCSRROMEntryIDType :
85: break;
86:
87: case kRemoteCSRROMEntryIDType :
88:
89: break;
90:
91: default :
92: break;
93: }
94:
95: // Entry is now invalid.
96: pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
97: }
98: }
99:
100: ////////////////////////////////////////////////////////////////////////////////
101: //
102: // FWCSRROMCreateEntryID
103: //
104: // Allocate memory for a CSR ROM entry ID.
105: //zzz could be a little more efficient computing allocation size.
106: //
107:
108: CSRROMEntryID FWCSRROMCreateEntryID(void)
109: {
110: CSRROMEntryID csrROMEntryID = kInvalidCSRROMEntryID;
111: CSRROMEntryIDDataPtr pCSRROMEntryIDData;
112: UInt32 maxSize;
113:
114: // Determine maximum size of all entry types.
115: // Need enough for local ID type.
116: maxSize = sizeof (CSRROMLocalIDData);
117: if (sizeof (CSRROMRemoteIDData) > maxSize)
118: maxSize = sizeof (CSRROMRemoteIDData);
119:
120: // Allocate the data.
121: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) IOMalloc (maxSize);
122: if (pCSRROMEntryIDData != NULL) {
123: pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
124: csrROMEntryID = (CSRROMEntryID) pCSRROMEntryIDData;
125: }
126: return (csrROMEntryID);
127: }
128:
129: ////////////////////////////////////////////////////////////////////////////////
130: //
131: // FWCSRROMDisposeEntryID
132: //
133: // Deallocate memory for a CSR ROM entry ID.
134: //
135:
136: void FWCSRROMDisposeEntryID(CSRROMEntryID csrROMEntryID)
137: {
138: CSRROMEntryIDDataPtr pCSRROMEntryIDData;
139:
140: if (csrROMEntryID != kInvalidCSRROMEntryID) {
141: UInt32 maxSize;
142:
143: // Determine maximum size of all entry types.
144: // Need enough for local ID type.
145: maxSize = sizeof (CSRROMLocalIDData);
146: if (sizeof (CSRROMRemoteIDData) > maxSize)
147: maxSize = sizeof (CSRROMRemoteIDData);
148: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
149:
150: // Invalidate entry.
151: FWCSRROMInvalidateEntryIDType (csrROMEntryID);
152:
153: // Deallocate entry.
154: IOFree(pCSRROMEntryIDData, maxSize);
155: }
156: }
157:
158: ////////////////////////////////////////////////////////////////////////////////
159: //
160: // FWCSRROMCreateRemoteEntryID
161: //
162: // Create a remote CSR ROM entry ID.
163: //
164:
165: static IOReturn FWCSRROMCreateRemoteEntryID(
166: CSRROMEntryID *pCSRROMEntryID,
167: const UInt32 * data,
168: UInt32 *physicalPath,
169: UInt32 pathSize)
170: {
171: CSRROMEntryID csrROMEntryID = *pCSRROMEntryID;
172: CSRROMEntryIDDataPtr pCSRROMEntryIDData;
173: CSRROMRemoteIDDataPtr pCSRROMRemoteIDData;
174:
175: // Allocate an entry ID if given entry ID is invalid.
176: if (csrROMEntryID == kInvalidCSRROMEntryID) {
177: csrROMEntryID = FWCSRROMCreateEntryID ();
178: // If entry ID is still invalid, there must have been a memory error.
179: if (csrROMEntryID == kInvalidCSRROMEntryID)
180: return kIOReturnNoMemory;
181: }
182:
183:
184: // Get data from ID.
185: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
186: pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;
187:
188: // If entry is not a remote type, invalidate its type.
189: if ((pCSRROMEntryIDData->entryType != kRemoteCSRROMEntryIDType) &&
190: (pCSRROMEntryIDData->entryType != kInvalidCSRROMEntryIDType)) {
191: FWCSRROMInvalidateEntryIDType (csrROMEntryID);
192: }
193:
194: // Make entry a remote type.
195: pCSRROMEntryIDData->entryType = kRemoteCSRROMEntryIDType;
196:
197:
198: // Copy directory paths and data pointer
199: pCSRROMRemoteIDData->data = data;
200: bcopy (physicalPath, pCSRROMRemoteIDData->physicalPath, pathSize * sizeof (UInt32));
201: pCSRROMRemoteIDData->pathSize = pathSize;
202:
203: // Return entry ID.
204: *pCSRROMEntryID = csrROMEntryID;
205:
206: return (kIOReturnSuccess);
207: }
208:
209: ////////////////////////////////////////////////////////////////////////////////
210: //
211: // FWCSRROMDisposeIterator
212: //
213: // Dispose of storage allocated for iterator.
214: //
215:
216: void FWCSRROMDisposeIterator(CSRROMEntryIterator csrROMIterator)
217: {
218: CSRROMEntryIteratorRecPtr pIteratorRec;
219:
220: // Deallocate if iterator is valid.
221: if (csrROMIterator != kInvalidCSRROMIterator) {
222: // Get iterator record.
223: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
224:
225: // Deallocate iterator record.
226: IOFree (pIteratorRec, sizeof (CSRROMEntryIteratorRec));
227: }
228: }
229:
230:
231: ////////////////////////////////////////////////////////////////////////////////
232: //
233: // FWCSRROMSetIterator
234: //
235: // Set current path and relationship of iterator.
236: //zzz should support all entry ID types.
237: //zzz should support kIterateRoot
238: //
239:
240: IOReturn FWCSRROMSetIterator(
241: CSRROMEntryIterator csrROMIterator,
242: CSRROMEntryID csrROMEntryID,
243: CSRROMIterationOp relationship)
244: {
245: CSRROMEntryIteratorRecPtr pIteratorRec;
246: CSRROMEntryIDDataPtr pCSRROMEntryIDData;
247: CSRROMRemoteIDDataPtr pCSRROMRemoteIDData;
248:
249: // Get CSR ROM search iterator record.
250: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
251:
252: // Set to given entry.
253: if (csrROMEntryID != kInvalidCSRROMEntryID) {
254: // Get entry data from ID.
255: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
256:
257: if (pCSRROMEntryIDData->entryType == kRemoteCSRROMEntryIDType) {
258: // Recast entry data.
259: pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;
260:
261: // Copy physical path.
262: bcopy (pCSRROMRemoteIDData->physicalPath,
263: pIteratorRec->physicalPath,
264: pCSRROMRemoteIDData->pathSize * sizeof (UInt32));
265:
266: // Copy data pointer and path depth
267: pIteratorRec->data = pCSRROMRemoteIDData->data;
268: pIteratorRec->pathSize = pCSRROMRemoteIDData->pathSize;
269: }
270: }
271:
272: // Set to given relationship.
273: if (relationship != kIterateContinue)
274: pIteratorRec->relationship = relationship;
275:
276: return (kIOReturnSuccess);
277: }
278:
279:
280: ////////////////////////////////////////////////////////////////////////////////
281: //
282: // FWCSRROMEntrySearch
283: //
284: // Search for the next ROM entry that matches the search criteria.
285: //zzz need to check the search type in the criteria record and the relationship
286: //zzz could be more efficient. should make and use more defs.
287: //zzz need to return information on what exactly was found
288: //zzz fill in entry value better
289: //zzz should break this up
290: //zzz should support all entry ID types.
291: //
292:
293: // zzz
294: // Made a quick fix here so that if we are searching for Unit Directories (key d1)
295: // we will ignore any Instance Directories (key d8) because they contain redundant
296: // pointers to Unit Directories. This is almost surely not the best soltution.
297:
298: IOReturn FWCSRROMEntrySearch(
299: CSRROMEntryIterator csrROMIterator,
300: CSRROMIterationOp relationship,
301: CSRROMEntryID *pCSRROMEntryID,
302: int *pDone,
303: CSRROMSearchCriteriaPtr pSearchCriteria,
304: UInt8 * pEntryValue,
305: UInt32 *pEntrySize)
306: {
307: CSRROMEntryIteratorRecPtr pIteratorRec;
308: UInt32 currentAddress, entryValueAddress;
309: UInt32 pathSize;
310: UInt32 directoryEnd;
311: UInt32 address;
312: UInt32 directoryHeader, directoryEntry;
313: UInt32 leafEntry;
314: UInt32 keyType, keyValue;
315: UInt32 keyTypeBit, keyValueBitHi, keyValueBitLo;
316: UInt32 returnedEntrySize;
317: bool found, done;
318: IOReturn status = kIOReturnSuccess;
319:
320: //zzz Part of the Instance Directory hack
321: bool unitDirSearch;
322: bool ignoreInstanceDir;
323:
324: // If we are searching for Unit Directories (in FWExpertLoader.c/FWUpdateDevice)
325: // then just don't go down any Instance Directories (key d8), because we'll find a
326: // redundant pointer to the Unit Directory in there.
327:
328: unitDirSearch = (pSearchCriteria->csrROMSearchType == kCSRROMSearchForKey) &&
329: (pSearchCriteria->keyType == kCSRDirectoryKeyTypeBit) &&
330: (pSearchCriteria->keyHi == kCSRUnitDirectoryKeyHiBit) &&
331: (pSearchCriteria->keyLo == kCSRUnitDirectoryKeyLoBit);
332:
333: // Get CSR ROM search iterator record.
334: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
335:
336: // Read the current directory length. First, get base address of current
337: // directory by going up one node in the directory path. Special case
338: // when we're in the root directory. Second, read the directory length
339: // at the base address.
340: pathSize = pIteratorRec->pathSize;
341: if (pathSize > 2) {
342: address = pIteratorRec->physicalPath[pathSize - 2];
343: directoryEntry = pIteratorRec->data[address];
344: address += (directoryEntry & 0x00FFFFFF);
345: }
346: else {
347: address = pIteratorRec->physicalPath[0];
348: }
349: directoryHeader = pIteratorRec->data[address];
350: directoryEnd = address + ((directoryHeader >> 16) + 1);
351:
352: // Loop until we've found what we're looking for, or we've searched
353: // everything.
354: found = false;
355: done = false;
356: while ((!found) && (!done)) {
357: // Read our current location.
358: pathSize = pIteratorRec->pathSize;
359: currentAddress = pIteratorRec->physicalPath[pathSize - 1];
360:
361: // Check if search was reset.
362: if (pIteratorRec->reset) {
363: pIteratorRec->reset = false;
364: }
365: else {
366: // Read directory entry at current address.
367: //zzz should have some address defs.
368: directoryEntry = pIteratorRec->data[currentAddress];
369: // If the current directory entry is a directory, add it to
370: // the path. Otherwise, go to next directory entry.
371: keyType = (directoryEntry & 0xC0000000) >> 30;
372: //zzz
373: //The Instance Directory hack
374: ignoreInstanceDir = (directoryEntry >> 24) == 0xd8;
375: //zzz
376: if ((keyType == kCSRDirectoryKeyType) && !ignoreInstanceDir) {
377: // Go to and read directory header.
378: //zzz should do this the right way if offset > 1024.
379: currentAddress += (directoryEntry & 0x00FFFFFF);
380: directoryHeader = pIteratorRec->data[currentAddress];
381: // Add directory to path and set location to first
382: // entry in directory.
383: pathSize++;
384:
385: directoryEnd =
386: currentAddress + ((directoryHeader >> 16) + 1);
387:
388: currentAddress += 1;
389: }
390: else {
391: currentAddress += 1;
392: }
393: }
394:
395: // If we're past the end of the current directory, take it out
396: // of path.
397: while ((currentAddress >= directoryEnd) && (!done)) {
398: pathSize--;
399: currentAddress = pIteratorRec->physicalPath[pathSize - 1] + 1;
400:
401: // Read the current directory length.
402: if (pathSize > 2) {
403: address = pIteratorRec->physicalPath[pathSize - 2];
404: directoryEntry = pIteratorRec->data[address];
405: address += (directoryEntry & 0x00FFFFFF);
406: }
407: else {
408: address = pIteratorRec->physicalPath[0];
409: }
410: directoryHeader = pIteratorRec->data[address];
411: directoryEnd = address + ((directoryHeader >> 16) + 1);
412: if (pathSize < 2) {
413: done = true;
414: }
415: }
416: // If we're not done searching, check the current directory entry
417: // against the search criteria.
418: if (!done) {
419: directoryEntry = pIteratorRec->data[currentAddress];
420: // Read key type and value.
421: keyType = (directoryEntry & 0xC0000000) >> 30;
422: keyValue = (directoryEntry & 0x3F000000) >> 24;
423:
424: // Convert to bit flag.
425: keyTypeBit = 1 << keyType;
426: if (keyValue > 31) {
427: keyValueBitHi = 1 << (keyValue - 32);
428: keyValueBitLo = 0;
429: }
430: else {
431: keyValueBitHi = 0;
432: keyValueBitLo = 1 << keyValue;
433: }
434:
435: // Compare bit flags against search criteria.
436:
437: if ((keyTypeBit & pSearchCriteria->keyType) &&
438: ((keyValueBitHi & pSearchCriteria->keyHi) ||
439: (keyValueBitLo & pSearchCriteria->keyLo))) {
440: switch (keyType) {
441: case kCSRImmediateKeyType :
442: if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
443: // Determine size of data.
444: if (*pEntrySize < 4)
445: returnedEntrySize = *pEntrySize;
446: else
447: returnedEntrySize = 4;
448:
449: // Copy data.//zzz not right.
450: //zzz need def here.
451: *((UInt32 *) pEntryValue) =
452: directoryEntry & 0x00FFFFFF;
453:
454: // Return size.
455: *pEntrySize = returnedEntrySize;
456: }
457: break;
458:
459: case kCSROffsetKeyType :
460: if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
461: // Determine size of data.
462: if (*pEntrySize < 4)
463: returnedEntrySize = *pEntrySize;
464: else
465: returnedEntrySize = 4;
466:
467: // Copy data.//zzz not right.
468: //zzz need def here.
469: *((UInt32 *) pEntryValue) =
470: directoryEntry & kCSREntryValue;
471:
472: // Return size.
473: *pEntrySize = returnedEntrySize;
474: }
475: break;
476:
477: case kCSRLeafKeyType :
478: if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
479: // Get address of leaf.
480: //zzz need to do indirect stuff right.
481: entryValueAddress = currentAddress + (directoryEntry & kCSREntryValue);
482:
483: // Get size of leaf.
484: leafEntry = pIteratorRec->data[entryValueAddress];
485: returnedEntrySize = (leafEntry >> 16) * sizeof (UInt32);
486: entryValueAddress += 1;
487: // Determine size of data.
488: if (returnedEntrySize > *pEntrySize)
489: returnedEntrySize = *pEntrySize;
490: // Copy data.
491: bcopy(&pIteratorRec->data[entryValueAddress], pEntryValue, returnedEntrySize);
492: // Return size.
493: *pEntrySize = returnedEntrySize;
494: }
495:
496: break;
497:
498: case kCSRDirectoryKeyType ://zzz
499: break;
500:
501: default : //zzz
502: break;
503: }
504:
505: found = true;
506: }
507: }
508:
509: // Update current address.
510: pIteratorRec->physicalPath[pathSize - 1] = currentAddress;
511: pIteratorRec->pathSize = pathSize;
512: }
513:
514: // Return CSR ROM entry ID.
515: if (pCSRROMEntryID != NULL) {
516: if (!done) {
517: status = FWCSRROMCreateRemoteEntryID
518: (pCSRROMEntryID,
519: pIteratorRec->data,
520: pIteratorRec->physicalPath,
521: pIteratorRec->pathSize);
522: }
523: else {
524: if (*pCSRROMEntryID != kInvalidCSRROMEntryID)
525: FWCSRROMDisposeEntryID (*pCSRROMEntryID);
526: *pCSRROMEntryID = kInvalidCSRROMEntryID;
527: }
528: }
529:
530: *pDone = done;
531: return (status);
532: }
533:
534:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.