37 void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors); |
39 void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors); |
38 |
40 |
39 private: |
41 private: |
40 virtual TInt ReadPartition(TUint32 aPtOffset); |
42 virtual TInt ReadPartition(TUint32 aPtOffset); |
41 static void SessionEndCallBack(TAny* aSelf); |
43 static void SessionEndCallBack(TAny* aSelf); |
42 void DoSessionEndCallBack(); |
44 void DoSessionEndCallBack(); |
43 virtual TInt DecodePartitionInfo(); |
45 virtual TInt DecodePartitionInfo(); |
|
46 TInt GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize); |
|
47 TInt GetPartitionOffset(TUint32& aPtOffset); |
|
48 TInt SelectNextPartition(); |
44 |
49 |
45 protected: |
50 protected: |
46 DMediaDriver* iDriver; |
51 DMediaDriver* iDriver; |
47 TPartitionInfo* iPartitionInfo; |
52 TPartitionInfo* iPartitionInfo; |
48 TMMCCallBack iSessionEndCallBack; |
53 TMMCCallBack iSessionEndCallBack; |
86 |
92 |
87 // this gets used before any access |
93 // this gets used before any access |
88 TInt bufLen, minorBufLen; |
94 TInt bufLen, minorBufLen; |
89 stack->BufferInfo(iIntBuf, bufLen, minorBufLen); |
95 stack->BufferInfo(iIntBuf, bufLen, minorBufLen); |
90 |
96 |
|
97 iSelectedPartition = TExtendedCSD::ESelectUserArea; |
|
98 |
91 return(KErrNone); |
99 return(KErrNone); |
92 } |
100 } |
93 |
101 |
94 TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack) |
102 TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack) |
95 { |
103 { |
96 iPartitionInfo = &aInfo; |
104 iPartitionInfo = &aInfo; |
|
105 iPartitionInfo->iPartitionCount = 0; |
97 iCallBack = aCallBack; |
106 iCallBack = aCallBack; |
98 |
107 |
|
108 // Always check the user partition first |
|
109 iSelectedPartition = TExtendedCSD::ESelectUserArea; |
|
110 iSession->SetPartition(iSelectedPartition); |
|
111 |
99 // Preferred partition scheme is BB5, which is located in the last block of the media. |
112 // Preferred partition scheme is BB5, which is located in the last block of the media. |
100 const TUint32 ptiOffset = (I64LOW(iCard->DeviceSize64() >> KDiskSectorShift)) - KPIOffsetFromMediaEnd; |
113 TUint32 ptiOffset; |
101 return ReadPartition(ptiOffset); |
114 TInt r; |
102 } |
115 do |
103 |
116 { |
|
117 r = GetPartitionOffset(ptiOffset); |
|
118 |
|
119 if(r == KErrNone) |
|
120 { |
|
121 r = ReadPartition(ptiOffset); |
|
122 return r; |
|
123 } |
|
124 |
|
125 r = SelectNextPartition(); |
|
126 } |
|
127 while(r != KErrNotFound); |
|
128 |
|
129 return r; |
|
130 } |
|
131 |
|
132 // retrieves size in terms of sectors |
|
133 TInt DBB5PartitionInfo::GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize) |
|
134 { |
|
135 TInt r = KErrNone; |
|
136 |
|
137 TUint32 size = 0; |
|
138 |
|
139 const TExtendedCSD& extCsd = iCard->ExtendedCSD(); |
|
140 |
|
141 switch(aPartition) |
|
142 { |
|
143 case TExtendedCSD::ESelectUserArea: |
|
144 { |
|
145 size = (TUint32)(iCard->DeviceSize64() / KSectorSize); |
|
146 |
|
147 if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5) |
|
148 { |
|
149 TUint32 otherPartitionsSize = |
|
150 extCsd.GeneralPurposePartition1SizeInSectors() |
|
151 + extCsd.GeneralPurposePartition2SizeInSectors() |
|
152 + extCsd.GeneralPurposePartition3SizeInSectors() |
|
153 + extCsd.GeneralPurposePartition4SizeInSectors(); |
|
154 |
|
155 __ASSERT_DEBUG(size >= otherPartitionsSize, Kern::Fault("DBB5PartitionInfo size mismatch", __LINE__)); |
|
156 size -= otherPartitionsSize; |
|
157 } |
|
158 } |
|
159 break; |
|
160 case TExtendedCSD::ESelectBootPartition1: |
|
161 case TExtendedCSD::ESelectBootPartition2: |
|
162 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_3) ? |
|
163 0 : extCsd.BootSizeInSectors(); |
|
164 break; |
|
165 case TExtendedCSD::ESelectRPMB: |
|
166 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? |
|
167 0 : extCsd.RpmbSizeInSectors(); |
|
168 break; |
|
169 case TExtendedCSD::ESelectGPAPartition1: |
|
170 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? |
|
171 0 : extCsd.GeneralPurposePartition1SizeInSectors(); |
|
172 break; |
|
173 case TExtendedCSD::ESelectGPAPartition2: |
|
174 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? |
|
175 0 : extCsd.GeneralPurposePartition2SizeInSectors(); |
|
176 break; |
|
177 case TExtendedCSD::ESelectGPAPartition3: |
|
178 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? |
|
179 0 : extCsd.GeneralPurposePartition3SizeInSectors(); |
|
180 break; |
|
181 case TExtendedCSD::ESelectGPAPartition4: |
|
182 size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? |
|
183 0 : extCsd.GeneralPurposePartition4SizeInSectors(); |
|
184 break; |
|
185 default: |
|
186 // unknown partition |
|
187 size = 0; |
|
188 r = KErrNotSupported; |
|
189 break; |
|
190 } |
|
191 |
|
192 aSize = size; |
|
193 return r; |
|
194 } |
|
195 |
|
196 TInt DBB5PartitionInfo::GetPartitionOffset(TUint32& aPtiOffset) |
|
197 { |
|
198 TInt r = GetPartitionSizeInSectors(iSelectedPartition, aPtiOffset); |
|
199 |
|
200 if((r != KErrNone) || (aPtiOffset == 0)) |
|
201 { |
|
202 // error reading or partition not supported, skip |
|
203 r = KErrNotSupported; |
|
204 } |
|
205 else |
|
206 { |
|
207 // need to determine correct end of the partition |
|
208 aPtiOffset -= KPIOffsetFromMediaEnd; |
|
209 } |
|
210 |
|
211 return r; |
|
212 } |
|
213 |
|
214 TInt DBB5PartitionInfo::SelectNextPartition() |
|
215 { |
|
216 TExtendedCSD extCsd = iCard->ExtendedCSD(); |
|
217 TUint maxPartition = TExtendedCSD::ESelectUserArea; |
|
218 |
|
219 if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5) |
|
220 { |
|
221 // v4.4 supports UDA, 2x BOOT, RPMB and 4x GPAP partitions |
|
222 maxPartition = TExtendedCSD::ESelectGPAPartition4; |
|
223 } |
|
224 #ifdef EMMC_BOOT_PARTITION_ACCESS_ENABLED |
|
225 else if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_3) |
|
226 { |
|
227 // v4.3 supports up to two BOOT partitions |
|
228 maxPartition = TExtendedCSD::ESelectBootPartition2; |
|
229 } |
|
230 #endif // EMMC_BOOT_PARTITION_ACCESS_ENABLED |
|
231 |
|
232 ++iSelectedPartition; |
|
233 |
|
234 // skip through to GPAP1 if either the currently selected partition is RPMB or |
|
235 // if it is one of the BOOT partitions and boot partition access is not enabled |
|
236 if((iSelectedPartition == TExtendedCSD::ESelectRPMB) |
|
237 #ifndef EMMC_BOOT_PARTITION_ACCESS_ENABLED |
|
238 || (iSelectedPartition == TExtendedCSD::ESelectBootPartition1) |
|
239 || (iSelectedPartition == TExtendedCSD::ESelectBootPartition2) |
|
240 #endif |
|
241 ) |
|
242 { |
|
243 iSelectedPartition = TExtendedCSD::ESelectGPAPartition1; |
|
244 } |
|
245 |
|
246 TInt r = KErrNone; |
|
247 if(iSelectedPartition > maxPartition) |
|
248 { |
|
249 r = KErrNotFound; // no more partitions to be checked |
|
250 } |
|
251 else |
|
252 { |
|
253 iSession->SetPartition(iSelectedPartition); |
|
254 } |
|
255 |
|
256 return r; |
|
257 } |
|
258 |
|
259 // returns KErrCompletion on success after having checked all partitions |
104 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset) |
260 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset) |
105 { |
261 { |
106 // If media driver is persistent (see EMediaDriverPersistent) |
262 // If media driver is persistent (see EMediaDriverPersistent) |
107 // the card may have changed since last power down, so reset CID |
263 // the card may have changed since last power down, so reset CID |
108 iSession->SetCard(iCard); |
264 iSession->SetCard(iCard); |
165 { |
321 { |
166 iDriver->EndInCritical(); |
322 iDriver->EndInCritical(); |
167 |
323 |
168 TInt r = iSession->EpocErrorCode(); |
324 TInt r = iSession->EpocErrorCode(); |
169 |
325 |
|
326 |
|
327 TInt& partitionCount = iPartitionInfo->iPartitionCount; |
|
328 |
170 if (r == KErrNone) |
329 if (r == KErrNone) |
171 r = DecodePartitionInfo(); |
330 r = DecodePartitionInfo(); |
172 |
331 |
173 if (!iCheckTOC) |
332 if (iCheckTOC) |
174 { |
333 { |
175 iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady); |
334 //BB5 table not found need to check for TOC in this partition before continuing |
176 } |
335 if (r!=KErrNone) |
177 } |
336 { |
|
337 iDriver->PartitionInfoComplete(KErrNotReady); |
|
338 } |
|
339 return; |
|
340 } |
|
341 |
|
342 |
|
343 if(r == KErrNone) |
|
344 { |
|
345 // check next partition(s) for BB5 |
|
346 TUint32 ptiOffset = 0; |
|
347 |
|
348 r = SelectNextPartition(); |
|
349 while(r != KErrNotFound) |
|
350 { |
|
351 if(r == KErrNone) |
|
352 r = GetPartitionOffset(ptiOffset); |
|
353 |
|
354 if(r == KErrNone) |
|
355 { |
|
356 r = ReadPartition(ptiOffset); |
|
357 if(r != KErrNone) |
|
358 break; |
|
359 |
|
360 |
|
361 return; |
|
362 } |
|
363 |
|
364 r = SelectNextPartition(); |
|
365 } |
|
366 |
|
367 |
|
368 // end of partitions - reinterpret error code |
|
369 if(r != KErrNotFound) |
|
370 { |
|
371 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: ReadPartition() failed r=%d!", r)); |
|
372 r = KErrCorrupt; |
|
373 } |
|
374 else if(partitionCount == 0) |
|
375 { |
|
376 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: No supported partitions found!")); |
|
377 r = KErrCorrupt; |
|
378 } |
|
379 else |
|
380 r = KErrCompletion; |
|
381 } |
|
382 |
|
383 // Notify medmmc that partitioninfo is complete |
|
384 iCallBack.CallBack(); |
|
385 |
|
386 // All potential partitions checked - KErrCompletion |
|
387 // indicates that there are no more partitions to check |
|
388 r = (r == KErrCompletion) ? KErrNone : KErrNotReady; |
|
389 iDriver->PartitionInfoComplete(r); |
|
390 } |
|
391 |
178 |
392 |
179 TInt DBB5PartitionInfo::DecodePartitionInfo() |
393 TInt DBB5PartitionInfo::DecodePartitionInfo() |
180 // |
394 // |
181 // Decode partition info that was read into internal buffer |
395 // Decode partition info that was read into internal buffer |
182 // |
396 // |
183 { |
397 { |
184 __KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()")); |
398 __KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()")); |
185 TUint partitionCount = iPartitionInfo->iPartitionCount = 0; |
399 TInt& partitionCount = iPartitionInfo->iPartitionCount; |
186 |
400 TInt r = KErrNone; |
187 |
401 |
188 if (iCheckTOC) |
402 if (iCheckTOC) |
189 { |
403 { |
190 // Try utilising the TOC (Table Of Contents) partitioning scheme |
404 // Try utilising the TOC (Table Of Contents) partitioning scheme |
191 const TText8* KRofsNames[KNoOfROFSPartitions] = { KTocRofs1Generic, |
405 const TText8* KRofsNames[KNoOfROFSPartitions] = { KTocRofs1Generic, |
192 KTocRofs2Generic, |
406 KTocRofs2Generic, |
322 (KPartitionTypeROM == partitionType) || |
536 (KPartitionTypeROM == partitionType) || |
323 (KPartitionTypePagedData == partitionType) ) ) |
537 (KPartitionTypePagedData == partitionType) ) ) |
324 { |
538 { |
325 iPartitionInfo->iEntry[partitionCount].iPartitionType = partitionType; |
539 iPartitionInfo->iEntry[partitionCount].iPartitionType = partitionType; |
326 iPartitionAttributes[partitionCount] = partitionTable->iPartitions[index].iPartition_attributes; |
540 iPartitionAttributes[partitionCount] = partitionTable->iPartitions[index].iPartition_attributes; |
|
541 static_cast<DMmcMediaDriverFlash *>(iDriver)->SetEMmcPartitionMapping(partitionCount, iSelectedPartition); |
|
542 // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS. |
|
543 const TUint32 KStartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0; |
327 |
544 |
328 // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS. |
545 iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KStartOffset) << KDiskSectorShift; |
329 const TUint32 KstartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0; |
546 iPartitionInfo->iEntry[partitionCount].iPartitionLen = ((Int64) partitionTable->iPartitions[index].iSize - KStartOffset) << KDiskSectorShift; |
330 |
|
331 iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KstartOffset) << KDiskSectorShift; |
|
332 iPartitionInfo->iEntry[partitionCount].iPartitionLen = ((Int64) partitionTable->iPartitions[index].iSize - KstartOffset) << KDiskSectorShift; |
|
333 |
547 |
334 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount)); |
548 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount)); |
335 __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount)); |
549 __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount)); |
336 __KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector )); |
550 __KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector )); |
337 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift))); |
551 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift))); |
338 __KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize )); |
552 __KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize )); |
339 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift)); |
553 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift)); |
340 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType)); |
554 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType)); |
341 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount])); |
555 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount])); |
|
556 __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionMapping.: 0x%x", static_cast<DMmcMediaDriverFlash *>(iDriver)->GetEMmcPartitionMapping(partitionCount))); |
342 __KTRACE_OPT(KPBUSDRV, Kern::Printf(" ")); |
557 __KTRACE_OPT(KPBUSDRV, Kern::Printf(" ")); |
343 |
558 |
344 partitionCount++; |
559 partitionCount++; |
345 } |
560 } |
346 } |
561 } |
359 |
574 |
360 // Validate partition address boundaries |
575 // Validate partition address boundaries |
361 if(partitionCount == 0) |
576 if(partitionCount == 0) |
362 { |
577 { |
363 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!")); |
578 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!")); |
364 return KErrCorrupt; |
579 // No Supported partitions found on this physical partition |
365 } |
580 return KErrNone; |
366 #ifdef __DEBUG_CHECK_PARTITION_ |
581 } |
367 else |
582 |
368 { |
583 #ifdef __DEBUG_CHECK_PARTITION_ |
369 // at least one entry for a supported partition found |
584 // Validate partition address boundaries |
370 const TInt64 deviceSize = iCard->DeviceSize64(); |
585 TUint32 eMmcPartitionSizeInSectors = 0; |
|
586 if(r == KErrNone) |
|
587 { |
|
588 // At least one entry for a supported partition found |
|
589 r = GetPartitionSizeInSectors(iSelectedPartition, eMmcPartitionSizeInSectors); |
|
590 |
|
591 if(r != KErrNone) |
|
592 { |
|
593 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Could not retrieve size for eMMC partition 0x%02X", iSelectedPartition)); |
|
594 r = KErrCorrupt; |
|
595 } |
|
596 } |
|
597 |
|
598 if(r == KErrNone) |
|
599 { |
|
600 TUint64 eMmcPartitionSize = eMmcPartitionSizeInSectors * KSectorSize; |
|
601 |
371 TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1]; |
602 TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1]; |
372 |
603 |
373 // Check that the card address space boundary is not exceeded by the last partition |
604 // Check that the eMmcPartition address space boundary is not exceeded by the last partition |
374 if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize) |
605 if(part.iPartitionBaseAddr + part.iPartitionLen > eMmcPartitionSize) |
375 { |
606 { |
376 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space")); |
607 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Partition #%d exceeds eMmc address space", partitionCount)); |
377 return KErrCorrupt; |
608 r = KErrCorrupt; |
378 } |
609 } |
379 |
610 } |
380 // Go through all partition entries and check boundaries |
611 |
381 for(TInt i = partitionCount - 1; i > 0; i--) |
612 if(r == KErrNone) |
|
613 { |
|
614 // Go through all BB5 partition entries on this eMMC partition and check boundaries |
|
615 for(TInt i = partitionCount - 1; i > iPartitionInfo->iPartitionCount; i--) |
382 { |
616 { |
383 const TPartitionEntry& curr = iPartitionInfo->iEntry[i]; |
617 const TPartitionEntry& curr = iPartitionInfo->iEntry[i]; |
384 TPartitionEntry& prev = iPartitionInfo->iEntry[i-1]; |
618 TPartitionEntry& prev = iPartitionInfo->iEntry[i-1]; |
385 |
619 |
386 // Check if partitions overlap |
620 // Check if partitions overlap |
387 if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen)) |
621 if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen)) |
388 { |
622 { |
389 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions - check #%d", i)); |
623 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions - check #%d", i)); |
390 return KErrCorrupt; |
624 r = KErrCorrupt; |
391 } |
625 } |
392 } |
626 } |
393 } |
627 } |
394 #endif // _DEBUG_CHECK_PARTITION_ |
628 #endif // _DEBUG_CHECK_PARTITION_ |
395 |
629 |
396 iPartitionInfo->iPartitionCount = partitionCount; |
630 if(r == KErrNone) |
397 iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64(); |
631 { |
398 |
632 iPartitionInfo->iPartitionCount = partitionCount; |
399 //Notify medmmc that partitioninfo is complete. |
633 iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64(); |
400 iCallBack.CallBack(); |
634 } |
401 |
635 |
402 __KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)", partitionCount)); |
636 __KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)", partitionCount)); |
|
637 return r; |
|
638 } |
|
639 |
|
640 |
|
641 // End - DBB5PartitionInfo |
|
642 |
|
643 |
|
644 EXPORT_C DEMMCPartitionInfo* CreateEmmcPartitionInfo() |
|
645 { |
|
646 return new DBB5PartitionInfo; |
|
647 } |
|
648 |
|
649 DECLARE_STANDARD_EXTENSION() |
|
650 { |
403 return KErrNone; |
651 return KErrNone; |
404 } |
652 } |
405 |
653 |
406 |
|
407 // End - DBB5PartitionInfo |
|
408 |
|
409 |
|
410 EXPORT_C DEMMCPartitionInfo* CreateEmmcPartitionInfo() |
|
411 { |
|
412 return new DBB5PartitionInfo; |
|
413 } |
|
414 |
|
415 DECLARE_STANDARD_EXTENSION() |
|
416 { |
|
417 return KErrNone; |
|
418 } |
|
419 |
|
420 // End of File |
654 // End of File |
421 |
655 |