public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Eric Dong <eric.dong@intel.com>
To: edk2-devel@lists.01.org
Cc: Jiewen Yao <jiewen.yao@intel.com>, Feng Tian <feng.tian@intel.com>
Subject: [Patch 09/10] SecurityPkg OpalPasswordDxe: Use PP actions to enable BlockSID.
Date: Wed, 16 Nov 2016 14:00:48 +0800	[thread overview]
Message-ID: <1479276049-34308-10-git-send-email-eric.dong@intel.com> (raw)
In-Reply-To: <1479276049-34308-1-git-send-email-eric.dong@intel.com>

Update the implementation, use physical presence defined actions to
update the BlockSid related status.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eric Dong <eric.dong@intel.com>
---
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c  |  25 +---
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h  |   4 +-
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c     | 143 ++++++++++++++++-----
 .../Opal/OpalPasswordDxe/OpalHiiFormStrings.uni    |  20 ++-
 .../Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h      |   6 +-
 .../Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf   |   1 +
 .../Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr  |  25 +++-
 7 files changed, 164 insertions(+), 60 deletions(-)

diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
index 9bf1ced..718d49e 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
@@ -416,28 +416,15 @@ ReadyToBootCallback (
   IN VOID             *Context
   )
 {
-  EFI_STATUS          Status;
-  OPAL_DRIVER_DEVICE* Itr;
-  TCG_RESULT          Result;
-  OPAL_EXTRA_INFO_VAR OpalExtraInfo;
-  UINTN               DataSize;
-  OPAL_SESSION        Session;
+  OPAL_DRIVER_DEVICE                         *Itr;
+  TCG_RESULT                                 Result;
+  OPAL_SESSION                               Session;
+  UINT32                                     PpStorageFlag;
 
   gBS->CloseEvent (Event);
 
-  DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
-  Status = gRT->GetVariable (
-                  OPAL_EXTRA_INFO_VAR_NAME,
-                  &gOpalExtraInfoVariableGuid,
-                  NULL,
-                  &DataSize,
-                  &OpalExtraInfo
-                  );
-  if (EFI_ERROR (Status)) {
-    return;
-  }
-
-  if (OpalExtraInfo.EnableBlockSid == TRUE) {
+  PpStorageFlag = TcgPhysicalPresenceStorageLibReturnStorageFlags();
+  if ((PpStorageFlag & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
     //
     // Send BlockSID command to each Opal disk
     //
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
index 213c139..b04d053 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
@@ -16,8 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define _OPAL_DRIVER_H_
 
 #include <PiDxe.h>
-
-#include <Guid/OpalPasswordExtraInfoVariable.h>
+#include <IndustryStandard/TcgPhysicalPresence.h>
 
 #include <Protocol/PciIo.h>
 #include <Protocol/SmmCommunication.h>
@@ -40,6 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiHiiServicesLib.h>
 #include <Library/TcgStorageOpalLib.h>
 #include <Library/OpalPasswordSupportLib.h>
+#include <Library/TcgPhysicalPresenceStorageLib.h>
 
 #define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
 
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
index ee73697..5e3106a 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
@@ -90,23 +90,63 @@ HiiSetCurrentConfiguration(
   VOID
   )
 {
-  EFI_STATUS                            Status;
-  OPAL_EXTRA_INFO_VAR                   OpalExtraInfo;
-  UINTN                                 DataSize;
+  UINT32                                       PpStorageFlag;
+  EFI_STRING                                   NewString;
 
   gHiiConfiguration.NumDisks = GetDeviceCount();
 
-  DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
-  Status = gRT->GetVariable (
-                  OPAL_EXTRA_INFO_VAR_NAME,
-                  &gOpalExtraInfoVariableGuid,
-                  NULL,
-                  &DataSize,
-                  &OpalExtraInfo
-                  );
-  if (!EFI_ERROR (Status)) {
-    gHiiConfiguration.EnableBlockSid = OpalExtraInfo.EnableBlockSid;
+  //
+  // Update the BlockSID status string.
+  //
+  PpStorageFlag = TcgPhysicalPresenceStorageLibReturnStorageFlags();
+
+  if ((PpStorageFlag & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_ENABLED), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISABLED), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL);
+  FreePool (NewString);
+
+  if ((PpStorageFlag & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL);
+  FreePool (NewString);
+
+  if ((PpStorageFlag & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
   }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL);
+  FreePool (NewString);
 }
 
 /**
@@ -400,6 +440,7 @@ DriverCallback(
 {
   HII_KEY    HiiKey;
   UINT8      HiiKeyId;
+  UINT32     PpRequest;
 
   if (ActionRequest != NULL) {
     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
@@ -469,9 +510,47 @@ DriverCallback(
         return EFI_SUCCESS;
 
       case HII_KEY_ID_BLOCKSID:
-        HiiSetBlockSid(Value->b);
+        switch (Value->u8) {
+          case 0:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+            break;
+
+          case 1:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID;
+            break;
+
+          case 2:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID;
+            break;
+
+          case 3:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE;
+            break;
+
+          case 4:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE;
+            break;
+
+          case 5:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE;
+            break;
+
+          case 6:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE;
+            break;
+
+          default:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+            DEBUG ((DEBUG_ERROR, "Invalid value input!\n"));
+            break;
+        }
+        HiiSetBlockSidAction(PpRequest);
+
         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
         return EFI_SUCCESS;
+
+      default:
+        break;
     }
   }
 
@@ -1090,25 +1169,27 @@ HiiPasswordEntered(
 
 **/
 EFI_STATUS
-HiiSetBlockSid (
-  BOOLEAN          Enable
+HiiSetBlockSidAction (
+  IN UINT32          PpRequest
   )
 {
-  EFI_STATUS                            Status;
-  OPAL_EXTRA_INFO_VAR                   OpalExtraInfo;
-  UINTN                                 DataSize;
-
-  Status = EFI_SUCCESS;
-
-  OpalExtraInfo.EnableBlockSid = Enable;
-  DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
-  Status = gRT->SetVariable (
-                 OPAL_EXTRA_INFO_VAR_NAME,
-                 &gOpalExtraInfoVariableGuid,
-                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                 DataSize,
-                 &OpalExtraInfo
-                 );
+  UINT32                           ReturnCode;
+  EFI_STATUS                       Status;
+
+  //
+  // Process TCG Physical Presence request just after trusted console is ready
+  // Platform can connect trusted consoles and then call the below function.
+  //
+  ReturnCode = TcgPhysicalPresenceStorageLibSubmitRequestToPreOSFunction (PpRequest, 0);
+  if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
+    Status = EFI_SUCCESS;
+  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) {
+    Status = EFI_OUT_OF_RESOURCES;
+  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) {
+    Status = EFI_UNSUPPORTED;
+  } else {
+    Status = EFI_DEVICE_ERROR;
+  }
 
   return Status;
 }
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
index 754dbf7..4cfbde3 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
@@ -54,9 +54,21 @@
 #string STR_DISK_INFO_REVERT                     #language en-US "Admin Revert to factory default and Disable"
 #string STR_DISK_INFO_DISABLE_USER               #language en-US "Disable User"
 #string STR_DISK_INFO_ENABLE_FEATURE             #language en-US "Enable Feature"
-#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US "Enable BlockSID"
-#string STR_ENABLED                              #language en-US "Enabled"
-#string STR_DISABLED                             #language en-US "Disabled"
+#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US "TCG Storage Action"
+#string STR_ENABLED                              #language en-US "Enable BlockSID"
+#string STR_DISABLED                             #language en-US "Disable BlockSID"
+
+#string STR_NONE                                 #language en-US "None"
+#string STR_DISK_INFO_ENABLE_BLOCKSID_TRUE       #language en-US "Require physical presence when remote enable BlockSID"
+#string STR_DISK_INFO_ENABLE_BLOCKSID_FALSE      #language en-US "Not require physical presence when remote enable BlockSID"
+#string STR_DISK_INFO_DISABLE_BLOCKSID_TRUE      #language en-US "Require physical presence when remote disable BlockSID"
+#string STR_DISK_INFO_DISABLE_BLOCKSID_FALSE     #language en-US "Not require physical presence when remote disable BlockSID"
+
+#string STR_BLOCKSID_STATUS_HELP                 #language en-US "BlockSID action change status"
+#string STR_BLOCKSID_STATUS                      #language en-US "Current BlockSID Status:"
+#string STR_BLOCKSID_STATUS1                     #language en-US ""
+#string STR_BLOCKSID_STATUS2                     #language en-US ""
+#string STR_BLOCKSID_STATUS3                     #language en-US ""
 
 #string STR_DISK_INFO_GOTO_LOCK_HELP             #language en-US "Lock the disk"
 #string STR_DISK_INFO_GOTO_UNLOCK_HELP           #language en-US "Unlock the disk"
@@ -66,7 +78,7 @@
 #string STR_DISK_INFO_GOTO_PSID_REVERT_HELP      #language en-US "Revert the disk to factory defaults"
 #string STR_DISK_INFO_GOTO_DISABLE_USER_HELP     #language en-US "Disable User"
 #string STR_DISK_INFO_GOTO_ENABLE_FEATURE_HELP   #language en-US "Enable Feature"
-#string STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP  #language en-US "Enable to send BlockSID command"
+#string STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP  #language en-US "Change BlockSID actions, includes enable or disable BlockSID, Require or not require physical presence when remote enable or disable BlockSID"
 
 /////////////////////////////////   DISK ACTION MENU FORM   /////////////////////////////////
 #string STR_DISK_ACTION_LBL                     #language en-US " "
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
index bb086bd..a7709dd 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
@@ -211,15 +211,15 @@ HiiPasswordEntered(
 /**
   Update block sid info.
 
-  @param      Enable         Enable/disable BlockSid.
+  @param      PpRequest      Input the Pp Request.
 
   @retval  EFI_SUCCESS       Do the required action success.
   @retval  Others            Other error occur.
 
 **/
 EFI_STATUS
-HiiSetBlockSid (
-  BOOLEAN          Enable
+HiiSetBlockSidAction (
+  UINT32          PpRequest
   );
 
 /**
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
index 703c1b6..91c4bfc 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
@@ -62,6 +62,7 @@
   OpalPasswordSupportLib
   UefiLib
   TcgStorageOpalLib
+  TcgPhysicalPresenceStorageLib
 
 [Protocols]
   gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
index 88cc2a1..218e0f4 100644
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
@@ -118,15 +118,38 @@ form formid = FORMID_VALUE_MAIN_MENU,
 
     subtitle text = STRING_TOKEN(STR_NULL);
 
+    grayoutif TRUE;
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS1);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS2);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS3);
+      subtitle text = STRING_TOKEN(STR_NULL);
+    endif;
+
     oneof varid   = OpalHiiConfig.EnableBlockSid,
       questionid  = 0x8017, // 32791,
       prompt      = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
       help        = STRING_TOKEN(STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP),
       flags       = INTERACTIVE,
-      option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_NONE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
       option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISABLED), value = 2, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), value = 3, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), value = 4, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), value = 5, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), value = 6, flags = RESET_REQUIRED;
     endoneof;
 
+
+
 endform;  // MAIN MENU FORM
 
 //
-- 
2.6.4.windows.1



  parent reply	other threads:[~2016-11-16  6:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-16  6:00 [Patch 00/10] Enable BlockSid related PP actions Eric Dong
2016-11-16  6:00 ` [Patch 01/10] SecurityPkg: Add definition for Physical Presence storage flag Eric Dong
2016-11-16  6:00 ` [Patch 02/10] SecurityPkg: Add header file for TcgPhysicalPresenceStorageLib Eric Dong
2016-11-16  6:00 ` [Patch 03/10] SecurityPkg: Add DxeTcgPhysicalPresenceStorageLib Eric Dong
2016-11-17  5:49   ` Zhang, Chao B
2016-11-16  6:00 ` [Patch 04/10] SecurityPkg: Add SmmTcgPhysicalPresenceStorageLib Eric Dong
2016-11-16  6:00 ` [Patch 05/10] SecurityPkg DxeTcg2PhysicalPresenceLib: Enable Storage actions Eric Dong
2016-11-16  6:00 ` [Patch 06/10] SecurityPkg DxeTcgPhysicalPresenceLib: " Eric Dong
2016-11-16  6:00 ` [Patch 07/10] SecurityPkg SmmTcg2PhysicalPresenceLib: " Eric Dong
2016-11-17  5:58   ` Zhang, Chao B
2016-11-16  6:00 ` [Patch 08/10] SecurityPkg TcgSmm: " Eric Dong
2016-11-16  6:00 ` Eric Dong [this message]
2016-11-16  6:00 ` [Patch 10/10] SecurityPkg Tcg2Config: Remove the empty options Eric Dong
2016-11-21  3:31 ` [Patch 00/10] Enable BlockSid related PP actions Yao, Jiewen
2016-11-23  8:12   ` Dong, Eric
2016-11-23  8:14     ` Yao, Jiewen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1479276049-34308-10-git-send-email-eric.dong@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox