summaryrefslogtreecommitdiffstats
path: root/UefiPayloadPkg/Library/SpiFlashLib/PchSpi.c
blob: 1dafce19cbd95e604d8303190531693a3066a9f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/** @file

  Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent

**/
#include "SpiCommon.h"

/**
  Acquire SPI MMIO BAR.

  @param[in] PchSpiBase           PCH SPI PCI Base Address

  @retval                         Return SPI BAR Address

**/
UINT32
AcquireSpiBar0 (
  IN  UINTN         PchSpiBase
  )
{
  return MmioRead32 (PchSpiBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);
}

/**
  Release SPI MMIO BAR. Do nothing.

  @param[in] PchSpiBase           PCH SPI PCI Base Address

**/
VOID
ReleaseSpiBar0 (
  IN  UINTN         PchSpiBase
  )
{
}



/**
  This function is to enable/disable BIOS Write Protect in SMM phase.

  @param[in] EnableSmmSts        Flag to Enable/disable Bios write protect

**/
VOID
CpuSmmDisableBiosWriteProtect (
   IN  BOOLEAN   EnableSmmSts
  )
{
  UINT32      Data32;

  if(EnableSmmSts){
    //
    // Disable BIOS Write Protect in SMM phase.
    //
    Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0);
    AsmWriteMsr32 (0x000001FE, Data32);
  } else {
    //
    // Enable BIOS Write Protect in SMM phase
    //
    Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0);
    AsmWriteMsr32 (0x000001FE, Data32);
  }

  //
  // Read FED30880h back to ensure the setting went through.
  //
  Data32 = MmioRead32 (0xFED30880);
}


/**
  This function is a hook for Spi to disable BIOS Write Protect.

  @param[in] PchSpiBase           PCH SPI PCI Base Address
  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not

  @retval EFI_SUCCESS             The protocol instance was properly initialized
  @retval EFI_ACCESS_DENIED       The BIOS Region can only be updated in SMM phase

**/
EFI_STATUS
EFIAPI
DisableBiosWriteProtect (
  IN  UINTN         PchSpiBase,
  IN  UINT8         CpuSmmBwp
  )
{

  //
  // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
  //
  MmioOr8 (PchSpiBase + R_SPI_BCR + 1, (B_SPI_BCR_SYNC_SS >> 8));

  //
  // Enable the access to the BIOS space for both read and write cycles
  //
  MmioOr8 (PchSpiBase + R_SPI_BCR, B_SPI_BCR_BIOSWE);

  if (CpuSmmBwp != 0) {
    CpuSmmDisableBiosWriteProtect (TRUE);
  }

  return EFI_SUCCESS;
}

/**
  This function is a hook for Spi to enable BIOS Write Protect.

  @param[in] PchSpiBase           PCH SPI PCI Base Address
  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not

**/
VOID
EFIAPI
EnableBiosWriteProtect (
  IN  UINTN         PchSpiBase,
  IN  UINT8         CpuSmmBwp
  )
{

  //
  // Disable the access to the BIOS space for write cycles
  //
  MmioAnd8 (PchSpiBase + R_SPI_BCR, (UINT8) (~B_SPI_BCR_BIOSWE));

  if (CpuSmmBwp != 0) {
    CpuSmmDisableBiosWriteProtect (FALSE);
  }
}

/**
  This function disables SPI Prefetching and caching,
  and returns previous BIOS Control Register value before disabling.

  @param[in] PchSpiBase           PCH SPI PCI Base Address

  @retval                         Previous BIOS Control Register value

**/
UINT8
SaveAndDisableSpiPrefetchCache (
  IN  UINTN         PchSpiBase
  )
{
  UINT8           BiosCtlSave;

  BiosCtlSave = MmioRead8 (PchSpiBase + R_SPI_BCR) & B_SPI_BCR_SRC;

  MmioAndThenOr32 (PchSpiBase + R_SPI_BCR, \
    (UINT32) (~B_SPI_BCR_SRC), \
    (UINT32) (V_SPI_BCR_SRC_PREF_DIS_CACHE_DIS <<  B_SPI_BCR_SRC));

  return BiosCtlSave;
}

/**
  This function updates BIOS Control Register with the given value.

  @param[in] PchSpiBase           PCH SPI PCI Base Address
  @param[in] BiosCtlValue         BIOS Control Register Value to be updated

**/
VOID
SetSpiBiosControlRegister (
  IN  UINTN         PchSpiBase,
  IN  UINT8         BiosCtlValue
  )
{
  MmioAndThenOr8 (PchSpiBase + R_SPI_BCR, (UINT8) ~B_SPI_BCR_SRC, BiosCtlValue);
}