EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

MdeModulePkg/Library/DxeNetLib/NetBuffer.c

Go to the documentation of this file.
00001 
00014 #include <Uefi.h>
00015 
00016 #include <Library/NetLib.h>
00017 #include <Library/BaseLib.h>
00018 #include <Library/DebugLib.h>
00019 #include <Library/BaseMemoryLib.h>
00020 #include <Library/UefiBootServicesTableLib.h>
00021 #include <Library/MemoryAllocationLib.h>
00022 
00023 
00038 NET_BUF *
00039 NetbufAllocStruct (
00040   IN UINT32                 BlockNum,
00041   IN UINT32                 BlockOpNum
00042   )
00043 {
00044   NET_BUF                   *Nbuf;
00045   NET_VECTOR                *Vector;
00046 
00047   ASSERT (BlockOpNum >= 1);
00048 
00049   //
00050   // Allocate three memory blocks.
00051   //
00052   Nbuf = AllocateZeroPool (NET_BUF_SIZE (BlockOpNum));
00053 
00054   if (Nbuf == NULL) {
00055     return NULL;
00056   }
00057 
00058   Nbuf->Signature           = NET_BUF_SIGNATURE;
00059   Nbuf->RefCnt              = 1;
00060   Nbuf->BlockOpNum          = BlockOpNum;
00061   InitializeListHead (&Nbuf->List);
00062 
00063   if (BlockNum != 0) {
00064     Vector = AllocateZeroPool (NET_VECTOR_SIZE (BlockNum));
00065 
00066     if (Vector == NULL) {
00067       goto FreeNbuf;
00068     }
00069 
00070     Vector->Signature = NET_VECTOR_SIGNATURE;
00071     Vector->RefCnt    = 1;
00072     Vector->BlockNum  = BlockNum;
00073     Nbuf->Vector      = Vector;
00074   }
00075 
00076   return Nbuf;
00077 
00078 FreeNbuf:
00079 
00080   FreePool (Nbuf);
00081   return NULL;
00082 }
00083 
00084 
00095 NET_BUF  *
00096 EFIAPI
00097 NetbufAlloc (
00098   IN UINT32                 Len
00099   )
00100 {
00101   NET_BUF                   *Nbuf;
00102   NET_VECTOR                *Vector;
00103   UINT8                     *Bulk;
00104 
00105   ASSERT (Len > 0);
00106 
00107   Nbuf = NetbufAllocStruct (1, 1);
00108 
00109   if (Nbuf == NULL) {
00110     return NULL;
00111   }
00112 
00113   Bulk = AllocatePool (Len);
00114 
00115   if (Bulk == NULL) {
00116     goto FreeNBuf;
00117   }
00118 
00119   Vector = Nbuf->Vector;
00120   Vector->Len                 = Len;
00121 
00122   Vector->Block[0].Bulk       = Bulk;
00123   Vector->Block[0].Len        = Len;
00124 
00125   Nbuf->BlockOp[0].BlockHead  = Bulk;
00126   Nbuf->BlockOp[0].BlockTail  = Bulk + Len;
00127 
00128   Nbuf->BlockOp[0].Head       = Bulk;
00129   Nbuf->BlockOp[0].Tail       = Bulk;
00130   Nbuf->BlockOp[0].Size       = 0;
00131 
00132   return Nbuf;
00133 
00134 FreeNBuf:
00135   FreePool (Nbuf);
00136   return NULL;
00137 }
00138 
00149 VOID
00150 NetbufFreeVector (
00151   IN NET_VECTOR             *Vector
00152   )
00153 {
00154   UINT32                    Index;
00155 
00156   ASSERT (Vector != NULL);
00157   NET_CHECK_SIGNATURE (Vector, NET_VECTOR_SIGNATURE);
00158   ASSERT (Vector->RefCnt > 0);
00159 
00160   Vector->RefCnt--;
00161 
00162   if (Vector->RefCnt > 0) {
00163     return;
00164   }
00165 
00166   if (Vector->Free != NULL) {
00167     //
00168     // Call external free function to free the vector if it
00169     // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
00170     // first block since it is allocated by us
00171     //
00172     if ((Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {
00173       gBS->FreePool (Vector->Block[0].Bulk);
00174     }
00175 
00176     Vector->Free (Vector->Arg);
00177 
00178   } else {
00179     //
00180     // Free each memory block associated with the Vector
00181     //
00182     for (Index = 0; Index < Vector->BlockNum; Index++) {
00183       gBS->FreePool (Vector->Block[Index].Bulk);
00184     }
00185   }
00186 
00187   FreePool (Vector);
00188 }
00189 
00190 
00203 VOID
00204 EFIAPI
00205 NetbufFree (
00206   IN NET_BUF                *Nbuf
00207   )
00208 {
00209   ASSERT (Nbuf != NULL);
00210   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00211   ASSERT (Nbuf->RefCnt > 0);
00212 
00213   Nbuf->RefCnt--;
00214 
00215   if (Nbuf->RefCnt == 0) {
00216     //
00217     // Update Vector only when NBuf is to be released. That is,
00218     // all the sharing of Nbuf increse Vector's RefCnt by one
00219     //
00220     NetbufFreeVector (Nbuf->Vector);
00221     FreePool (Nbuf);
00222   }
00223 }
00224 
00225 
00238 NET_BUF *
00239 EFIAPI
00240 NetbufClone (
00241   IN NET_BUF                *Nbuf
00242   )
00243 {
00244   NET_BUF                   *Clone;
00245 
00246   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00247 
00248   Clone = AllocatePool (NET_BUF_SIZE (Nbuf->BlockOpNum));
00249 
00250   if (Clone == NULL) {
00251     return NULL;
00252   }
00253 
00254   Clone->Signature  = NET_BUF_SIGNATURE;
00255   Clone->RefCnt     = 1;
00256   InitializeListHead (&Clone->List);
00257 
00258   Clone->Ip   = Nbuf->Ip;
00259   Clone->Tcp  = Nbuf->Tcp;
00260 
00261   CopyMem (Clone->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
00262 
00263   NET_GET_REF (Nbuf->Vector);
00264 
00265   Clone->Vector     = Nbuf->Vector;
00266   Clone->BlockOpNum = Nbuf->BlockOpNum;
00267   Clone->TotalSize  = Nbuf->TotalSize;
00268   CopyMem (Clone->BlockOp, Nbuf->BlockOp, sizeof (NET_BLOCK_OP) * Nbuf->BlockOpNum);
00269 
00270   return Clone;
00271 }
00272 
00273 
00290 NET_BUF  *
00291 EFIAPI
00292 NetbufDuplicate (
00293   IN NET_BUF                *Nbuf,
00294   IN OUT NET_BUF            *Duplicate        OPTIONAL,
00295   IN UINT32                 HeadSpace
00296   )
00297 {
00298   UINT8                     *Dst;
00299 
00300   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00301 
00302   if (Duplicate == NULL) {
00303     Duplicate = NetbufAlloc (Nbuf->TotalSize + HeadSpace);
00304   }
00305 
00306   if (Duplicate == NULL) {
00307     return NULL;
00308   }
00309 
00310   //
00311   // Don't set the IP and TCP head point, since it is most
00312   // like that they are pointing to the memory of Nbuf.
00313   //
00314   CopyMem (Duplicate->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
00315   NetbufReserve (Duplicate, HeadSpace);
00316 
00317   Dst = NetbufAllocSpace (Duplicate, Nbuf->TotalSize, NET_BUF_TAIL);
00318   NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dst);
00319 
00320   return Duplicate;
00321 }
00322 
00323 
00330 VOID
00331 EFIAPI
00332 NetbufFreeList (
00333   IN OUT LIST_ENTRY         *Head
00334   )
00335 {
00336   LIST_ENTRY                *Entry;
00337   LIST_ENTRY                *Next;
00338   NET_BUF                   *Nbuf;
00339 
00340   Entry = Head->ForwardLink;
00341 
00342   NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
00343     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
00344     NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00345 
00346     RemoveEntryList (Entry);
00347     NetbufFree (Nbuf);
00348   }
00349 
00350   ASSERT (IsListEmpty (Head));
00351 }
00352 
00353 
00371 UINT8  *
00372 EFIAPI
00373 NetbufGetByte (
00374   IN  NET_BUF               *Nbuf,
00375   IN  UINT32                Offset,
00376   OUT UINT32                *Index  OPTIONAL
00377   )
00378 {
00379   NET_BLOCK_OP              *BlockOp;
00380   UINT32                    Loop;
00381   UINT32                    Len;
00382 
00383   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00384 
00385   if (Offset >= Nbuf->TotalSize) {
00386     return NULL;
00387   }
00388 
00389   BlockOp = Nbuf->BlockOp;
00390   Len     = 0;
00391 
00392   for (Loop = 0; Loop < Nbuf->BlockOpNum; Loop++) {
00393 
00394     if (Len + BlockOp[Loop].Size <= Offset) {
00395       Len += BlockOp[Loop].Size;
00396       continue;
00397     }
00398 
00399     if (Index != NULL) {
00400       *Index = Loop;
00401     }
00402 
00403     return BlockOp[Loop].Head + (Offset - Len);
00404   }
00405 
00406   return NULL;
00407 }
00408 
00409 
00410 
00426 VOID
00427 NetbufSetBlock (
00428   IN OUT NET_BUF            *Nbuf,
00429   IN UINT8                  *Bulk,
00430   IN UINT32                 Len,
00431   IN UINT32                 Index
00432   )
00433 {
00434   NET_BLOCK_OP              *BlockOp;
00435   NET_BLOCK                 *Block;
00436 
00437   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00438   NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
00439   ASSERT (Index < Nbuf->BlockOpNum);
00440 
00441   Block               = &(Nbuf->Vector->Block[Index]);
00442   BlockOp             = &(Nbuf->BlockOp[Index]);
00443   Block->Len          = Len;
00444   Block->Bulk         = Bulk;
00445   BlockOp->BlockHead  = Bulk;
00446   BlockOp->BlockTail  = Bulk + Len;
00447   BlockOp->Head       = Bulk;
00448   BlockOp->Tail       = Bulk + Len;
00449   BlockOp->Size       = Len;
00450 }
00451 
00452 
00453 
00468 VOID
00469 NetbufSetBlockOp (
00470   IN OUT NET_BUF            *Nbuf,
00471   IN UINT8                  *Bulk,
00472   IN UINT32                 Len,
00473   IN UINT32                 Index
00474   )
00475 {
00476   NET_BLOCK_OP              *BlockOp;
00477 
00478   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00479   ASSERT (Index < Nbuf->BlockOpNum);
00480 
00481   BlockOp             = &(Nbuf->BlockOp[Index]);
00482   BlockOp->BlockHead  = Bulk;
00483   BlockOp->BlockTail  = Bulk + Len;
00484   BlockOp->Head       = Bulk;
00485   BlockOp->Tail       = Bulk + Len;
00486   BlockOp->Size       = Len;
00487 }
00488 
00489 
00499 VOID
00500 EFIAPI
00501 NetbufGetFragmentFree (
00502   IN VOID                   *Arg
00503   )
00504 {
00505   NET_VECTOR                *Vector;
00506 
00507   Vector = (NET_VECTOR *)Arg;
00508   NetbufFreeVector (Vector);
00509 }
00510 
00511 
00529 NET_BUF  *
00530 EFIAPI
00531 NetbufGetFragment (
00532   IN NET_BUF                *Nbuf,
00533   IN UINT32                 Offset,
00534   IN UINT32                 Len,
00535   IN UINT32                 HeadSpace
00536   )
00537 {
00538   NET_BUF                   *Child;
00539   NET_VECTOR                *Vector;
00540   NET_BLOCK_OP              *BlockOp;
00541   UINT32                    CurBlockOp;
00542   UINT32                    BlockOpNum;
00543   UINT8                     *FirstBulk;
00544   UINT32                    Index;
00545   UINT32                    First;
00546   UINT32                    Last;
00547   UINT32                    FirstSkip;
00548   UINT32                    FirstLen;
00549   UINT32                    LastLen;
00550   UINT32                    Cur;
00551 
00552   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00553 
00554   if ((Len == 0) || (Offset + Len > Nbuf->TotalSize)) {
00555     return NULL;
00556   }
00557 
00558   //
00559   // First find the first and last BlockOp that contains
00560   // the valid data, and compute the offset of the first
00561   // BlockOp and length of the last BlockOp
00562   //
00563   BlockOp = Nbuf->BlockOp;
00564   Cur     = 0;
00565 
00566   for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
00567     if (Offset < Cur + BlockOp[Index].Size) {
00568       break;
00569     }
00570 
00571     Cur += BlockOp[Index].Size;
00572   }
00573 
00574   //
00575   // First is the index of the first BlockOp, FirstSkip is
00576   // the offset of the first byte in the first BlockOp.
00577   //
00578   First     = Index;
00579   FirstSkip = Offset - Cur;
00580   FirstLen  = BlockOp[Index].Size - FirstSkip;
00581 
00582   Last      = 0;
00583   LastLen   = 0;
00584 
00585   if (Len > FirstLen) {
00586     Cur += BlockOp[Index].Size;
00587     Index++;
00588 
00589     for (; Index < Nbuf->BlockOpNum; Index++) {
00590       if (Offset + Len <= Cur + BlockOp[Index].Size) {
00591         Last    = Index;
00592         LastLen = Offset + Len - Cur;
00593         break;
00594       }
00595 
00596       Cur += BlockOp[Index].Size;
00597     }
00598 
00599   } else {
00600     Last     = First;
00601     LastLen  = Len;
00602     FirstLen = Len;
00603   }
00604 
00605   ASSERT (Last >= First);
00606   BlockOpNum = Last - First + 1;
00607   CurBlockOp = 0;
00608 
00609   if (HeadSpace != 0) {
00610     //
00611     // Allocate an extra block to accomdate the head space.
00612     //
00613     BlockOpNum++;
00614 
00615     Child = NetbufAllocStruct (1, BlockOpNum);
00616 
00617     if (Child == NULL) {
00618       return NULL;
00619     }
00620 
00621     FirstBulk = AllocatePool (HeadSpace);
00622 
00623     if (FirstBulk == NULL) {
00624       goto FreeChild;
00625     }
00626 
00627     Vector        = Child->Vector;
00628     Vector->Free  = NetbufGetFragmentFree;
00629     Vector->Arg   = Nbuf->Vector;
00630     Vector->Flag  = NET_VECTOR_OWN_FIRST;
00631     Vector->Len   = HeadSpace;
00632 
00633     //
00634     // Reserve the head space in the first block
00635     //
00636     NetbufSetBlock (Child, FirstBulk, HeadSpace, 0);
00637     Child->BlockOp[0].Head += HeadSpace;
00638     Child->BlockOp[0].Size =  0;
00639     CurBlockOp++;
00640 
00641   } else {
00642     Child = NetbufAllocStruct (0, BlockOpNum);
00643 
00644     if (Child == NULL) {
00645       return NULL;
00646     }
00647 
00648     Child->Vector = Nbuf->Vector;
00649   }
00650 
00651   NET_GET_REF (Nbuf->Vector);
00652   Child->TotalSize = Len;
00653 
00654   //
00655   // Set all the BlockOp up, the first and last one are special
00656   // and need special process.
00657   //
00658   NetbufSetBlockOp (
00659     Child,
00660     Nbuf->BlockOp[First].Head + FirstSkip,
00661     FirstLen,
00662     CurBlockOp++
00663     );
00664 
00665   for (Index = First + 1; Index < Last; Index++) {
00666     NetbufSetBlockOp (
00667       Child,
00668       BlockOp[Index].Head,
00669       BlockOp[Index].Size,
00670       CurBlockOp++
00671       );
00672   }
00673 
00674   if (First != Last) {
00675     NetbufSetBlockOp (
00676       Child,
00677       BlockOp[Last].Head,
00678       LastLen,
00679       CurBlockOp
00680       );
00681   }
00682 
00683   CopyMem (Child->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);
00684   return Child;
00685 
00686 FreeChild:
00687 
00688   FreePool (Child);
00689   return NULL;
00690 }
00691 
00692 
00693 
00716 NET_BUF  *
00717 EFIAPI
00718 NetbufFromExt (
00719   IN NET_FRAGMENT           *ExtFragment,
00720   IN UINT32                 ExtNum,
00721   IN UINT32                 HeadSpace,
00722   IN UINT32                 HeadLen,
00723   IN NET_VECTOR_EXT_FREE    ExtFree,
00724   IN VOID                   *Arg          OPTIONAL
00725   )
00726 {
00727   NET_BUF                   *Nbuf;
00728   NET_VECTOR                *Vector;
00729   NET_FRAGMENT              SavedFragment;
00730   UINT32                    SavedIndex;
00731   UINT32                    TotalLen;
00732   UINT32                    BlockNum;
00733   UINT8                     *FirstBlock;
00734   UINT32                    FirstBlockLen;
00735   UINT8                     *Header;
00736   UINT32                    CurBlock;
00737   UINT32                    Index;
00738   UINT32                    Len;
00739   UINT32                    Copied;
00740 
00741   ASSERT ((ExtFragment != NULL) && (ExtNum > 0) && (ExtFree != NULL));
00742 
00743   SavedFragment.Bulk = NULL;
00744   SavedFragment.Len  = 0;
00745 
00746   FirstBlockLen  = 0;
00747   FirstBlock     = NULL;
00748   BlockNum       = ExtNum;
00749   Index          = 0;
00750   TotalLen       = 0;
00751   SavedIndex     = 0;
00752   Len            = 0;
00753   Copied         = 0;
00754 
00755   //
00756   // No need to consolidate the header if the first block is
00757   // longer than the header length or there is only one block.
00758   //
00759   if ((ExtFragment[0].Len >= HeadLen) || (ExtNum == 1)) {
00760     HeadLen = 0;
00761   }
00762 
00763   //
00764   // Allocate an extra block if we need to:
00765   //  1. Allocate some header space
00766   //  2. aggreate the packet header
00767   //
00768   if ((HeadSpace != 0) || (HeadLen != 0)) {
00769     FirstBlockLen = HeadLen + HeadSpace;
00770     FirstBlock    = AllocatePool (FirstBlockLen);
00771 
00772     if (FirstBlock == NULL) {
00773       return NULL;
00774     }
00775 
00776     BlockNum++;
00777   }
00778 
00779   //
00780   // Copy the header to the first block, reduce the NET_BLOCK
00781   // to allocate by one for each block that is completely covered
00782   // by the first bulk.
00783   //
00784   if (HeadLen != 0) {
00785     Len    = HeadLen;
00786     Header = FirstBlock + HeadSpace;
00787 
00788     for (Index = 0; Index < ExtNum; Index++) {
00789       if (Len >= ExtFragment[Index].Len) {
00790         CopyMem (Header, ExtFragment[Index].Bulk, ExtFragment[Index].Len);
00791 
00792         Copied    += ExtFragment[Index].Len;
00793         Len       -= ExtFragment[Index].Len;
00794         Header    += ExtFragment[Index].Len;
00795         TotalLen  += ExtFragment[Index].Len;
00796         BlockNum--;
00797 
00798         if (Len == 0) {
00799           //
00800           // Increament the index number to point to the next
00801           // non-empty fragment.
00802           //
00803           Index++;
00804           break;
00805         }
00806 
00807       } else {
00808         CopyMem (Header, ExtFragment[Index].Bulk, Len);
00809 
00810         Copied    += Len;
00811         TotalLen  += Len;
00812 
00813         //
00814         // Adjust the block structure to exclude the data copied,
00815         // So, the left-over block can be processed as other blocks.
00816         // But it must be recovered later. (SavedIndex > 0) always
00817         // holds since we don't aggreate the header if the first block
00818         // is bigger enough that the header is continuous
00819         //
00820         SavedIndex    = Index;
00821         SavedFragment = ExtFragment[Index];
00822         ExtFragment[Index].Bulk += Len;
00823         ExtFragment[Index].Len  -= Len;
00824         break;
00825       }
00826     }
00827   }
00828 
00829   Nbuf = NetbufAllocStruct (BlockNum, BlockNum);
00830 
00831   if (Nbuf == NULL) {
00832     goto FreeFirstBlock;
00833   }
00834 
00835   Vector       = Nbuf->Vector;
00836   Vector->Free = ExtFree;
00837   Vector->Arg  = Arg;
00838   Vector->Flag = ((FirstBlockLen != 0) ? NET_VECTOR_OWN_FIRST : 0);
00839 
00840   //
00841   // Set the first block up which may contain
00842   // some head space and aggregated header
00843   //
00844   CurBlock = 0;
00845 
00846   if (FirstBlockLen != 0) {
00847     NetbufSetBlock (Nbuf, FirstBlock, HeadSpace + Copied, 0);
00848     Nbuf->BlockOp[0].Head += HeadSpace;
00849     Nbuf->BlockOp[0].Size =  Copied;
00850 
00851     CurBlock++;
00852   }
00853 
00854   for (; Index < ExtNum; Index++) {
00855     NetbufSetBlock (Nbuf, ExtFragment[Index].Bulk, ExtFragment[Index].Len, CurBlock);
00856     TotalLen += ExtFragment[Index].Len;
00857     CurBlock++;
00858   }
00859 
00860   Vector->Len     = TotalLen + HeadSpace;
00861   Nbuf->TotalSize = TotalLen;
00862 
00863   if (SavedIndex != 0) {
00864     ExtFragment[SavedIndex] = SavedFragment;
00865   }
00866 
00867   return Nbuf;
00868 
00869 FreeFirstBlock:
00870   if (FirstBlock != NULL) {
00871     FreePool (FirstBlock);
00872   }
00873   return NULL;
00874 }
00875 
00876 
00890 EFI_STATUS
00891 EFIAPI
00892 NetbufBuildExt (
00893   IN NET_BUF                *Nbuf,
00894   IN OUT NET_FRAGMENT       *ExtFragment,
00895   IN OUT UINT32             *ExtNum
00896   )
00897 {
00898   UINT32                    Index;
00899   UINT32                    Current;
00900 
00901   Current = 0;
00902 
00903   for (Index = 0; (Index < Nbuf->BlockOpNum); Index++) {
00904     if (Nbuf->BlockOp[Index].Size == 0) {
00905       continue;
00906     }
00907 
00908     if (Current < *ExtNum) {
00909       ExtFragment[Current].Bulk = Nbuf->BlockOp[Index].Head;
00910       ExtFragment[Current].Len  = Nbuf->BlockOp[Index].Size;
00911       Current++;
00912     } else {
00913       return EFI_BUFFER_TOO_SMALL;
00914     }
00915   }
00916 
00917   *ExtNum = Current;
00918   return EFI_SUCCESS;
00919 }
00920 
00921 
00939 NET_BUF  *
00940 EFIAPI
00941 NetbufFromBufList (
00942   IN LIST_ENTRY             *BufList,
00943   IN UINT32                 HeadSpace,
00944   IN UINT32                 HeaderLen,
00945   IN NET_VECTOR_EXT_FREE    ExtFree,
00946   IN VOID                   *Arg              OPTIONAL
00947   )
00948 {
00949   NET_FRAGMENT              *Fragment;
00950   UINT32                    FragmentNum;
00951   LIST_ENTRY                *Entry;
00952   NET_BUF                   *Nbuf;
00953   UINT32                    Index;
00954   UINT32                    Current;
00955 
00956   //
00957   //Compute how many blocks are there
00958   //
00959   FragmentNum = 0;
00960 
00961   NET_LIST_FOR_EACH (Entry, BufList) {
00962     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
00963     NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00964     FragmentNum += Nbuf->BlockOpNum;
00965   }
00966 
00967   //
00968   //Allocate and copy block points
00969   //
00970   Fragment = AllocatePool (sizeof (NET_FRAGMENT) * FragmentNum);
00971 
00972   if (Fragment == NULL) {
00973     return NULL;
00974   }
00975 
00976   Current = 0;
00977 
00978   NET_LIST_FOR_EACH (Entry, BufList) {
00979     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
00980     NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
00981 
00982     for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
00983       if (Nbuf->BlockOp[Index].Size != 0) {
00984         Fragment[Current].Bulk = Nbuf->BlockOp[Index].Head;
00985         Fragment[Current].Len  = Nbuf->BlockOp[Index].Size;
00986         Current++;
00987       }
00988     }
00989   }
00990 
00991   Nbuf = NetbufFromExt (Fragment, Current, HeadSpace, HeaderLen, ExtFree, Arg);
00992   FreePool (Fragment);
00993 
00994   return Nbuf;
00995 }
00996 
00997 
01010 VOID
01011 EFIAPI
01012 NetbufReserve (
01013   IN OUT NET_BUF            *Nbuf,
01014   IN UINT32                 Len
01015   )
01016 {
01017   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01018   NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
01019 
01020   ASSERT ((Nbuf->BlockOpNum == 1) && (Nbuf->TotalSize == 0));
01021   ASSERT ((Nbuf->Vector->Free == NULL) && (Nbuf->Vector->Len >= Len));
01022 
01023   Nbuf->BlockOp[0].Head += Len;
01024   Nbuf->BlockOp[0].Tail += Len;
01025 
01026   ASSERT (Nbuf->BlockOp[0].Tail <= Nbuf->BlockOp[0].BlockTail);
01027 }
01028 
01029 
01042 UINT8*
01043 EFIAPI
01044 NetbufAllocSpace (
01045   IN OUT NET_BUF            *Nbuf,
01046   IN UINT32                 Len,
01047   IN BOOLEAN                FromHead
01048   )
01049 {
01050   NET_BLOCK_OP              *BlockOp;
01051   UINT32                    Index;
01052   UINT8                     *SavedTail;
01053 
01054   Index = 0;
01055 
01056   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01057   NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
01058 
01059   ASSERT (Len > 0);
01060 
01061   if (FromHead) {
01062     //
01063     // Allocate some space from head. If the buffer is empty,
01064     // allocate from the first block. If it isn't, allocate
01065     // from the first non-empty block, or the block before that.
01066     //
01067     if (Nbuf->TotalSize == 0) {
01068       Index = 0;
01069     } else {
01070       NetbufGetByte (Nbuf, 0, &Index);
01071 
01072       if ((NET_HEADSPACE(&(Nbuf->BlockOp[Index])) < Len) && (Index > 0)) {
01073         Index--;
01074       }
01075     }
01076 
01077     BlockOp = &(Nbuf->BlockOp[Index]);
01078 
01079     if (NET_HEADSPACE (BlockOp) < Len) {
01080       return NULL;
01081     }
01082 
01083     BlockOp->Head   -= Len;
01084     BlockOp->Size   += Len;
01085     Nbuf->TotalSize += Len;
01086 
01087     return BlockOp->Head;
01088 
01089   } else {
01090     //
01091     // Allocate some space from the tail. If the buffer is empty,
01092     // allocate from the first block. If it isn't, allocate
01093     // from the last non-empty block, or the block after that.
01094     //
01095     if (Nbuf->TotalSize == 0) {
01096       Index = 0;
01097     } else {
01098       NetbufGetByte (Nbuf, Nbuf->TotalSize - 1, &Index);
01099 
01100       if ((NET_TAILSPACE(&(Nbuf->BlockOp[Index])) < Len) &&
01101           (Index < Nbuf->BlockOpNum - 1)) {
01102 
01103         Index++;
01104       }
01105     }
01106 
01107     BlockOp = &(Nbuf->BlockOp[Index]);
01108 
01109     if (NET_TAILSPACE (BlockOp) < Len) {
01110       return NULL;
01111     }
01112 
01113     SavedTail       = BlockOp->Tail;
01114 
01115     BlockOp->Tail   += Len;
01116     BlockOp->Size   += Len;
01117     Nbuf->TotalSize += Len;
01118 
01119     return SavedTail;
01120   }
01121 }
01122 
01123 
01133 VOID
01134 NetblockTrim (
01135   IN OUT NET_BLOCK_OP       *BlockOp,
01136   IN UINT32                 Len,
01137   IN BOOLEAN                FromHead
01138   )
01139 {
01140   ASSERT ((BlockOp != NULL) && (BlockOp->Size >= Len));
01141 
01142   BlockOp->Size -= Len;
01143 
01144   if (FromHead) {
01145     BlockOp->Head += Len;
01146   } else {
01147     BlockOp->Tail -= Len;
01148   }
01149 }
01150 
01151 
01164 UINT32
01165 EFIAPI
01166 NetbufTrim (
01167   IN OUT NET_BUF            *Nbuf,
01168   IN UINT32                 Len,
01169   IN BOOLEAN                FromHead
01170   )
01171 {
01172   NET_BLOCK_OP              *BlockOp;
01173   UINT32                    Index;
01174   UINT32                    Trimmed;
01175 
01176   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01177 
01178   if (Len > Nbuf->TotalSize) {
01179     Len = Nbuf->TotalSize;
01180   }
01181 
01182   //
01183   // If FromTail is true, iterate backward. That
01184   // is, init Index to NBuf->BlockNum - 1, and
01185   // decrease it by 1 during each loop. Otherwise,
01186   // iterate forward. That is, init Index to 0, and
01187   // increase it by 1 during each loop.
01188   //
01189   Trimmed          = 0;
01190   Nbuf->TotalSize -= Len;
01191 
01192   Index   = (FromHead ? 0 : Nbuf->BlockOpNum - 1);
01193   BlockOp = Nbuf->BlockOp;
01194 
01195   for (;;) {
01196     if (BlockOp[Index].Size == 0) {
01197       Index += (FromHead ? 1 : -1);
01198       continue;
01199     }
01200 
01201     if (Len > BlockOp[Index].Size) {
01202       Len     -= BlockOp[Index].Size;
01203       Trimmed += BlockOp[Index].Size;
01204       NetblockTrim (&BlockOp[Index], BlockOp[Index].Size, FromHead);
01205     } else {
01206       Trimmed += Len;
01207       NetblockTrim (&BlockOp[Index], Len, FromHead);
01208       break;
01209     }
01210 
01211     Index += (FromHead ? 1 : -1);
01212   }
01213 
01214   return Trimmed;
01215 }
01216 
01217 
01233 UINT32
01234 EFIAPI
01235 NetbufCopy (
01236   IN NET_BUF                *Nbuf,
01237   IN UINT32                 Offset,
01238   IN UINT32                 Len,
01239   IN UINT8                  *Dest
01240   )
01241 {
01242   NET_BLOCK_OP              *BlockOp;
01243   UINT32                    Skip;
01244   UINT32                    Left;
01245   UINT32                    Copied;
01246   UINT32                    Index;
01247   UINT32                    Cur;
01248 
01249   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01250   ASSERT (Dest);
01251 
01252   if ((Len == 0) || (Nbuf->TotalSize <= Offset)) {
01253     return 0;
01254   }
01255 
01256   if (Nbuf->TotalSize - Offset < Len) {
01257     Len = Nbuf->TotalSize - Offset;
01258   }
01259 
01260   BlockOp = Nbuf->BlockOp;
01261 
01262   //
01263   // Skip to the offset. Don't make "Offset-By-One" error here.
01264   // Cur + BLOCK.SIZE is the first sequence number of next block.
01265   // So, (Offset < Cur + BLOCK.SIZE) means that the  first byte
01266   // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
01267   // first byte is the next block's first byte.
01268   //
01269   Cur = 0;
01270 
01271   for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
01272     if (BlockOp[Index].Size == 0) {
01273       continue;
01274     }
01275 
01276     if (Offset < Cur + BlockOp[Index].Size) {
01277       break;
01278     }
01279 
01280     Cur += BlockOp[Index].Size;
01281   }
01282 
01283   //
01284   // Cur is the sequence number of the first byte in the block
01285   // Offset - Cur is the number of bytes before first byte to
01286   // to copy in the current block.
01287   //
01288   Skip  = Offset - Cur;
01289   Left  = BlockOp[Index].Size - Skip;
01290 
01291   if (Len <= Left) {
01292     CopyMem (Dest, BlockOp[Index].Head + Skip, Len);
01293     return Len;
01294   }
01295 
01296   CopyMem (Dest, BlockOp[Index].Head + Skip, Left);
01297 
01298   Dest  += Left;
01299   Len   -= Left;
01300   Copied = Left;
01301 
01302   Index++;
01303 
01304   for (; Index < Nbuf->BlockOpNum; Index++) {
01305     if (Len > BlockOp[Index].Size) {
01306       Len    -= BlockOp[Index].Size;
01307       Copied += BlockOp[Index].Size;
01308 
01309       CopyMem (Dest, BlockOp[Index].Head, BlockOp[Index].Size);
01310       Dest   += BlockOp[Index].Size;
01311     } else {
01312       Copied += Len;
01313       CopyMem (Dest, BlockOp[Index].Head, Len);
01314       break;
01315     }
01316   }
01317 
01318   return Copied;
01319 }
01320 
01321 
01328 VOID
01329 EFIAPI
01330 NetbufQueInit (
01331   IN OUT NET_BUF_QUEUE          *NbufQue
01332   )
01333 {
01334   NbufQue->Signature  = NET_QUE_SIGNATURE;
01335   NbufQue->RefCnt     = 1;
01336   InitializeListHead (&NbufQue->List);
01337 
01338   InitializeListHead (&NbufQue->BufList);
01339   NbufQue->BufSize  = 0;
01340   NbufQue->BufNum   = 0;
01341 }
01342 
01343 
01351 NET_BUF_QUEUE  *
01352 EFIAPI
01353 NetbufQueAlloc (
01354   VOID
01355   )
01356 {
01357   NET_BUF_QUEUE             *NbufQue;
01358 
01359   NbufQue = AllocatePool (sizeof (NET_BUF_QUEUE));
01360   if (NbufQue == NULL) {
01361     return NULL;
01362   }
01363 
01364   NetbufQueInit (NbufQue);
01365 
01366   return NbufQue;
01367 }
01368 
01369 
01380 VOID
01381 EFIAPI
01382 NetbufQueFree (
01383   IN NET_BUF_QUEUE          *NbufQue
01384   )
01385 {
01386   ASSERT (NbufQue != NULL);
01387   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01388 
01389   NbufQue->RefCnt--;
01390 
01391   if (NbufQue->RefCnt == 0) {
01392     NetbufQueFlush (NbufQue);
01393     FreePool (NbufQue);
01394   }
01395 }
01396 
01397 
01405 VOID
01406 EFIAPI
01407 NetbufQueAppend (
01408   IN OUT NET_BUF_QUEUE          *NbufQue,
01409   IN OUT NET_BUF                *Nbuf
01410   )
01411 {
01412   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01413   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01414 
01415   InsertTailList (&NbufQue->BufList, &Nbuf->List);
01416 
01417   NbufQue->BufSize += Nbuf->TotalSize;
01418   NbufQue->BufNum++;
01419 }
01420 
01421 
01431 NET_BUF  *
01432 EFIAPI
01433 NetbufQueRemove (
01434   IN OUT NET_BUF_QUEUE          *NbufQue
01435   )
01436 {
01437   NET_BUF                   *First;
01438 
01439   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01440 
01441   if (NbufQue->BufNum == 0) {
01442     return NULL;
01443   }
01444 
01445   First = NET_LIST_USER_STRUCT (NbufQue->BufList.ForwardLink, NET_BUF, List);
01446 
01447   NetListRemoveHead (&NbufQue->BufList);
01448 
01449   NbufQue->BufSize -= First->TotalSize;
01450   NbufQue->BufNum--;
01451   return First;
01452 }
01453 
01454 
01471 UINT32
01472 EFIAPI
01473 NetbufQueCopy (
01474   IN NET_BUF_QUEUE          *NbufQue,
01475   IN UINT32                 Offset,
01476   IN UINT32                 Len,
01477   OUT UINT8                 *Dest
01478   )
01479 {
01480   LIST_ENTRY                *Entry;
01481   NET_BUF                   *Nbuf;
01482   UINT32                    Skip;
01483   UINT32                    Left;
01484   UINT32                    Cur;
01485   UINT32                    Copied;
01486 
01487   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01488   ASSERT (Dest != NULL);
01489 
01490   if ((Len == 0) || (NbufQue->BufSize <= Offset)) {
01491     return 0;
01492   }
01493 
01494   if (NbufQue->BufSize - Offset < Len) {
01495     Len = NbufQue->BufSize - Offset;
01496   }
01497 
01498   //
01499   // skip to the Offset
01500   //
01501   Cur   = 0;
01502   Nbuf  = NULL;
01503 
01504   NET_LIST_FOR_EACH (Entry, &NbufQue->BufList) {
01505     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
01506 
01507     if (Offset < Cur + Nbuf->TotalSize) {
01508       break;
01509     }
01510 
01511     Cur += Nbuf->TotalSize;
01512   }
01513 
01514   ASSERT (Nbuf != NULL);
01515 
01516   //
01517   // Copy the data in the first buffer.
01518   //
01519   Skip  = Offset - Cur;
01520   Left  = Nbuf->TotalSize - Skip;
01521 
01522   if (Len < Left) {
01523     return NetbufCopy (Nbuf, Skip, Len, Dest);
01524   }
01525 
01526   NetbufCopy (Nbuf, Skip, Left, Dest);
01527   Dest  += Left;
01528   Len   -= Left;
01529   Copied = Left;
01530 
01531   //
01532   // Iterate over the others
01533   //
01534   Entry = Entry->ForwardLink;
01535 
01536   while ((Len > 0) && (Entry != &NbufQue->BufList)) {
01537     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
01538 
01539     if (Len > Nbuf->TotalSize) {
01540       Len -= Nbuf->TotalSize;
01541       Copied += Nbuf->TotalSize;
01542 
01543       NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dest);
01544       Dest += Nbuf->TotalSize;
01545 
01546     } else {
01547       NetbufCopy (Nbuf, 0, Len, Dest);
01548       Copied += Len;
01549       break;
01550     }
01551 
01552     Entry = Entry->ForwardLink;
01553   }
01554 
01555   return Copied;
01556 }
01557 
01558 
01572 UINT32
01573 EFIAPI
01574 NetbufQueTrim (
01575   IN OUT NET_BUF_QUEUE      *NbufQue,
01576   IN UINT32                 Len
01577   )
01578 {
01579   LIST_ENTRY                *Entry;
01580   LIST_ENTRY                *Next;
01581   NET_BUF                   *Nbuf;
01582   UINT32                    Trimmed;
01583 
01584   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01585 
01586   if (Len == 0) {
01587     return 0;
01588   }
01589 
01590   if (Len > NbufQue->BufSize) {
01591     Len = NbufQue->BufSize;
01592   }
01593 
01594   NbufQue->BufSize -= Len;
01595   Trimmed = 0;
01596 
01597   NET_LIST_FOR_EACH_SAFE (Entry, Next, &NbufQue->BufList) {
01598     Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
01599 
01600     if (Len >= Nbuf->TotalSize) {
01601       Trimmed += Nbuf->TotalSize;
01602       Len -= Nbuf->TotalSize;
01603 
01604       RemoveEntryList (Entry);
01605       NetbufFree (Nbuf);
01606 
01607       NbufQue->BufNum--;
01608 
01609       if (Len == 0) {
01610         break;
01611       }
01612 
01613     } else {
01614       Trimmed += NetbufTrim (Nbuf, Len, NET_BUF_HEAD);
01615       break;
01616     }
01617   }
01618 
01619   return Trimmed;
01620 }
01621 
01622 
01629 VOID
01630 EFIAPI
01631 NetbufQueFlush (
01632   IN OUT NET_BUF_QUEUE          *NbufQue
01633   )
01634 {
01635   NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);
01636 
01637   NetbufFreeList (&NbufQue->BufList);
01638 
01639   NbufQue->BufNum   = 0;
01640   NbufQue->BufSize  = 0;
01641 }
01642 
01643 
01653 UINT16
01654 EFIAPI
01655 NetblockChecksum (
01656   IN UINT8                  *Bulk,
01657   IN UINT32                 Len
01658   )
01659 {
01660   register UINT32           Sum;
01661 
01662   Sum = 0;
01663 
01664   while (Len > 1) {
01665     Sum += *(UINT16 *) Bulk;
01666     Bulk += 2;
01667     Len -= 2;
01668   }
01669 
01670   //
01671   // Add left-over byte, if any
01672   //
01673   if (Len > 0) {
01674     Sum += *(UINT8 *) Bulk;
01675   }
01676 
01677   //
01678   // Fold 32-bit sum to 16 bits
01679   //
01680   while ((Sum >> 16) != 0) {
01681     Sum = (Sum & 0xffff) + (Sum >> 16);
01682 
01683   }
01684 
01685   return (UINT16) Sum;
01686 }
01687 
01688 
01698 UINT16
01699 EFIAPI
01700 NetAddChecksum (
01701   IN UINT16                 Checksum1,
01702   IN UINT16                 Checksum2
01703   )
01704 {
01705   UINT32                    Sum;
01706 
01707   Sum = Checksum1 + Checksum2;
01708 
01709   //
01710   // two UINT16 can only add up to a carry of 1.
01711   //
01712   if ((Sum >> 16) != 0) {
01713     Sum = (Sum & 0xffff) + 1;
01714 
01715   }
01716 
01717   return (UINT16) Sum;
01718 }
01719 
01720 
01729 UINT16
01730 EFIAPI
01731 NetbufChecksum (
01732   IN NET_BUF                *Nbuf
01733   )
01734 {
01735   NET_BLOCK_OP              *BlockOp;
01736   UINT32                    Offset;
01737   UINT16                    TotalSum;
01738   UINT16                    BlockSum;
01739   UINT32                    Index;
01740 
01741   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01742 
01743   TotalSum  = 0;
01744   Offset    = 0;
01745   BlockOp   = Nbuf->BlockOp;
01746 
01747   for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {
01748     if (BlockOp[Index].Size == 0) {
01749       continue;
01750     }
01751 
01752     BlockSum = NetblockChecksum (BlockOp[Index].Head, BlockOp[Index].Size);
01753 
01754     if ((Offset & 0x01) != 0) {
01755       //
01756       // The checksum starts with an odd byte, swap
01757       // the checksum before added to total checksum
01758       //
01759       BlockSum = SwapBytes16 (BlockSum);
01760     }
01761 
01762     TotalSum = NetAddChecksum (BlockSum, TotalSum);
01763     Offset  += BlockOp[Index].Size;
01764   }
01765 
01766   return TotalSum;
01767 }
01768 
01769 
01783 UINT16
01784 EFIAPI
01785 NetPseudoHeadChecksum (
01786   IN IP4_ADDR               Src,
01787   IN IP4_ADDR               Dst,
01788   IN UINT8                  Proto,
01789   IN UINT16                 Len
01790   )
01791 {
01792   NET_PSEUDO_HDR            Hdr;
01793 
01794   //
01795   // Zero the memory to relieve align problems
01796   //
01797   ZeroMem (&Hdr, sizeof (Hdr));
01798 
01799   Hdr.SrcIp     = Src;
01800   Hdr.DstIp     = Dst;
01801   Hdr.Protocol  = Proto;
01802   Hdr.Len       = HTONS (Len);
01803 
01804   return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));
01805 }
01806 
01820 UINT16
01821 EFIAPI
01822 NetIp6PseudoHeadChecksum (
01823   IN EFI_IPv6_ADDRESS       *Src,
01824   IN EFI_IPv6_ADDRESS       *Dst,
01825   IN UINT8                  NextHeader,
01826   IN UINT32                 Len
01827   )
01828 {
01829   NET_IP6_PSEUDO_HDR        Hdr;
01830 
01831   //
01832   // Zero the memory to relieve align problems
01833   //
01834   ZeroMem (&Hdr, sizeof (Hdr));
01835 
01836   IP6_COPY_ADDRESS (&Hdr.SrcIp, Src);
01837   IP6_COPY_ADDRESS (&Hdr.DstIp, Dst);
01838 
01839   Hdr.NextHeader = NextHeader;
01840   Hdr.Len        = HTONL (Len);
01841 
01842   return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));
01843 }
01844 
01856 VOID
01857 NetIpSecNetbufFree (
01858   NET_BUF   *Nbuf
01859   )
01860 {
01861   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
01862   ASSERT (Nbuf->RefCnt > 0);
01863 
01864   Nbuf->RefCnt--;
01865 
01866   if (Nbuf->RefCnt == 0) {
01867     
01868     //
01869     // Update Vector only when NBuf is to be released. That is,
01870     // all the sharing of Nbuf increse Vector's RefCnt by one
01871     //
01872     NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);
01873     ASSERT (Nbuf->Vector->RefCnt > 0);
01874 
01875     Nbuf->Vector->RefCnt--;
01876 
01877     if (Nbuf->Vector->RefCnt > 0) {
01878       return;
01879     }
01880 
01881     //
01882     // If NET_VECTOR_OWN_FIRST is set, release the first block since it is 
01883     // allocated by us
01884     //
01885     if ((Nbuf->Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {
01886       FreePool (Nbuf->Vector->Block[0].Bulk);
01887     }
01888     FreePool (Nbuf->Vector);
01889     FreePool (Nbuf); 
01890   } 
01891 }
01892 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines