action.yml 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. name: 'Apply Device-Specific Patches'
  2. description: 'Apply WiFi/Bluetooth fixes for Samsung and Xiaomi 6.6 GKI devices'
  3. inputs:
  4. version:
  5. description: 'Kernel config version (e.g., android15-6.6)'
  6. required: true
  7. kernel_version:
  8. description: 'Kernel version (e.g., 6.6)'
  9. required: true
  10. runs:
  11. using: "composite"
  12. steps:
  13. - name: Fix WiFi and Bluetooth on Samsung 6.6 GKI Devices
  14. if: inputs.version == 'android15-6.6'
  15. shell: bash
  16. working-directory: ${{ github.workspace }}/kernel/common
  17. run: |
  18. set -euo pipefail
  19. PATCH="${{ github.workspace }}/kernel_patches/samsung/min_kdp/add-min_kdp-symbols.patch"
  20. MIN_KDP="${{ github.workspace }}/kernel_patches/samsung/min_kdp/min_kdp.c"
  21. test -f "$PATCH" || { echo "Missing Samsung min_kdp patch: $PATCH" >&2; exit 1; }
  22. test -f "$MIN_KDP" || { echo "Missing Samsung min_kdp source: $MIN_KDP" >&2; exit 1; }
  23. SYMBOL_LIST=android/abi_gki_aarch64_galaxy
  24. TRANSACTION_DIR="$(mktemp -d)"
  25. BACKUP_DIR="$TRANSACTION_DIR/original"
  26. STAGE_DIR="$TRANSACTION_DIR/stage"
  27. TRANSACTION_COMMITTED=false
  28. declare -a TRANSACTION_PATHS
  29. TRANSACTION_PATH_COUNT=0
  30. add_transaction_path() {
  31. local path="$1"
  32. case "$path" in
  33. /dev/null|..|../*|*/../*|/*)
  34. echo "Unsafe Samsung patch path: $path" >&2
  35. exit 1
  36. ;;
  37. esac
  38. local index existing
  39. for ((index = 0; index < TRANSACTION_PATH_COUNT; index++)); do
  40. existing="${TRANSACTION_PATHS[index]}"
  41. [ "$existing" = "$path" ] && return
  42. done
  43. TRANSACTION_PATHS[TRANSACTION_PATH_COUNT]="$path"
  44. TRANSACTION_PATH_COUNT=$((TRANSACTION_PATH_COUNT + 1))
  45. }
  46. restore_transaction() {
  47. set +e
  48. set +u
  49. if [ "$TRANSACTION_COMMITTED" = true ]; then
  50. rm -rf "$TRANSACTION_DIR"
  51. return
  52. fi
  53. local index path
  54. for ((index = 0; index < TRANSACTION_PATH_COUNT; index++)); do
  55. path="${TRANSACTION_PATHS[index]}"
  56. if [[ -e "$BACKUP_DIR/$path" || -L "$BACKUP_DIR/$path" ]]; then
  57. rm -rf "$path"
  58. mkdir -p "$(dirname "$path")"
  59. cp -a "$BACKUP_DIR/$path" "$path"
  60. else
  61. rm -rf "$path"
  62. fi
  63. done
  64. rm -rf "$TRANSACTION_DIR"
  65. }
  66. trap restore_transaction EXIT
  67. PATCH_PATHS=()
  68. while IFS= read -r path; do
  69. [ -n "$path" ] && PATCH_PATHS+=("$path")
  70. done < <(awk '/^(---|\+\+\+) / { path=$2; sub(/^[ab]\//, "", path); print path }' "$PATCH" | sort -u)
  71. for path in "${PATCH_PATHS[@]}"; do
  72. add_transaction_path "$path"
  73. done
  74. add_transaction_path "$SYMBOL_LIST"
  75. add_transaction_path drivers/min_kdp.c
  76. add_transaction_path drivers/Makefile
  77. for path in "${TRANSACTION_PATHS[@]}"; do
  78. if [[ -e "$path" || -L "$path" ]]; then
  79. mkdir -p "$BACKUP_DIR/$(dirname "$path")" "$STAGE_DIR/$(dirname "$path")"
  80. cp -a "$path" "$BACKUP_DIR/$path"
  81. cp -a "$path" "$STAGE_DIR/$path"
  82. else
  83. mkdir -p "$STAGE_DIR/$(dirname "$path")"
  84. fi
  85. done
  86. (
  87. cd "$STAGE_DIR"
  88. if patch -p1 --dry-run < "$PATCH" 2>/dev/null; then
  89. patch -p1 --no-backup-if-mismatch < "$PATCH"
  90. else
  91. echo "Rigid .stg patch failed (upstream drift), falling back to idempotent insert"
  92. python3 - android/abi_gki_aarch64.stg <<'PYEOF'
  93. import sys
  94. stg_path = sys.argv[1]
  95. with open(stg_path) as f:
  96. src = f.read()
  97. def ensure_before(anchor, block, label):
  98. global src
  99. if label in src:
  100. print(f"already present: {label}")
  101. return
  102. if anchor in src:
  103. src = src.replace(anchor, block + anchor, 1)
  104. print(f"inserted {label} at anchor")
  105. else:
  106. # STG text format is order-insensitive: append as last resort
  107. if not src.endswith('\n'):
  108. src += '\n'
  109. src += block
  110. print(f"inserted {label} at EOF (anchor missing)")
  111. func1 = ('function {\n id: 0x1e5195df\n return_type_id: 0x48b5725f\n'
  112. ' parameter_id: 0x3d551c03\n parameter_id: 0x6720d32f\n}\n')
  113. func2 = ('function {\n id: 0xc18e39fb\n return_type_id: 0x4585663f\n'
  114. ' parameter_id: 0x3d551c03\n}\n')
  115. elf1 = ('elf_symbol {\n id: 0xb0801f6e\n name: "kdp_set_cred_non_rcu"\n is_defined: true\n'
  116. ' symbol_type: FUNCTION\n crc: 0x738bae5e\n type_id: 0x1e5195df\n'
  117. ' full_name: "kdp_set_cred_non_rcu"\n}\n')
  118. elf2 = ('elf_symbol {\n id: 0x3037c5bc\n name: "kdp_usecount_dec_and_test"\n is_defined: true\n'
  119. ' symbol_type: FUNCTION\n crc: 0xda582aa5\n type_id: 0xc18e39fb\n'
  120. ' full_name: "kdp_usecount_dec_and_test"\n}\n')
  121. elf3 = ('elf_symbol {\n id: 0x8334a496\n name: "kdp_usecount_inc"\n is_defined: true\n'
  122. ' symbol_type: FUNCTION\n crc: 0xfb342499\n type_id: 0x1fcd1693\n'
  123. ' full_name: "kdp_usecount_inc"\n}\n')
  124. ensure_before('function {\n id: 0x1e571002', func1, 'id: 0x1e5195df')
  125. ensure_before('function {\n id: 0xc18f1240', func2, 'id: 0xc18e39fb')
  126. elf_anchor = 'elf_symbol {\n id: 0x493ce9fc\n name: "loops_per_jiffy"'
  127. for block, label in [(elf1, '"kdp_set_cred_non_rcu"'), (elf2, '"kdp_usecount_dec_and_test"'), (elf3, '"kdp_usecount_inc"')]:
  128. ensure_before(elf_anchor, block, label)
  129. # interface symbol_ids must land inside the interface block
  130. iface_ids = ['0xb0801f6e', '0x3037c5bc', '0x8334a496']
  131. missing = [i for i in iface_ids if f'symbol_id: {i}' not in src]
  132. if missing:
  133. lines = [f' symbol_id: {i}\n' for i in missing]
  134. # 0xc750a072 exists in all snapshots (incl. 2024-09 where
  135. # 0x132eb5f1 is missing upstream); insert right after it.
  136. anchor = ' symbol_id: 0xc750a072\n'
  137. if anchor in src:
  138. src = src.replace(anchor, anchor + ''.join(lines), 1)
  139. print(f"inserted interface ids after 0xc750a072: {missing}")
  140. else:
  141. idx = src.find('interface {')
  142. assert idx != -1, 'interface block not found in .stg'
  143. end = src.find('\n}\n', idx)
  144. assert end != -1, 'interface block close not found'
  145. src = src[:end] + ''.join(lines).rstrip('\n') + src[end:]
  146. print(f"inserted interface ids before interface close: {missing}")
  147. else:
  148. print('interface ids already present')
  149. with open(stg_path, 'w') as f:
  150. f.write(src)
  151. print('fallback .stg insert done')
  152. PYEOF
  153. fi
  154. printf '%s\n' \
  155. 'kdp_set_cred_non_rcu' \
  156. 'kdp_usecount_dec_and_test' \
  157. 'kdp_usecount_inc' >> "$SYMBOL_LIST"
  158. cp "$MIN_KDP" drivers/min_kdp.c
  159. if ! grep -Fqx 'obj-y += min_kdp.o' drivers/Makefile; then
  160. printf '%s\n' 'obj-y += min_kdp.o' >> drivers/Makefile
  161. fi
  162. )
  163. for path in "${TRANSACTION_PATHS[@]}"; do
  164. if [[ -e "$STAGE_DIR/$path" || -L "$STAGE_DIR/$path" ]]; then
  165. mkdir -p "$(dirname "$path")"
  166. rm -rf "$path"
  167. cp -a "$STAGE_DIR/$path" "$path"
  168. else
  169. rm -rf "$path"
  170. fi
  171. done
  172. TRANSACTION_COMMITTED=true
  173. - name: Fix WiFi and Bluetooth on Xiaomi 6.6 GKI Devices
  174. if: inputs.version == 'android15-6.6'
  175. shell: bash
  176. working-directory: ${{ github.workspace }}/kernel/common
  177. run: |
  178. SYMBOL_LIST=android/abi_gki_aarch64_xiaomi
  179. echo "device_find_any_child" >> $SYMBOL_LIST