6edadf0b283c176a6a6c47fec982974d0051bf57
[reactos.git] / reactos / drivers / filesystems / udfs / udf_info / alloc.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 ////////////////////////////////////////////////////////////////////
5 /*
6 Module name:
7
8 alloc.cpp
9
10 Abstract:
11
12 This file contains filesystem-specific routines
13 responsible for disk space management
14
15 */
16
17 #include "udf.h"
18
19 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_ALLOC
20
21 static const int8 bit_count_tab[] = {
22 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
23 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
24 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
25 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
26 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
27 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
28 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
29 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
30
31 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
32 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
33 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
34 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
35 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
36 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
37 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
38 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
39 };
40
41 /*
42 This routine converts physical address to logical in specified partition
43 */
44 uint32
45 UDFPhysLbaToPart(
46 IN PVCB Vcb,
47 IN uint32 PartNum,
48 IN uint32 Addr
49 )
50 {
51 PUDFPartMap pm = Vcb->Partitions;
52 //#ifdef _X86_
53 #ifdef _MSC_VER
54 uint32 retval;
55 __asm {
56 push ebx
57 push ecx
58 push edx
59
60 mov ebx,Vcb
61 mov edx,[ebx]Vcb.PartitionMaps
62 mov ebx,pm
63 mov ecx,PartNum
64 xor eax,eax
65 loop_pl2p:
66 cmp ecx,edx
67 jae short EO_pl2p
68 cmp [ebx]pm.PartitionNum,cx
69 jne short cont_pl2p
70 mov eax,Addr
71 sub eax,[ebx]pm.PartitionRoot
72 mov ecx,Vcb
73 mov ecx,[ecx]Vcb.LB2B_Bits
74 shr eax,cl
75 jmp short EO_pl2p
76 cont_pl2p:
77 add ebx,size UDFPartMap
78 inc ecx
79 jmp short loop_pl2p
80 EO_pl2p:
81 mov retval,eax
82
83 pop edx
84 pop ecx
85 pop ebx
86 }
87 #ifdef UDF_DBG
88 {
89 // validate return value
90 lb_addr locAddr;
91 locAddr.logicalBlockNum = retval;
92 locAddr.partitionReferenceNum = (uint16)PartNum;
93 UDFPartLbaToPhys(Vcb, &locAddr);
94 }
95 #endif // UDF_DBG
96 return retval;
97 #else // NO X86 optimization , use generic C/C++
98 uint32 i;
99 // walk through partition maps to find suitable one...
100 for(i=PartNum; i<Vcb->PartitionMaps; i++, pm++) {
101 if(pm->PartitionNum == PartNum)
102 // wow! return relative address
103 return (Addr - pm->PartitionRoot) >> Vcb->LB2B_Bits;
104 }
105 return 0;
106 #endif // _X86_
107 } // end UDFPhysLbaToPart()
108
109 /*
110 This routine returns physycal Lba for partition-relative addr
111 */
112 uint32
113 __fastcall
114 UDFPartLbaToPhys(
115 IN PVCB Vcb,
116 IN lb_addr* Addr
117 )
118 {
119 uint32 i, a;
120 if(Addr->partitionReferenceNum >= Vcb->PartitionMaps) {
121 AdPrint(("UDFPartLbaToPhys: part %x, lbn %x (err)\n",
122 Addr->partitionReferenceNum, Addr->logicalBlockNum));
123 if(Vcb->PartitionMaps &&
124 (Vcb->CompatFlags & UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS)) {
125 AdPrint(("UDFPartLbaToPhys: try to recover: part %x -> %x\n",
126 Addr->partitionReferenceNum, Vcb->PartitionMaps-1));
127 Addr->partitionReferenceNum = (USHORT)(Vcb->PartitionMaps-1);
128 } else {
129 return LBA_OUT_OF_EXTENT;
130 }
131 }
132 // walk through partition maps & transform relative address
133 // to physical
134 for(i=Addr->partitionReferenceNum; i<Vcb->PartitionMaps; i++) {
135 if(Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) {
136 a = Vcb->Partitions[i].PartitionRoot +
137 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
138 if(a > Vcb->LastPossibleLBA) {
139 AdPrint(("UDFPartLbaToPhys: root %x, lbn %x, lba %x (err1)\n",
140 Vcb->Partitions[i].PartitionRoot, Addr->logicalBlockNum, a));
141 BrutePoint();
142 return LBA_OUT_OF_EXTENT;
143 }
144 return a;
145 }
146 }
147 a = Vcb->Partitions[i-1].PartitionRoot +
148 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
149 if(a > Vcb->LastPossibleLBA) {
150 AdPrint(("UDFPartLbaToPhys: i %x, root %x, lbn %x, lba %x (err2)\n",
151 i, Vcb->Partitions[i-1].PartitionRoot, Addr->logicalBlockNum, a));
152 BrutePoint();
153 return LBA_OUT_OF_EXTENT;
154 }
155 return a;
156 } // end UDFPartLbaToPhys()
157
158
159 /*
160 This routine returns physycal Lba for partition-relative addr
161 No partition bounds check is performed.
162 This routine only checks if requested partition exists.
163 It is introduced for 'Adaptec DirectCD' compatibility,
164 because it uses negative values as extent terminator (against standard)
165 */
166 /*uint32
167 __fastcall
168 UDFPartLbaToPhysCompat(
169 IN PVCB Vcb,
170 IN lb_addr* Addr
171 )
172 {
173 uint32 i, a;
174 if(Addr->partitionReferenceNum >= Vcb->PartitionMaps) return LBA_NOT_ALLOCATED;
175 // walk through partition maps & transform relative address
176 // to physical
177 for(i=Addr->partitionReferenceNum; i<Vcb->PartitionMaps; i++) {
178 if(Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) {
179 a = Vcb->Partitions[i].PartitionRoot +
180 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
181 if(a > Vcb->LastPossibleLBA) {
182 BrutePoint();
183 }
184 return a;
185 }
186 }
187 a = Vcb->Partitions[i-1].PartitionRoot +
188 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
189 if(a > Vcb->LastPossibleLBA) {
190 BrutePoint();
191 }
192 return a;
193 } // end UDFPartLbaToPhysCompat()*/
194
195
196 /*
197 This routine looks for the partition containing given physical sector
198 */
199 uint32
200 __fastcall
201 UDFGetPartNumByPhysLba(
202 IN PVCB Vcb,
203 IN uint32 Lba
204 )
205 {
206 uint32 i=Vcb->PartitionMaps-1, root;
207 PUDFPartMap pm = &(Vcb->Partitions[i]);
208 // walk through the partition maps to find suitable one
209 for(;i!=0xffffffff;i--,pm--) {
210 if( ((root = pm->PartitionRoot) <= Lba) &&
211 ((root + pm->PartitionLen) > Lba) ) return (uint16)pm->PartitionNum;
212 }
213 return LBA_OUT_OF_EXTENT; // Lba doesn't belong to any partition
214 } // end UDFGetPartNumByPhysLba()
215
216 /*
217 Very simple routine. It walks through the Partition Maps & returns
218 the 1st Lba of the 1st suitable one
219 */
220 uint32
221 __fastcall
222 UDFPartStart(
223 PVCB Vcb,
224 uint32 PartNum
225 )
226 {
227 uint32 i;
228 if(PartNum == (uint32)-1) return 0;
229 if(PartNum == (uint32)-2) return Vcb->Partitions[0].PartitionRoot;
230 for(i=PartNum; i<Vcb->PartitionMaps; i++) {
231 if(Vcb->Partitions[i].PartitionNum == PartNum) return Vcb->Partitions[i].PartitionRoot;
232 }
233 return 0;
234 } // end UDFPartStart(
235
236 /*
237 This routine does almost the same as previous.
238 The only difference is changing First Lba to Last one...
239 */
240 uint32
241 __fastcall
242 UDFPartEnd(
243 PVCB Vcb,
244 uint32 PartNum
245 )
246 {
247 uint32 i;
248 if(PartNum == (uint32)-1) return Vcb->LastLBA;
249 if(PartNum == (uint32)-2) PartNum = Vcb->PartitionMaps-1;
250 for(i=PartNum; i<Vcb->PartitionMaps; i++) {
251 if(Vcb->Partitions[i].PartitionNum == PartNum)
252 return (Vcb->Partitions[i].PartitionRoot +
253 Vcb->Partitions[i].PartitionLen);
254 }
255 return (Vcb->Partitions[i-1].PartitionRoot +
256 Vcb->Partitions[i-1].PartitionLen);
257 } // end UDFPartEnd()
258
259 /*
260 Very simple routine. It walks through the Partition Maps & returns
261 the 1st Lba of the 1st suitable one
262 */
263 uint32
264 __fastcall
265 UDFPartLen(
266 PVCB Vcb,
267 uint32 PartNum
268 )
269 {
270
271 if(PartNum == (uint32)-2) return UDFPartEnd(Vcb, -2) - UDFPartStart(Vcb, -2);
272 /*#ifdef _X86_
273 uint32 ret_val;
274 __asm {
275 mov ebx,Vcb
276 mov eax,PartNum
277 cmp eax,-1
278 jne short NOT_last_gpl
279 mov eax,[ebx]Vcb.LastLBA
280 jmp short EO_gpl
281 NOT_last_gpl:
282 mov esi,eax
283 xor eax,eax
284 mov ecx,[ebx]Vcb.PartitionMaps
285 jecxz EO_gpl
286
287 mov eax,esi
288 mov edx,size UDFTrackMap
289 mul edx
290 add ebx,eax
291 mov eax,esi
292 gpl_loop:
293 cmp [ebx]Vcb.PartitionMaps.PartitionNum,ax
294 je short EO_gpl_1
295 add ebx,size UDFTrackMap
296 inc eax
297 cmp eax,ecx
298 jb short gpl_loop
299 sub ebx,size UDFTrackMap
300 EO_gpl_1:
301 mov eax,[ebx]Vcb.PartitionMaps.PartitionLen
302 add eax,[ebx]Vcb.PartitionMaps.PartitionRoot
303 EO_gpl:
304 mov ret_val,eax
305 }
306 return ret_val;
307 #else // NO X86 optimization , use generic C/C++*/
308 uint32 i;
309 if(PartNum == (uint32)-1) return Vcb->LastLBA;
310 for(i=PartNum; i<Vcb->PartitionMaps; i++) {
311 if(Vcb->Partitions[i].PartitionNum == PartNum)
312 return Vcb->Partitions[i].PartitionLen;
313 }
314 return (Vcb->Partitions[i-1].PartitionRoot +
315 Vcb->Partitions[i-1].PartitionLen);
316 /*#endif // _X86_*/
317 } // end UDFPartLen()
318
319 /*
320 This routine returns length of bit-chain starting from Offs bit in
321 array Bitmap. Bitmap scan is limited with Lim.
322 */
323
324 //#if defined _X86_
325 #if defined _MSC_VER
326
327 __declspec (naked)
328 uint32
329 __stdcall
330 UDFGetBitmapLen(
331 uint32* Bitmap,
332 uint32 Offs,
333 uint32 Lim // NOT included
334 )
335 {
336 _asm {
337 push ebp
338 mov ebp, esp
339
340 push ebx
341 push ecx
342 push edx
343 push esi
344 push edi
345
346 xor edx,edx // init bit-counter
347 mov ebx,[ebp+0x08] // set base pointer in EBX (Bitmap)
348 mov esi,[ebp+0x0c] // set Offs in ESI
349 mov edi,[ebp+0x10] // set Lim in EDI
350
351 // check if Lim <= Offs
352 cmp esi,edi
353 // jb start_count
354 // ja exit_count
355 // inc edx
356 // jmp exit_count
357 jae exit_count
358
359 //start_count:
360
361 // set 1st bit number in CL
362 mov ecx,esi
363 and cl,0x1f
364 // make ESI uint32-index
365 shr esi,5
366
367 // save last bit number in CH
368 mov eax,edi
369 and al,0x1f
370 mov ch,al
371 // make EDI uint32-index of the last uint32
372 shr edi,5
373
374 mov eax,[ebx+esi*4]
375 shr eax,cl
376 test eax,1
377
378 jz Loop_0
379
380 /* COUNT 1-BITS SECTION */
381 Loop_1:
382
383 cmp esi,edi
384 ja exit_count // must never happen
385 jb non_last_1
386
387 Loop_last_1:
388
389 cmp cl,ch
390 jae exit_count
391 // do we met 0 ?
392 test eax,1
393 jz exit_count
394 shr eax,1
395 inc edx
396 inc cl
397 jmp Loop_last_1
398
399 non_last_1:
400
401 or cl,cl
402 jnz std_count_1
403 cmp eax,-1
404 je quick_count_1
405
406 std_count_1:
407
408 cmp cl,0x1f
409 ja next_uint32_1
410 // do we met 0 ?
411 test eax,1
412 jz exit_count
413 shr eax,1
414 inc edx
415 inc cl
416 jmp std_count_1
417
418 quick_count_1:
419
420 add edx,0x20
421
422 next_uint32_1:
423
424 inc esi
425 mov eax,[ebx+esi*4]
426 xor cl,cl
427 jmp Loop_1
428
429 /* COUNT 0-BITS SECTION */
430 Loop_0:
431
432 cmp esi,edi
433 ja exit_count // must never happen
434 jb non_last_0
435
436 Loop_last_0:
437
438 cmp cl,ch
439 jae exit_count
440 // do we met 1 ?
441 test eax,1
442 jnz exit_count
443 shr eax,1
444 inc edx
445 inc cl
446 jmp Loop_last_0
447
448 non_last_0:
449
450 or cl,cl
451 jnz std_count_0
452 or eax,eax
453 jz quick_count_0
454
455 std_count_0:
456
457 cmp cl,0x1f
458 ja next_uint32_0
459 // do we met 1 ?
460 test eax,1
461 jnz exit_count
462 shr eax,1
463 inc edx
464 inc cl
465 jmp std_count_0
466
467 quick_count_0:
468
469 add edx,0x20
470
471 next_uint32_0:
472
473 inc esi
474 mov eax,[ebx+esi*4]
475 xor cl,cl
476 jmp Loop_0
477
478 exit_count:
479
480 mov eax,edx
481
482 pop edi
483 pop esi
484 pop edx
485 pop ecx
486 pop ebx
487
488 pop ebp
489
490 ret 0x0c
491 }
492
493 #else // NO X86 optimization , use generic C/C++
494
495 uint32
496 __stdcall
497 UDFGetBitmapLen(
498 uint32* Bitmap,
499 uint32 Offs,
500 uint32 Lim // NOT included
501 )
502 {
503 ASSERT(Offs <= Lim);
504 if(Offs >= Lim) {
505 return 0;//(Offs == Lim);
506 }
507
508 BOOLEAN bit = UDFGetBit(Bitmap, Offs);
509 uint32 i=Offs>>5;
510 uint32 len=0;
511 uint8 j=(uint8)(Offs&31);
512 uint8 lLim=(uint8)(Lim&31);
513
514 Lim = Lim>>5;
515
516 ASSERT((bit == 0) || (bit == 1));
517
518 uint32 a;
519
520 a = Bitmap[i] >> j;
521
522 while(i<=Lim) {
523
524 while( j < ((i<Lim) ? 32 : lLim) ) {
525 if( ((BOOLEAN)(a&1)) != bit)
526 return len;
527 len++;
528 a>>=1;
529 j++;
530 }
531 j=0;
532 While_3:
533 i++;
534 a = Bitmap[i];
535
536 if(i<Lim) {
537 if((bit && (a==0xffffffff)) ||
538 (!bit && !a)) {
539 len+=32;
540 goto While_3;
541 }
542 }
543 }
544
545 return len;
546
547 #endif // _X86_
548
549 } // end UDFGetBitmapLen()
550
551 #ifndef UDF_READ_ONLY_BUILD
552 /*
553 This routine scans disc free space Bitmap for minimal suitable extent.
554 It returns maximal available extent if no long enough extents found.
555 */
556 uint32
557 UDFFindMinSuitableExtent(
558 IN PVCB Vcb,
559 IN uint32 Length, // in blocks
560 IN uint32 SearchStart,
561 IN uint32 SearchLim, // NOT included
562 OUT uint32* MaxExtLen,
563 IN uint8 AllocFlags
564 )
565 {
566 uint32 i, len;
567 uint32* cur;
568 uint32 best_lba=0;
569 uint32 best_len=0;
570 uint32 max_lba=0;
571 uint32 max_len=0;
572 BOOLEAN align = FALSE;
573 uint32 PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits;
574
575 UDF_CHECK_BITMAP_RESOURCE(Vcb);
576
577 // we'll try to allocate packet-aligned block at first
578 if(!(Length & (PS-1)) && !Vcb->CDR_Mode && (Length >= PS*2))
579 align = TRUE;
580 if(AllocFlags & EXTENT_FLAG_ALLOC_SEQUENTIAL)
581 align = TRUE;
582 if(Length > (uint32)(UDF_MAX_EXTENT_LENGTH >> Vcb->BlockSizeBits))
583 Length = (UDF_MAX_EXTENT_LENGTH >> Vcb->BlockSizeBits);
584 // align Length according to _Logical_ block size & convert it to BCount
585 i = (1<<Vcb->LB2B_Bits)-1;
586 Length = (Length+i) & ~i;
587 cur = (uint32*)(Vcb->FSBM_Bitmap);
588
589 retry_no_align:
590
591 i=SearchStart;
592 // scan Bitmap
593 while(i<SearchLim) {
594 ASSERT(i <= SearchLim);
595 if(align) {
596 i = (i+PS-1) & ~(PS-1);
597 ASSERT(i <= SearchLim);
598 if(i >= SearchLim)
599 break;
600 }
601 len = UDFGetBitmapLen(cur, i, SearchLim);
602 if(UDFGetFreeBit(cur, i)) { // is the extent found free or used ?
603 // wow! it is free!
604 if(len >= Length) {
605 // minimize extent length
606 if(!best_len || (best_len > len)) {
607 best_lba = i;
608 best_len = len;
609 }
610 if(len == Length)
611 break;
612 } else {
613 // remember max extent
614 if(max_len < len) {
615 max_lba = i;
616 max_len = len;
617 }
618 }
619 // if this is CD-R mode, we should not think about fragmentation
620 // due to CD-R nature file will be fragmented in any case
621 if(Vcb->CDR_Mode) break;
622 }
623 i += len;
624 }
625 // if we can't find suitable Packet-size aligned block,
626 // retry without any alignment requirements
627 if(!best_len && align) {
628 align = FALSE;
629 goto retry_no_align;
630 }
631 if(best_len) {
632 // minimal suitable block
633 (*MaxExtLen) = best_len;
634 return best_lba;
635 }
636 // maximal available
637 (*MaxExtLen) = max_len;
638 return max_lba;
639 } // end UDFFindMinSuitableExtent()
640 #endif //UDF_READ_ONLY_BUILD
641
642 #ifdef UDF_CHECK_DISK_ALLOCATION
643 /*
644 This routine checks space described by Mapping as Used/Freed (optionaly)
645 */
646 void
647 UDFCheckSpaceAllocation_(
648 IN PVCB Vcb,
649 IN PEXTENT_MAP Map,
650 IN uint32 asXXX
651 #ifdef UDF_TRACK_ONDISK_ALLOCATION
652 ,IN uint32 FE_lba,
653 IN uint32 BugCheckId,
654 IN uint32 Line
655 #endif //UDF_TRACK_ONDISK_ALLOCATION
656 )
657 {
658 uint32 i=0;
659 uint32 lba, j, len, BS, BSh;
660 BOOLEAN asUsed = (asXXX == AS_USED);
661
662 if(!Map) return;
663
664 BS = Vcb->BlockSize;
665 BSh = Vcb->BlockSizeBits;
666
667 UDFAcquireResourceShared(&(Vcb->BitMapResource1),TRUE);
668 // walk through all frags in data area specified
669 #ifdef UDF_TRACK_ONDISK_ALLOCATION
670 AdPrint(("ChkAlloc:Map:%x:File:%x:Line:%d\n",
671 Map,
672 BugCheckId,
673 Line
674 ));
675 #endif //UDF_TRACK_ONDISK_ALLOCATION
676 while(Map[i].extLength & UDF_EXTENT_LENGTH_MASK) {
677
678 #ifdef UDF_TRACK_ONDISK_ALLOCATION
679 AdPrint(("ChkAlloc:%x:%s:%x:@:%x:(%x):File:%x:Line:%d\n",
680 FE_lba,
681 asUsed ? "U" : "F",
682 (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh,
683 Map[i].extLocation,
684 (Map[i].extLength >> 30),
685 BugCheckId,
686 Line
687 ));
688 #endif //UDF_TRACK_ONDISK_ALLOCATION
689 if(asUsed) {
690 UDFCheckUsedBitOwner(Vcb, (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh, FE_lba);
691 } else {
692 UDFCheckFreeBitOwner(Vcb, (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh);
693 }
694
695 if((Map[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) {
696 // skip unallocated frags
697 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
698 ASSERT(!Map[i].extLocation);
699 i++;
700 continue;
701 } else {
702 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
703 ASSERT(Map[i].extLocation);
704 }
705
706 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
707 ASSERT(!(Map[i].extLength & (BS-1)));
708 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
709 len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
710 lba = Map[i].extLocation;
711 if((lba+len) > Vcb->LastPossibleLBA) {
712 // skip blocks beyond media boundary
713 if(lba > Vcb->LastPossibleLBA) {
714 ASSERT(FALSE);
715 i++;
716 continue;
717 }
718 len = Vcb->LastPossibleLBA - lba;
719 }
720
721 // mark frag as XXX (see asUsed parameter)
722 if(asUsed) {
723
724 ASSERT(len);
725 for(j=0;j<len;j++) {
726 if(lba+j > Vcb->LastPossibleLBA) {
727 BrutePoint();
728 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba+j));
729 break;
730 }
731 if(!UDFGetUsedBit(Vcb->FSBM_Bitmap, lba+j)) {
732 BrutePoint();
733 AdPrint(("USED Mapping covers FREE block(s) @%x\n",lba+j));
734 break;
735 }
736 }
737
738 } else {
739
740 ASSERT(len);
741 for(j=0;j<len;j++) {
742 if(lba+j > Vcb->LastPossibleLBA) {
743 BrutePoint();
744 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba+j));
745 break;
746 }
747 if(!UDFGetFreeBit(Vcb->FSBM_Bitmap, lba+j)) {
748 BrutePoint();
749 AdPrint(("FREE Mapping covers USED block(s) @%x\n",lba+j));
750 break;
751 }
752 }
753 }
754
755 i++;
756 }
757 UDFReleaseResource(&(Vcb->BitMapResource1));
758 } // end UDFCheckSpaceAllocation_()
759 #endif //UDF_CHECK_DISK_ALLOCATION
760
761 void
762 UDFMarkBadSpaceAsUsed(
763 IN PVCB Vcb,
764 IN lba_t lba,
765 IN ULONG len
766 )
767 {
768 uint32 j;
769 #define BIT_C (sizeof(Vcb->BSBM_Bitmap[0])*8)
770 len = (lba+len+BIT_C-1)/BIT_C;
771 if(Vcb->BSBM_Bitmap) {
772 for(j=lba/BIT_C; j<len; j++) {
773 Vcb->FSBM_Bitmap[j] &= ~Vcb->BSBM_Bitmap[j];
774 }
775 }
776 #undef BIT_C
777 } // UDFMarkBadSpaceAsUsed()
778
779 /*
780 This routine marks space described by Mapping as Used/Freed (optionaly)
781 */
782 void
783 UDFMarkSpaceAsXXXNoProtect_(
784 IN PVCB Vcb,
785 IN PEXTENT_MAP Map,
786 IN uint32 asXXX
787 #ifdef UDF_TRACK_ONDISK_ALLOCATION
788 ,IN uint32 FE_lba,
789 IN uint32 BugCheckId,
790 IN uint32 Line
791 #endif //UDF_TRACK_ONDISK_ALLOCATION
792 )
793 {
794 uint32 i=0;
795 uint32 lba, j, len, BS, BSh;
796 uint32 root;
797 BOOLEAN asUsed = (asXXX == AS_USED || (asXXX & AS_BAD));
798 #ifdef UDF_TRACK_ONDISK_ALLOCATION
799 BOOLEAN bit_before, bit_after;
800 #endif //UDF_TRACK_ONDISK_ALLOCATION
801
802 UDF_CHECK_BITMAP_RESOURCE(Vcb);
803
804 if(!Map) return;
805
806 BS = Vcb->BlockSize;
807 BSh = Vcb->BlockSizeBits;
808 Vcb->BitmapModified = TRUE;
809 UDFSetModified(Vcb);
810 // walk through all frags in data area specified
811 while(Map[i].extLength & UDF_EXTENT_LENGTH_MASK) {
812 if((Map[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) {
813 // skip unallocated frags
814 i++;
815 continue;
816 }
817 ASSERT(Map[i].extLocation);
818
819 #ifdef UDF_TRACK_ONDISK_ALLOCATION
820 AdPrint(("Alloc:%x:%s:%x:@:%x:File:%x:Line:%d\n",
821 FE_lba,
822 asUsed ? ((asXXX & AS_BAD) ? "B" : "U") : "F",
823 (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits,
824 Map[i].extLocation,
825 BugCheckId,
826 Line
827 ));
828 #endif //UDF_TRACK_ONDISK_ALLOCATION
829
830 #ifdef UDF_DBG
831 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
832 ASSERT(!(Map[i].extLength & (BS-1)));
833 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
834 // len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
835 #else // UDF_DBG
836 // len = (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh;
837 #endif // UDF_DBG
838 len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
839 lba = Map[i].extLocation;
840 if((lba+len) > Vcb->LastPossibleLBA) {
841 // skip blocks beyond media boundary
842 if(lba > Vcb->LastPossibleLBA) {
843 ASSERT(FALSE);
844 i++;
845 continue;
846 }
847 len = Vcb->LastPossibleLBA - lba;
848 }
849
850 #ifdef UDF_TRACK_ONDISK_ALLOCATION
851 if(lba)
852 bit_before = UDFGetBit(Vcb->FSBM_Bitmap, lba-1);
853 bit_after = UDFGetBit(Vcb->FSBM_Bitmap, lba+len);
854 #endif //UDF_TRACK_ONDISK_ALLOCATION
855
856 // mark frag as XXX (see asUsed parameter)
857 if(asUsed) {
858 /* for(j=0;j<len;j++) {
859 UDFSetUsedBit(Vcb->FSBM_Bitmap, lba+j);
860 }*/
861 ASSERT(len);
862 UDFSetUsedBits(Vcb->FSBM_Bitmap, lba, len);
863 #ifdef UDF_TRACK_ONDISK_ALLOCATION
864 for(j=0;j<len;j++) {
865 ASSERT(UDFGetUsedBit(Vcb->FSBM_Bitmap, lba+j));
866 }
867 #endif //UDF_TRACK_ONDISK_ALLOCATION
868
869 if(Vcb->Vat) {
870 // mark logical blocks in VAT as used
871 for(j=0;j<len;j++) {
872 root = UDFPartStart(Vcb, UDFGetPartNumByPhysLba(Vcb, lba));
873 if((Vcb->Vat[lba-root+j] == UDF_VAT_FREE_ENTRY) &&
874 (lba > Vcb->LastLBA)) {
875 Vcb->Vat[lba-root+j] = 0x7fffffff;
876 }
877 }
878 }
879 } else {
880 /* for(j=0;j<len;j++) {
881 UDFSetFreeBit(Vcb->FSBM_Bitmap, lba+j);
882 }*/
883 ASSERT(len);
884 UDFSetFreeBits(Vcb->FSBM_Bitmap, lba, len);
885 #ifdef UDF_TRACK_ONDISK_ALLOCATION
886 for(j=0;j<len;j++) {
887 ASSERT(UDFGetFreeBit(Vcb->FSBM_Bitmap, lba+j));
888 }
889 #endif //UDF_TRACK_ONDISK_ALLOCATION
890 if(asXXX & AS_BAD) {
891 UDFSetBits(Vcb->BSBM_Bitmap, lba, len);
892 }
893 UDFMarkBadSpaceAsUsed(Vcb, lba, len);
894
895 if(asXXX & AS_DISCARDED) {
896 UDFUnmapRange(Vcb, lba, len);
897 WCacheDiscardBlocks__(&(Vcb->FastCache), Vcb, lba, len);
898 UDFSetZeroBits(Vcb->ZSBM_Bitmap, lba, len);
899 }
900 if(Vcb->Vat) {
901 // mark logical blocks in VAT as free
902 // this operation can decrease resulting VAT size
903 for(j=0;j<len;j++) {
904 root = UDFPartStart(Vcb, UDFGetPartNumByPhysLba(Vcb, lba));
905 Vcb->Vat[lba-root+j] = UDF_VAT_FREE_ENTRY;
906 }
907 }
908 // mark discarded extent as Not-Alloc-Not-Rec to
909 // prevent writes there
910 Map[i].extLength = (len << BSh) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30);
911 Map[i].extLocation = 0;
912 }
913
914 #ifdef UDF_TRACK_ONDISK_ALLOCATION
915 if(lba)
916 ASSERT(bit_before == UDFGetBit(Vcb->FSBM_Bitmap, lba-1));
917 ASSERT(bit_after == UDFGetBit(Vcb->FSBM_Bitmap, lba+len));
918 #endif //UDF_TRACK_ONDISK_ALLOCATION
919
920 i++;
921 }
922 } // end UDFMarkSpaceAsXXXNoProtect_()
923
924 /*
925 This routine marks space described by Mapping as Used/Freed (optionaly)
926 It protects data with sync Resource
927 */
928 void
929 UDFMarkSpaceAsXXX_(
930 IN PVCB Vcb,
931 IN PEXTENT_MAP Map,
932 IN uint32 asXXX
933 #ifdef UDF_TRACK_ONDISK_ALLOCATION
934 ,IN uint32 FE_lba,
935 IN uint32 BugCheckId,
936 IN uint32 Line
937 #endif //UDF_TRACK_ONDISK_ALLOCATION
938 )
939 {
940 if(!Map) return;
941 if(!Map[0].extLength) {
942 #ifdef UDF_DBG
943 ASSERT(!Map[0].extLocation);
944 #endif // UDF_DBG
945 return;
946 }
947
948 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
949 #ifdef UDF_TRACK_ONDISK_ALLOCATION
950 UDFMarkSpaceAsXXXNoProtect_(Vcb, Map, asXXX, FE_lba, BugCheckId, Line);
951 #else //UDF_TRACK_ONDISK_ALLOCATION
952 UDFMarkSpaceAsXXXNoProtect_(Vcb, Map, asXXX);
953 #endif //UDF_TRACK_ONDISK_ALLOCATION
954 UDFReleaseResource(&(Vcb->BitMapResource1));
955
956 } // end UDFMarkSpaceAsXXX_()
957
958 #ifndef UDF_READ_ONLY_BUILD
959 /*
960 This routine builds mapping for Length bytes in FreeSpace
961 It should be used when IN_ICB method is unavailable.
962 */
963 OSSTATUS
964 UDFAllocFreeExtent_(
965 IN PVCB Vcb,
966 IN int64 Length,
967 IN uint32 SearchStart,
968 IN uint32 SearchLim, // NOT included
969 OUT PEXTENT_INFO ExtInfo,
970 IN uint8 AllocFlags
971 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
972 ,IN uint32 src,
973 IN uint32 line
974 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
975 )
976 {
977 EXTENT_AD Ext;
978 PEXTENT_MAP Map = NULL;
979 uint32 len, LBS, BSh, blen;
980
981 LBS = Vcb->LBlockSize;
982 BSh = Vcb->BlockSizeBits;
983 blen = (uint32)(((Length+LBS-1) & ~((int64)LBS-1)) >> BSh);
984 ExtInfo->Mapping = NULL;
985 ExtInfo->Offset = 0;
986
987 ASSERT(blen <= (uint32)(UDF_MAX_EXTENT_LENGTH >> BSh));
988
989 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
990
991 if(blen > (SearchLim - SearchStart)) {
992 goto no_free_space_err;
993 }
994 // walk through the free space bitmap & find a single extent or a set of
995 // frags giving in sum the Length specified
996 while(blen) {
997 Ext.extLocation = UDFFindMinSuitableExtent(Vcb, blen, SearchStart,
998 SearchLim, &len, AllocFlags);
999
1000 // ASSERT(len <= (uint32)(UDF_MAX_EXTENT_LENGTH >> BSh));
1001 if(len >= blen) {
1002 // complete search
1003 Ext.extLength = blen<<BSh;
1004 blen = 0;
1005 } else if(len) {
1006 // we need still some frags to complete request &
1007 // probably we have the opportunity to do it
1008 Ext.extLength = len<<BSh;
1009 blen -= len;
1010 } else {
1011 no_free_space_err:
1012 // no more free space. abort
1013 if(ExtInfo->Mapping) {
1014 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, ExtInfo->Mapping, AS_DISCARDED); // free
1015 MyFreePool__(ExtInfo->Mapping);
1016 ExtInfo->Mapping = NULL;
1017 }
1018 UDFReleaseResource(&(Vcb->BitMapResource1));
1019 ExtInfo->Length = 0;//UDFGetExtentLength(ExtInfo->Mapping);
1020 AdPrint((" DISK_FULL\n"));
1021 return STATUS_DISK_FULL;
1022 }
1023 // append the frag found to mapping
1024 ASSERT(!(Ext.extLength >> 30));
1025 ASSERT(Ext.extLocation);
1026
1027 // mark newly allocated blocks as zero-filled
1028 UDFSetZeroBits(Vcb->ZSBM_Bitmap, Ext.extLocation, (Ext.extLength & UDF_EXTENT_LENGTH_MASK) >> BSh);
1029
1030 if(AllocFlags & EXTENT_FLAG_VERIFY) {
1031 if(!UDFCheckArea(Vcb, Ext.extLocation, Ext.extLength >> BSh)) {
1032 AdPrint(("newly allocated extent contains BB\n"));
1033 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, ExtInfo->Mapping, AS_DISCARDED); // free
1034 UDFMarkBadSpaceAsUsed(Vcb, Ext.extLocation, Ext.extLength >> BSh); // bad -> bad+used
1035 // roll back
1036 blen += Ext.extLength>>BSh;
1037 continue;
1038 }
1039 }
1040
1041 Ext.extLength |= EXTENT_NOT_RECORDED_ALLOCATED << 30;
1042 if(!(ExtInfo->Mapping)) {
1043 // create new
1044 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
1045 ExtInfo->Mapping = UDFExtentToMapping_(&Ext, src, line);
1046 #else // UDF_TRACK_ALLOC_FREE_EXTENT
1047 ExtInfo->Mapping = UDFExtentToMapping(&Ext);
1048 #endif // UDF_TRACK_ALLOC_FREE_EXTENT
1049 if(!ExtInfo->Mapping) {
1050 BrutePoint();
1051 UDFReleaseResource(&(Vcb->BitMapResource1));
1052 ExtInfo->Length = 0;
1053 return STATUS_INSUFFICIENT_RESOURCES;
1054 }
1055 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, ExtInfo->Mapping, AS_USED); // used
1056 } else {
1057 // update existing
1058 Map = UDFExtentToMapping(&Ext);
1059 if(!Map) {
1060 BrutePoint();
1061 UDFReleaseResource(&(Vcb->BitMapResource1));
1062 ExtInfo->Length = UDFGetExtentLength(ExtInfo->Mapping);
1063 return STATUS_INSUFFICIENT_RESOURCES;
1064 }
1065 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, Map, AS_USED); // used
1066 ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, Map);
1067 MyFreePool__(Map);
1068 }
1069 if(!ExtInfo->Mapping) {
1070 BrutePoint();
1071 UDFReleaseResource(&(Vcb->BitMapResource1));
1072 ExtInfo->Length = 0;
1073 return STATUS_INSUFFICIENT_RESOURCES;
1074 }
1075 }
1076 UDFReleaseResource(&(Vcb->BitMapResource1));
1077 ExtInfo->Length = Length;
1078 return STATUS_SUCCESS;
1079 } // end UDFAllocFreeExtent_()
1080 #endif //UDF_READ_ONLY_BUILD
1081
1082 /*
1083 Returns block-count
1084 */
1085 uint32
1086 __fastcall
1087 UDFGetPartFreeSpace(
1088 IN PVCB Vcb,
1089 IN uint32 partNum
1090 )
1091 {
1092 uint32 lim/*, len=1*/;
1093 uint32 s=0;
1094 uint32 j;
1095 PUCHAR cur = (PUCHAR)(Vcb->FSBM_Bitmap);
1096
1097 lim = (UDFPartEnd(Vcb,partNum)+7)/8;
1098 for(j=(UDFPartStart(Vcb,partNum)+7)/8; j<lim/* && len*/; j++) {
1099 s+=bit_count_tab[cur[j]];
1100 }
1101 return s;
1102 } // end UDFGetPartFreeSpace()
1103
1104 int64
1105 __fastcall
1106 UDFGetFreeSpace(
1107 IN PVCB Vcb
1108 )
1109 {
1110 int64 s=0;
1111 uint32 i;
1112 // uint32* cur = (uint32*)(Vcb->FSBM_Bitmap);
1113
1114 if(!Vcb->CDR_Mode &&
1115 !(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
1116 for(i=0;i<Vcb->PartitionMaps;i++) {
1117 /* lim = UDFPartEnd(Vcb,i);
1118 for(j=UDFPartStart(Vcb,i); j<lim && len; ) {
1119 len = UDFGetBitmapLen(cur, j, lim);
1120 if(UDFGetFreeBit(cur, j)) // is the extent found free or used ?
1121 s+=len;
1122 j+=len;
1123 }*/
1124 s += UDFGetPartFreeSpace(Vcb, i);
1125 }
1126 } else {
1127 ASSERT(Vcb->LastPossibleLBA >= max(Vcb->NWA, Vcb->LastLBA));
1128 s = Vcb->LastPossibleLBA - max(Vcb->NWA, Vcb->LastLBA);
1129 //if(s & ((int64)1 << 64)) s=0;
1130 }
1131 return s >> Vcb->LB2B_Bits;
1132 } // end UDFGetFreeSpace()
1133
1134 /*
1135 Returns block-count
1136 */
1137 int64
1138 __fastcall
1139 UDFGetTotalSpace(
1140 IN PVCB Vcb
1141 )
1142 {
1143 int64 s=0;
1144 uint32 i;
1145
1146 if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
1147 s= Vcb->LastPossibleLBA;
1148 } else if(!Vcb->CDR_Mode) {
1149 for(i=0;i<Vcb->PartitionMaps;i++) {
1150 s+=Vcb->Partitions[i].PartitionLen;
1151 }
1152 } else {
1153 if(s & ((int64)1 << 64)) s=0;
1154 s= Vcb->LastPossibleLBA - Vcb->Partitions[0].PartitionRoot;
1155 }
1156 return s >> Vcb->LB2B_Bits;
1157 } // end UDFGetTotalSpace()
1158
1159 /*
1160 Callback for WCache
1161 returns Allocated and Zero-filled flags for given block
1162 any data in 'unallocated' blocks may be changed during flush process
1163 */
1164 uint32
1165 UDFIsBlockAllocated(
1166 IN void* _Vcb,
1167 IN uint32 Lba
1168 )
1169 {
1170 ULONG ret_val = 0;
1171 uint32* bm;
1172 // return TRUE;
1173 if(!(((PVCB)_Vcb)->VCBFlags & UDF_VCB_ASSUME_ALL_USED)) {
1174 // check used
1175 if((bm = (uint32*)(((PVCB)_Vcb)->FSBM_Bitmap)))
1176 ret_val = (UDFGetUsedBit(bm, Lba) ? WCACHE_BLOCK_USED : 0);
1177 // check zero-filled
1178 if((bm = (uint32*)(((PVCB)_Vcb)->ZSBM_Bitmap)))
1179 ret_val |= (UDFGetZeroBit(bm, Lba) ? WCACHE_BLOCK_ZERO : 0);
1180 } else {
1181 ret_val = WCACHE_BLOCK_USED;
1182 }
1183 // check bad block
1184
1185 // WCache works with LOGICAL addresses, not PHYSICAL, BB check must be performed UNDER cache
1186 /*
1187 if(bm = (uint32*)(((PVCB)_Vcb)->BSBM_Bitmap)) {
1188 ret_val |= (UDFGetBadBit(bm, Lba) ? WCACHE_BLOCK_BAD : 0);
1189 if(ret_val & WCACHE_BLOCK_BAD) {
1190 KdPrint(("Marked BB @ %#x\n", Lba));
1191 }
1192 }
1193 */
1194 return ret_val;
1195 } // end UDFIsBlockAllocated()
1196
1197 #ifdef _X86_
1198
1199 #pragma warning(disable:4035) // re-enable below
1200
1201 __declspec (naked)
1202 BOOLEAN
1203 __fastcall
1204 UDFGetBit__(
1205 IN uint32* arr, // ECX
1206 IN uint32 bit // EDX
1207 )
1208 {
1209 // CheckAddr(arr);
1210 // ASSERT(bit < 300000);
1211 #ifdef _MSC_VER
1212 __asm {
1213 push ebx
1214 push ecx
1215 // mov eax,bit
1216 mov eax,edx
1217 shr eax,3
1218 and al,0fch
1219 add eax,ecx // eax+arr
1220 mov eax,[eax]
1221 mov cl,dl
1222 ror eax,cl
1223 and eax,1
1224
1225 pop ecx
1226 pop ebx
1227 ret
1228 }
1229 #else
1230 /* FIXME ReactOS */
1231 return ((BOOLEAN)(((((uint32*)(arr))[(bit)>>5]) >> ((bit)&31)) &1));
1232 #endif
1233 } // end UDFGetBit__()
1234
1235 __declspec (naked)
1236 void
1237 __fastcall
1238 UDFSetBit__(
1239 IN uint32* arr, // ECX
1240 IN uint32 bit // EDX
1241 )
1242 {
1243 // CheckAddr(arr);
1244 // ASSERT(bit < 300000);
1245 #ifdef _MSC_VER
1246 __asm {
1247 push eax
1248 push ebx
1249 push ecx
1250 // mov eax,bit
1251 mov eax,edx
1252 shr eax,3
1253 and al,0fch
1254 add eax,ecx // eax+arr
1255 mov ebx,1
1256 mov cl,dl
1257 rol ebx,cl
1258 or [eax],ebx
1259
1260 pop ecx
1261 pop ebx
1262 pop eax
1263 ret
1264 }
1265 #else
1266 /* FIXME ReactOS */
1267 (((uint32*)(arr))[(bit)>>5]) |= (((uint32)1) << ((bit)&31));
1268 #endif
1269 } // end UDFSetBit__()
1270
1271 void
1272 UDFSetBits__(
1273 IN uint32* arr,
1274 IN uint32 bit,
1275 IN uint32 bc
1276 )
1277 {
1278 #ifdef _MSC_VER
1279 __asm {
1280 push eax
1281 push ebx
1282 push ecx
1283 push edx
1284 push esi
1285
1286 mov edx,bc
1287 or edx,edx
1288 jz short EO_sb_loop
1289
1290 mov ecx,bit
1291 mov esi,arr
1292
1293 mov ebx,1
1294 rol ebx,cl
1295
1296 mov eax,ecx
1297 shr eax,3
1298 and al,0fch
1299
1300 test cl, 0x1f
1301 jnz short sb_loop_cont
1302 sb_loop_2:
1303 cmp edx,0x20
1304 jb short sb_loop_cont
1305
1306 mov [dword ptr esi+eax],0xffffffff
1307 sub edx,0x20
1308 jz short EO_sb_loop
1309 add eax,4
1310 add ecx,0x20
1311 jmp short sb_loop_2
1312
1313 sb_loop_cont:
1314 or [esi+eax],ebx
1315
1316 rol ebx,1
1317 inc ecx
1318 dec edx
1319 jz short EO_sb_loop
1320
1321 test cl, 0x1f
1322 jnz short sb_loop_cont
1323 add eax,4
1324 jmp short sb_loop_2
1325 EO_sb_loop:
1326 pop esi
1327 pop edx
1328 pop ecx
1329 pop ebx
1330 pop eax
1331 }
1332 #else
1333 /* FIXME ReactOS */
1334 uint32 j;
1335 for(j=0;j<bc;j++) {
1336 UDFSetBit(arr, bit+j);
1337 }
1338 #endif
1339 } // end UDFSetBits__()
1340
1341 __declspec (naked)
1342 void
1343 __fastcall
1344 UDFClrBit__(
1345 IN uint32* arr, // ECX
1346 IN uint32 bit // EDX
1347 )
1348 {
1349 // CheckAddr(arr);
1350 // ASSERT(bit < 300000);
1351 #ifdef _MSC_VER
1352 __asm {
1353 push eax
1354 push ebx
1355 push ecx
1356 // mov eax,bit
1357 mov eax,edx
1358 shr eax,3
1359 and al,0fch
1360 add eax,ecx // eax+arr
1361 mov ebx,0fffffffeh
1362 mov cl,dl
1363 rol ebx,cl
1364 and [eax],ebx
1365
1366 pop ecx
1367 pop ebx
1368 pop eax
1369 ret
1370 }
1371 #else
1372 /* FIXME ReactOS */
1373 (((uint32*)(arr))[(bit)>>5]) &= (~(((uint32)1) << ((bit)&31)));
1374 #endif
1375 } // end UDFClrBit__()
1376
1377 void
1378 UDFClrBits__(
1379 IN uint32* arr,
1380 IN uint32 bit,
1381 IN uint32 bc
1382 )
1383 {
1384 #ifdef _MSC_VER
1385 __asm {
1386 push eax
1387 push ebx
1388 push ecx
1389 push edx
1390 push esi
1391
1392 mov edx,bc
1393 or edx,edx
1394 jz short EO_cp_loop
1395
1396 mov ecx,bit
1397 mov esi,arr
1398
1399 mov ebx,0xfffffffe
1400 rol ebx,cl
1401
1402 mov eax,ecx
1403 shr eax,3
1404 and al,0fch
1405
1406 test cl, 0x1f
1407 jnz short cp_loop_cont
1408 cp_loop_2:
1409 cmp edx,0x20
1410 jb short cp_loop_cont
1411
1412 mov [dword ptr esi+eax],0x00000000
1413 sub edx,0x20
1414 jz short EO_cp_loop
1415 add eax,4
1416 add ecx,0x20
1417 jmp short cp_loop_2
1418
1419 cp_loop_cont:
1420 and [esi+eax],ebx
1421
1422 rol ebx,1
1423 inc ecx
1424 dec edx
1425 jz short EO_cp_loop
1426
1427 test cl, 0x1f
1428 jnz short cp_loop_cont
1429 add eax,4
1430 jmp short cp_loop_2
1431 EO_cp_loop:
1432 pop esi
1433 pop edx
1434 pop ecx
1435 pop ebx
1436 pop eax
1437 }
1438 #else
1439 /* FIXME ReactOS */
1440 uint32 j;
1441 for(j=0;j<bc;j++) {
1442 UDFClrBit(arr, bit+j);
1443 }
1444 #endif
1445 } // end UDFClrBits__()
1446
1447 #pragma warning(default:4035)
1448 #endif // _X86_